🧹 clean up duty 🧹
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -4,7 +4,6 @@
|
|||||||
},
|
},
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }],
|
|
||||||
"eslint.workingDirectories": [
|
"eslint.workingDirectories": [
|
||||||
{ "pattern": "apps/*/" },
|
{ "pattern": "apps/*/" },
|
||||||
{ "pattern": "packages/*/" },
|
{ "pattern": "packages/*/" },
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# openpanel
|
# Openpanel
|
||||||
|
|
||||||
Openpanel is a simple analytics tool for logging events on web and react-native. My goal is to make a minimal mixpanel copy with the most basic features (for now).
|
Openpanel is a simple analytics tool for logging events on web and react-native. My goal is to make a minimal mixpanel copy with the most basic features (for now).
|
||||||
|
|
||||||
|
|||||||
@@ -1,224 +0,0 @@
|
|||||||
import { omit, prop, uniqBy } from 'ramda';
|
|
||||||
|
|
||||||
import { generateProfileId, getTime, toISOString } from '@openpanel/common';
|
|
||||||
import type { Event, IServiceCreateEventPayload } from '@openpanel/db';
|
|
||||||
import {
|
|
||||||
createEvent as createClickhouseEvent,
|
|
||||||
db,
|
|
||||||
formatClickhouseDate,
|
|
||||||
getSalts,
|
|
||||||
} from '@openpanel/db';
|
|
||||||
|
|
||||||
import { parseIp } from '../src/utils/parseIp';
|
|
||||||
import { parseUserAgent } from '../src/utils/parseUserAgent';
|
|
||||||
|
|
||||||
const clean = omit([
|
|
||||||
'ip',
|
|
||||||
'os',
|
|
||||||
'ua',
|
|
||||||
'url',
|
|
||||||
'hash',
|
|
||||||
'host',
|
|
||||||
'path',
|
|
||||||
'device',
|
|
||||||
'screen',
|
|
||||||
'hostname',
|
|
||||||
'language',
|
|
||||||
'referrer',
|
|
||||||
'timezone',
|
|
||||||
]);
|
|
||||||
async function main() {
|
|
||||||
const events = await db.event.findMany({
|
|
||||||
where: {
|
|
||||||
project_id: '4e2798cb-e255-4e9d-960d-c9ad095aabd7',
|
|
||||||
name: 'screen_view',
|
|
||||||
createdAt: {
|
|
||||||
gte: new Date('2024-01-01'),
|
|
||||||
lt: new Date('2024-02-04'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'asc',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const grouped: Record<string, Event[]> = {};
|
|
||||||
let index = 0;
|
|
||||||
for (const event of events.slice()) {
|
|
||||||
// console.log(index, event.name, event.createdAt.toISOString());
|
|
||||||
index++;
|
|
||||||
|
|
||||||
const properties = event.properties as Record<string, any>;
|
|
||||||
|
|
||||||
if (properties.ua?.includes('bot')) {
|
|
||||||
// console.log('IGNORE', event.id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!event.profile_id) {
|
|
||||||
// console.log('IGNORE', event.id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const hej = grouped[event.profile_id];
|
|
||||||
if (hej) {
|
|
||||||
hej.push(event);
|
|
||||||
} else {
|
|
||||||
grouped[event.profile_id] = [event];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Total users', Object.keys(grouped).length);
|
|
||||||
|
|
||||||
let uidx = -1;
|
|
||||||
for (const profile_id of Object.keys(grouped)) {
|
|
||||||
uidx++;
|
|
||||||
console.log(`User index ${uidx}`);
|
|
||||||
|
|
||||||
const events = uniqBy(prop('createdAt'), grouped[profile_id] || []);
|
|
||||||
|
|
||||||
if (events) {
|
|
||||||
let lastSessionStart = null;
|
|
||||||
let screenViews = 0;
|
|
||||||
let totalDuration = 0;
|
|
||||||
console.log('new user...');
|
|
||||||
let eidx = -1;
|
|
||||||
for (const event of events) {
|
|
||||||
eidx++;
|
|
||||||
const prevEvent = events[eidx - 1];
|
|
||||||
const prevEventAt = prevEvent?.createdAt;
|
|
||||||
|
|
||||||
const nextEvent = events[eidx + 1];
|
|
||||||
|
|
||||||
const properties = event.properties as Record<string, any>;
|
|
||||||
const projectId = event.project_id;
|
|
||||||
const path = properties.path!;
|
|
||||||
const ip = properties.ip!;
|
|
||||||
const origin = 'https://openpanel.kiddo.se';
|
|
||||||
const ua = properties.ua!;
|
|
||||||
const uaInfo = parseUserAgent(ua);
|
|
||||||
const salts = await getSalts();
|
|
||||||
const profileId = generateProfileId({
|
|
||||||
salt: salts.current,
|
|
||||||
origin,
|
|
||||||
ip,
|
|
||||||
ua,
|
|
||||||
});
|
|
||||||
|
|
||||||
const geo = parseIp(ip);
|
|
||||||
|
|
||||||
const isNextEventNewSession =
|
|
||||||
nextEvent &&
|
|
||||||
nextEvent.createdAt.getTime() - event.createdAt.getTime() >
|
|
||||||
1000 * 60 * 30;
|
|
||||||
|
|
||||||
const payload: IServiceCreateEventPayload = {
|
|
||||||
name: event.name,
|
|
||||||
profileId,
|
|
||||||
projectId,
|
|
||||||
properties: clean(properties),
|
|
||||||
createdAt: event.createdAt.toISOString(),
|
|
||||||
country: geo.country,
|
|
||||||
city: geo.city,
|
|
||||||
region: geo.region,
|
|
||||||
continent: geo.continent,
|
|
||||||
os: uaInfo.os,
|
|
||||||
osVersion: uaInfo.osVersion,
|
|
||||||
browser: uaInfo.browser,
|
|
||||||
browserVersion: uaInfo.browserVersion,
|
|
||||||
device: uaInfo.device,
|
|
||||||
brand: uaInfo.brand,
|
|
||||||
model: uaInfo.model,
|
|
||||||
duration:
|
|
||||||
nextEvent && !isNextEventNewSession
|
|
||||||
? nextEvent.createdAt.getTime() - event.createdAt.getTime()
|
|
||||||
: 0,
|
|
||||||
path,
|
|
||||||
referrer: properties?.referrer?.host ?? '', // TODO
|
|
||||||
referrerName: properties?.referrer?.host ?? '', // TODO
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!prevEventAt) {
|
|
||||||
lastSessionStart = await createSessionStart(payload);
|
|
||||||
} else if (
|
|
||||||
event.createdAt.getTime() - prevEventAt.getTime() >
|
|
||||||
1000 * 60 * 30
|
|
||||||
) {
|
|
||||||
if (eidx > 0 && prevEventAt && lastSessionStart) {
|
|
||||||
await createSessionEnd(prevEventAt, lastSessionStart, {
|
|
||||||
screenViews,
|
|
||||||
totalDuration,
|
|
||||||
});
|
|
||||||
totalDuration = 0;
|
|
||||||
screenViews = 0;
|
|
||||||
lastSessionStart = await createSessionStart(payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
screenViews++;
|
|
||||||
totalDuration += payload.duration;
|
|
||||||
await createEvent(payload);
|
|
||||||
} // for each user event
|
|
||||||
|
|
||||||
const prevEventAt = events[events.length - 1]?.createdAt;
|
|
||||||
if (prevEventAt && lastSessionStart) {
|
|
||||||
await createSessionEnd(prevEventAt, lastSessionStart, {
|
|
||||||
screenViews,
|
|
||||||
totalDuration,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createEvent(event: IServiceCreateEventPayload) {
|
|
||||||
console.log(
|
|
||||||
`Create ${event.name} - ${event.path} - ${formatClickhouseDate(
|
|
||||||
event.createdAt
|
|
||||||
)} - ${event.duration / 1000} sec`
|
|
||||||
);
|
|
||||||
await createClickhouseEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createSessionStart(event: IServiceCreateEventPayload) {
|
|
||||||
const session: IServiceCreateEventPayload = {
|
|
||||||
...event,
|
|
||||||
duration: 0,
|
|
||||||
name: 'session_start',
|
|
||||||
createdAt: toISOString(getTime(event.createdAt) - 100),
|
|
||||||
};
|
|
||||||
|
|
||||||
await createEvent(session);
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createSessionEnd(
|
|
||||||
prevEventAt: Date,
|
|
||||||
sessionStart: IServiceCreateEventPayload,
|
|
||||||
options: {
|
|
||||||
screenViews: number;
|
|
||||||
totalDuration: number;
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
const properties: Record<string, unknown> = {};
|
|
||||||
if (options.screenViews === 1) {
|
|
||||||
properties.__bounce = true;
|
|
||||||
} else {
|
|
||||||
properties.__bounce = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const session: IServiceCreateEventPayload = {
|
|
||||||
...sessionStart,
|
|
||||||
properties: {
|
|
||||||
...properties,
|
|
||||||
...sessionStart.properties,
|
|
||||||
},
|
|
||||||
duration: options.totalDuration,
|
|
||||||
name: 'session_end',
|
|
||||||
createdAt: toISOString(prevEventAt.getTime() + 10),
|
|
||||||
};
|
|
||||||
|
|
||||||
await createEvent(session);
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
//@ts-nocheck
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const crypto = require('crypto');
|
|
||||||
|
|
||||||
function createHash(data, len) {
|
|
||||||
return crypto
|
|
||||||
.createHash('shake256', { outputLength: len })
|
|
||||||
.update(data)
|
|
||||||
.digest('hex');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(createHash('foo', 2));
|
|
||||||
// 1af9
|
|
||||||
console.log(createHash('foo', 32));
|
|
||||||
// 1af97f7818a28edf}
|
|
||||||
}
|
|
||||||
main();
|
|
||||||
@@ -18,7 +18,7 @@ import type { PostEventPayload } from '@openpanel/sdk';
|
|||||||
const SESSION_TIMEOUT = 1000 * 60 * 30;
|
const SESSION_TIMEOUT = 1000 * 60 * 30;
|
||||||
const SESSION_END_TIMEOUT = SESSION_TIMEOUT + 1000;
|
const SESSION_END_TIMEOUT = SESSION_TIMEOUT + 1000;
|
||||||
|
|
||||||
async function withTiming<T>(name: string, promise: T) {
|
async function withTiming<T>(name: string, promise: Promise<T>) {
|
||||||
try {
|
try {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
const res = await promise;
|
const res = await promise;
|
||||||
|
|||||||
@@ -8,5 +8,5 @@
|
|||||||
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
|
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
|
||||||
},
|
},
|
||||||
"include": ["."],
|
"include": ["."],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules", "dist"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleErrorToastOptions } from '@/app/_trpc/client';
|
|
||||||
import { Card, CardActions, CardActionsItem } from '@/components/card';
|
import { Card, CardActions, CardActionsItem } from '@/components/card';
|
||||||
import { FullPageEmptyState } from '@/components/full-page-empty-state';
|
import { FullPageEmptyState } from '@/components/full-page-empty-state';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
import { pushModal } from '@/modals';
|
import { pushModal } from '@/modals';
|
||||||
|
import { api, handleErrorToastOptions } from '@/trpc/client';
|
||||||
import { LayoutPanelTopIcon, Pencil, PlusIcon, Trash } from 'lucide-react';
|
import { LayoutPanelTopIcon, Pencil, PlusIcon, Trash } from 'lucide-react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ export function EventDetails({ event, open, setOpen }: Props) {
|
|||||||
key={item.name}
|
key={item.name}
|
||||||
name={item.name}
|
name={item.name}
|
||||||
value={item.value}
|
value={item.value}
|
||||||
onClick={item.onClick}
|
onClick={() => item.onClick?.()}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -225,7 +225,7 @@ export function EventDetails({ event, open, setOpen }: Props) {
|
|||||||
className="w-full"
|
className="w-full"
|
||||||
onClick={() => setIsEditOpen(true)}
|
onClick={() => setIsEditOpen(true)}
|
||||||
>
|
>
|
||||||
Customize "{name}"
|
Customize "{name}"
|
||||||
</Button>
|
</Button>
|
||||||
</SheetFooter>
|
</SheetFooter>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type { Dispatch, SetStateAction } from 'react';
|
import type { Dispatch, SetStateAction } from 'react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
@@ -11,6 +10,7 @@ import {
|
|||||||
SheetHeader,
|
SheetHeader,
|
||||||
SheetTitle,
|
SheetTitle,
|
||||||
} from '@/components/ui/sheet';
|
} from '@/components/ui/sheet';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
@@ -78,7 +78,7 @@ export function EventEdit({ event, open, setOpen }: Props) {
|
|||||||
<Sheet open={open} onOpenChange={setOpen}>
|
<Sheet open={open} onOpenChange={setOpen}>
|
||||||
<SheetContent>
|
<SheetContent>
|
||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
<SheetTitle>Edit "{name}"</SheetTitle>
|
<SheetTitle>Edit "{name}"</SheetTitle>
|
||||||
</SheetHeader>
|
</SheetHeader>
|
||||||
<div className="my-8 flex flex-col gap-8">
|
<div className="my-8 flex flex-col gap-8">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
@@ -12,6 +11,7 @@ import {
|
|||||||
SheetTrigger,
|
SheetTrigger,
|
||||||
} from '@/components/ui/sheet';
|
} from '@/components/ui/sheet';
|
||||||
import { Tooltip, TooltipContent } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent } from '@/components/ui/tooltip';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import { TooltipTrigger } from '@radix-ui/react-tooltip';
|
import { TooltipTrigger } from '@radix-ui/react-tooltip';
|
||||||
import type { VariantProps } from 'class-variance-authority';
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export default function LayoutOrganizationSelector({
|
|||||||
.filter((item) => item.slug)
|
.filter((item) => item.slug)
|
||||||
.map((item) => ({
|
.map((item) => ({
|
||||||
label: item.name,
|
label: item.name,
|
||||||
value: item.slug!,
|
value: item.slug,
|
||||||
})) ?? []
|
})) ?? []
|
||||||
}
|
}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Widget, WidgetBody, WidgetHead } from '@/components/widget';
|
import { Widget, WidgetBody, WidgetHead } from '@/components/widget';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
|
import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
|
||||||
@@ -15,6 +14,7 @@ import {
|
|||||||
SheetTrigger,
|
SheetTrigger,
|
||||||
} from '@/components/ui/sheet';
|
} from '@/components/ui/sheet';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { PlusIcon, SendIcon } from 'lucide-react';
|
import { PlusIcon, SendIcon } from 'lucide-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
|
import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@@ -12,6 +11,7 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
} from '@/components/ui/table';
|
} from '@/components/ui/table';
|
||||||
import { Widget, WidgetHead } from '@/components/widget';
|
import { Widget, WidgetHead } from '@/components/widget';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
|
|
||||||
import type { IServiceMember, IServiceProject } from '@openpanel/db';
|
import type { IServiceMember, IServiceProject } from '@openpanel/db';
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Widget, WidgetBody, WidgetHead } from '@/components/widget';
|
import { Widget, WidgetBody, WidgetHead } from '@/components/widget';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Button } from '@/components/ui/button';
|
|||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { SaveIcon } from 'lucide-react';
|
import { SaveIcon } from 'lucide-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -13,8 +14,6 @@ import { useForm } from 'react-hook-form';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { api, handleError } from '../../_trpc/client';
|
|
||||||
|
|
||||||
const validation = z.object({
|
const validation = z.object({
|
||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { notFound, redirect } from 'next/navigation';
|
|||||||
import {
|
import {
|
||||||
getCurrentProjects,
|
getCurrentProjects,
|
||||||
getOrganizationBySlug,
|
getOrganizationBySlug,
|
||||||
getProjectsByOrganizationSlug,
|
|
||||||
isWaitlistUserAccepted,
|
isWaitlistUserAccepted,
|
||||||
} from '@openpanel/db';
|
} from '@openpanel/db';
|
||||||
|
|
||||||
@@ -36,8 +35,8 @@ export default async function Page({ params: { organizationId } }: PageProps) {
|
|||||||
<LogoSquare className="mb-8 w-20 md:w-28" />
|
<LogoSquare className="mb-8 w-20 md:w-28" />
|
||||||
<h1 className="text-3xl font-medium">Not quite there yet</h1>
|
<h1 className="text-3xl font-medium">Not quite there yet</h1>
|
||||||
<div className="text-lg">
|
<div className="text-lg">
|
||||||
We're still working on Openpanel, but we're not quite there yet.
|
We're still working on Openpanel, but we're not quite
|
||||||
We'll let you know when we're ready to go!
|
there yet. We'll let you know when we're ready to go!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Button, buttonVariants } from '@/components/ui/button';
|
|||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { SaveIcon, WallpaperIcon } from 'lucide-react';
|
import { SaveIcon, WallpaperIcon } from 'lucide-react';
|
||||||
@@ -14,8 +15,6 @@ import type { SubmitHandler } from 'react-hook-form';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { api, handleError } from '../_trpc/client';
|
|
||||||
|
|
||||||
const validation = z
|
const validation = z
|
||||||
.object({
|
.object({
|
||||||
organization: z.string().min(3),
|
organization: z.string().min(3),
|
||||||
@@ -61,8 +60,8 @@ export function CreateOrganization() {
|
|||||||
<LogoSquare className="mb-4 w-20" />
|
<LogoSquare className="mb-4 w-20" />
|
||||||
<h1 className="text-3xl font-medium">Nice job!</h1>
|
<h1 className="text-3xl font-medium">Nice job!</h1>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
You're ready to start using our SDK. Save the client ID and secret (if
|
You're ready to start using our SDK. Save the client ID and
|
||||||
you have any)
|
secret (if you have any)
|
||||||
</div>
|
</div>
|
||||||
<CreateClientSuccess {...mutation.data.client} />
|
<CreateClientSuccess {...mutation.data.client} />
|
||||||
<div className="mt-4 flex gap-4">
|
<div className="mt-4 flex gap-4">
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ export default async function Page() {
|
|||||||
<LogoSquare className="mb-8 w-20 md:w-28" />
|
<LogoSquare className="mb-8 w-20 md:w-28" />
|
||||||
<h1 className="text-3xl font-medium">Not quite there yet</h1>
|
<h1 className="text-3xl font-medium">Not quite there yet</h1>
|
||||||
<div className="text-lg">
|
<div className="text-lg">
|
||||||
We're still working on Openpanel, but we're not quite there yet.
|
We're still working on Openpanel, but we're not quite
|
||||||
We'll let you know when we're ready to go!
|
there yet. We'll let you know when we're ready to go!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,6 +32,6 @@ export async function POST(request: Request) {
|
|||||||
return Response.json({ message: 'Webhook received!' });
|
return Response.json({ message: 'Webhook received!' });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GET() {
|
export function GET() {
|
||||||
return Response.json({ message: 'Hello World!' });
|
return Response.json({ message: 'Hello World!' });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { appRouter } from '@/server/api/root';
|
import { appRouter } from '@/trpc/api/root';
|
||||||
import { getAuth } from '@clerk/nextjs/server';
|
import { getAuth } from '@clerk/nextjs/server';
|
||||||
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
|
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ const handler = (req: Request) =>
|
|||||||
endpoint: '/api/trpc',
|
endpoint: '/api/trpc',
|
||||||
req,
|
req,
|
||||||
router: appRouter,
|
router: appRouter,
|
||||||
async createContext({ req }) {
|
createContext({ req }) {
|
||||||
const session = getAuth(req as any);
|
const session = getAuth(req as any);
|
||||||
return {
|
return {
|
||||||
session,
|
session,
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import * as Sentry from "@sentry/nextjs";
|
|
||||||
import Error from "next/error";
|
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
export default function GlobalError({ error }) {
|
|
||||||
useEffect(() => {
|
|
||||||
Sentry.captureException(error);
|
|
||||||
}, [error]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<Error />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
23
apps/dashboard/src/app/global-error.tsx
Normal file
23
apps/dashboard/src/app/global-error.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import * as Sentry from '@sentry/nextjs';
|
||||||
|
|
||||||
|
export default function GlobalError({
|
||||||
|
error,
|
||||||
|
}: {
|
||||||
|
error: Error & { digest?: string };
|
||||||
|
reset: () => void;
|
||||||
|
}) {
|
||||||
|
useEffect(() => {
|
||||||
|
Sentry.captureException(error);
|
||||||
|
}, [error]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<body>
|
||||||
|
<h1>Something went wrong</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { TooltipProvider } from '@/components/ui/tooltip';
|
import { TooltipProvider } from '@/components/ui/tooltip';
|
||||||
import { ModalProvider } from '@/modals';
|
import { ModalProvider } from '@/modals';
|
||||||
import type { AppStore } from '@/redux';
|
import type { AppStore } from '@/redux';
|
||||||
import makeStore from '@/redux';
|
import makeStore from '@/redux';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { ClerkProvider, useAuth } from '@clerk/nextjs';
|
import { ClerkProvider, useAuth } from '@clerk/nextjs';
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
import { httpLink } from '@trpc/client';
|
import { httpLink } from '@trpc/client';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { pushModal, showConfirm } from '@/modals';
|
import { pushModal, showConfirm } from '@/modals';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { clipboard } from '@/utils/clipboard';
|
import { clipboard } from '@/utils/clipboard';
|
||||||
import { MoreHorizontal } from 'lucide-react';
|
import { MoreHorizontal } from 'lucide-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|||||||
@@ -11,13 +11,17 @@ import {
|
|||||||
import { MoonIcon, SunIcon } from 'lucide-react';
|
import { MoonIcon, SunIcon } from 'lucide-react';
|
||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
|
|
||||||
export default function DarkModeToggle() {
|
interface Props {
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DarkModeToggle({ className }: Props) {
|
||||||
const { setTheme } = useTheme();
|
const { setTheme } = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="outline" size="icon">
|
<Button variant="outline" size="icon" className={className}>
|
||||||
<SunIcon className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
<SunIcon className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||||
<MoonIcon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
<MoonIcon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||||
<span className="sr-only">Toggle theme</span>
|
<span className="sr-only">Toggle theme</span>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react';
|
||||||
import { api } from '@/app/_trpc/client';
|
import { api } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import AnimateHeight from 'react-animate-height';
|
import AnimateHeight from 'react-animate-height';
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ export function OverviewLiveHistogram({
|
|||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="top">
|
<TooltipContent side="top">
|
||||||
<div>{minute.count} active users</div>
|
<div>{minute.count} active users</div>
|
||||||
<div>@ {new Date(minute.date).toLocaleTimeString()}</div>
|
<div>@ {new Date(minute.date).toLocaleTimeString()}</div>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { pushModal } from '@/modals';
|
import { pushModal } from '@/modals';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { EyeIcon, Globe2Icon, LockIcon } from 'lucide-react';
|
import { EyeIcon, Globe2Icon, LockIcon } from 'lucide-react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { pushModal, showConfirm } from '@/modals';
|
import { pushModal, showConfirm } from '@/modals';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { clipboard } from '@/utils/clipboard';
|
import { clipboard } from '@/utils/clipboard';
|
||||||
import { MoreHorizontal } from 'lucide-react';
|
import { MoreHorizontal } from 'lucide-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
import { pushModal } from '@/modals';
|
import { pushModal } from '@/modals';
|
||||||
import { useDispatch, useSelector } from '@/redux';
|
import { useDispatch, useSelector } from '@/redux';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { SaveIcon } from 'lucide-react';
|
import { SaveIcon } from 'lucide-react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api } from '@/app/_trpc/client';
|
import { api } from '@/trpc/client';
|
||||||
|
|
||||||
import type { IChartInput } from '@openpanel/validation';
|
import type { IChartInput } from '@openpanel/validation';
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import airplane from '@/lottie/airplane.json';
|
|
||||||
import ballon from '@/lottie/ballon.json';
|
|
||||||
import noData from '@/lottie/no-data.json';
|
|
||||||
import { cn } from '@/utils/cn';
|
|
||||||
import type { LottieComponentProps } from 'lottie-react';
|
|
||||||
import Lottie from 'lottie-react';
|
|
||||||
|
|
||||||
const animations = {
|
|
||||||
airplane,
|
|
||||||
ballon,
|
|
||||||
noData,
|
|
||||||
};
|
|
||||||
type Animations = keyof typeof animations;
|
|
||||||
|
|
||||||
export const ChartAnimation = ({
|
|
||||||
name,
|
|
||||||
...props
|
|
||||||
}: Omit<LottieComponentProps, 'animationData'> & {
|
|
||||||
name: Animations;
|
|
||||||
}) => <Lottie animationData={animations[name]} loop={true} {...props} />;
|
|
||||||
|
|
||||||
export const ChartAnimationContainer = (
|
|
||||||
props: React.ButtonHTMLAttributes<HTMLDivElement>
|
|
||||||
) => (
|
|
||||||
<div
|
|
||||||
{...props}
|
|
||||||
className={cn(
|
|
||||||
'rounded-md border border-border bg-background p-8',
|
|
||||||
props.className
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
useMemo,
|
useMemo,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import type { IChartSerie } from '@/server/api/routers/chart';
|
import type { IChartSerie } from '@/trpc/api/routers/chart';
|
||||||
|
|
||||||
import type { IChartInput } from '@openpanel/validation';
|
import type { IChartInput } from '@openpanel/validation';
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { ColorSquare } from '@/components/color-square';
|
import { ColorSquare } from '@/components/color-square';
|
||||||
import { fancyMinutes, useNumber } from '@/hooks/useNumerFormatter';
|
import { fancyMinutes, useNumber } from '@/hooks/useNumerFormatter';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { theme } from '@/utils/theme';
|
import { theme } from '@/utils/theme';
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
import { Area, AreaChart } from 'recharts';
|
import { Area, AreaChart } from 'recharts';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
|
import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
|
||||||
import { useNumber } from '@/hooks/useNumerFormatter';
|
import { useNumber } from '@/hooks/useNumerFormatter';
|
||||||
import { useRechartDataModel } from '@/hooks/useRechartDataModel';
|
import { useRechartDataModel } from '@/hooks/useRechartDataModel';
|
||||||
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { getChartColor } from '@/utils/theme';
|
import { getChartColor } from '@/utils/theme';
|
||||||
import {
|
import {
|
||||||
Area,
|
Area,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { Progress } from '@/components/ui/progress';
|
import { Progress } from '@/components/ui/progress';
|
||||||
import { useNumber } from '@/hooks/useNumerFormatter';
|
import { useNumber } from '@/hooks/useNumerFormatter';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import { getChartColor } from '@/utils/theme';
|
import { getChartColor } from '@/utils/theme';
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
|
import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
|
||||||
import { useNumber } from '@/hooks/useNumerFormatter';
|
import { useNumber } from '@/hooks/useNumerFormatter';
|
||||||
import { useRechartDataModel } from '@/hooks/useRechartDataModel';
|
import { useRechartDataModel } from '@/hooks/useRechartDataModel';
|
||||||
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { getChartColor, theme } from '@/utils/theme';
|
import { getChartColor, theme } from '@/utils/theme';
|
||||||
import { Bar, BarChart, CartesianGrid, Tooltip, XAxis, YAxis } from 'recharts';
|
import { Bar, BarChart, CartesianGrid, Tooltip, XAxis, YAxis } from 'recharts';
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
|
import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
|
||||||
import { useNumber } from '@/hooks/useNumerFormatter';
|
import { useNumber } from '@/hooks/useNumerFormatter';
|
||||||
import { useRechartDataModel } from '@/hooks/useRechartDataModel';
|
import { useRechartDataModel } from '@/hooks/useRechartDataModel';
|
||||||
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { getChartColor } from '@/utils/theme';
|
import { getChartColor } from '@/utils/theme';
|
||||||
import {
|
import {
|
||||||
CartesianGrid,
|
CartesianGrid,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { theme } from '@/utils/theme';
|
import { theme } from '@/utils/theme';
|
||||||
import WorldMap from 'react-svg-worldmap';
|
import WorldMap from 'react-svg-worldmap';
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
|
|
||||||
import { useChartContext } from './ChartProvider';
|
import { useChartContext } from './ChartProvider';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { AutoSizer } from '@/components/react-virtualized-auto-sizer';
|
import { AutoSizer } from '@/components/react-virtualized-auto-sizer';
|
||||||
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
import { useVisibleSeries } from '@/hooks/useVisibleSeries';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import { round } from '@/utils/math';
|
import { round } from '@/utils/math';
|
||||||
import { getChartColor } from '@/utils/theme';
|
import { getChartColor } from '@/utils/theme';
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
|
||||||
import { Pagination, usePagination } from '@/components/pagination';
|
import { Pagination, usePagination } from '@/components/pagination';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
@@ -20,6 +19,7 @@ import { useFormatDateInterval } from '@/hooks/useFormatDateInterval';
|
|||||||
import { useMappings } from '@/hooks/useMappings';
|
import { useMappings } from '@/hooks/useMappings';
|
||||||
import { useNumber } from '@/hooks/useNumerFormatter';
|
import { useNumber } from '@/hooks/useNumerFormatter';
|
||||||
import { useSelector } from '@/redux';
|
import { useSelector } from '@/redux';
|
||||||
|
import type { IChartData } from '@/trpc/client';
|
||||||
import { getChartColor } from '@/utils/theme';
|
import { getChartColor } from '@/utils/theme';
|
||||||
|
|
||||||
import { PreviousDiffIndicator } from '../PreviousDiffIndicator';
|
import { PreviousDiffIndicator } from '../PreviousDiffIndicator';
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { RouterOutputs } from '@/app/_trpc/client';
|
|
||||||
import {
|
import {
|
||||||
Carousel,
|
Carousel,
|
||||||
CarouselContent,
|
CarouselContent,
|
||||||
@@ -8,6 +7,7 @@ import {
|
|||||||
CarouselNext,
|
CarouselNext,
|
||||||
CarouselPrevious,
|
CarouselPrevious,
|
||||||
} from '@/components/ui/carousel';
|
} from '@/components/ui/carousel';
|
||||||
|
import type { RouterOutputs } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import { round } from '@/utils/math';
|
import { round } from '@/utils/math';
|
||||||
import { ArrowRight, ArrowRightIcon } from 'lucide-react';
|
import { ArrowRight, ArrowRightIcon } from 'lucide-react';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { RouterOutputs } from '@/app/_trpc/client';
|
import type { RouterOutputs } from '@/trpc/client';
|
||||||
import { api } from '@/app/_trpc/client';
|
import { api } from '@/trpc/client';
|
||||||
|
|
||||||
import type { IChartInput } from '@openpanel/validation';
|
import type { IChartInput } from '@openpanel/validation';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { Combobox } from '@/components/ui/combobox';
|
import { Combobox } from '@/components/ui/combobox';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
import { useDispatch } from '@/redux';
|
import { useDispatch } from '@/redux';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import { DatabaseIcon } from 'lucide-react';
|
import { DatabaseIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { ColorSquare } from '@/components/color-square';
|
import { ColorSquare } from '@/components/color-square';
|
||||||
import { Combobox } from '@/components/ui/combobox';
|
import { Combobox } from '@/components/ui/combobox';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
import { useDispatch, useSelector } from '@/redux';
|
import { useDispatch, useSelector } from '@/redux';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { SplitIcon } from 'lucide-react';
|
import { SplitIcon } from 'lucide-react';
|
||||||
|
|
||||||
import type { IChartBreakdown } from '@openpanel/validation';
|
import type { IChartBreakdown } from '@openpanel/validation';
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { ColorSquare } from '@/components/color-square';
|
import { ColorSquare } from '@/components/color-square';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
|
import { ComboboxAdvanced } from '@/components/ui/combobox-advanced';
|
||||||
@@ -7,6 +6,7 @@ import { RenderDots } from '@/components/ui/RenderDots';
|
|||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
import { useMappings } from '@/hooks/useMappings';
|
import { useMappings } from '@/hooks/useMappings';
|
||||||
import { useDispatch } from '@/redux';
|
import { useDispatch } from '@/redux';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { SlidersHorizontal, Trash } from 'lucide-react';
|
import { SlidersHorizontal, Trash } from 'lucide-react';
|
||||||
|
|
||||||
import { operators } from '@openpanel/constants';
|
import { operators } from '@openpanel/constants';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
|
||||||
import { Combobox } from '@/components/ui/combobox';
|
import { Combobox } from '@/components/ui/combobox';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
import { useDispatch } from '@/redux';
|
import { useDispatch } from '@/redux';
|
||||||
|
import { api } from '@/trpc/client';
|
||||||
import { FilterIcon } from 'lucide-react';
|
import { FilterIcon } from 'lucide-react';
|
||||||
|
|
||||||
import type { IChartEvent } from '@openpanel/validation';
|
import type { IChartEvent } from '@openpanel/validation';
|
||||||
|
|||||||
@@ -35,12 +35,14 @@ Alert.displayName = 'Alert';
|
|||||||
const AlertTitle = React.forwardRef<
|
const AlertTitle = React.forwardRef<
|
||||||
HTMLParagraphElement,
|
HTMLParagraphElement,
|
||||||
React.HTMLAttributes<HTMLHeadingElement>
|
React.HTMLAttributes<HTMLHeadingElement>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, children, ...props }, ref) => (
|
||||||
<h5
|
<h5
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn('mb-1 font-medium leading-none tracking-tight', className)}
|
className={cn('mb-1 font-medium leading-none tracking-tight', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
>
|
||||||
|
{children}
|
||||||
|
</h5>
|
||||||
));
|
));
|
||||||
AlertTitle.displayName = 'AlertTitle';
|
AlertTitle.displayName = 'AlertTitle';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
||||||
import { cva, type VariantProps } from 'class-variance-authority';
|
import { cva } from 'class-variance-authority';
|
||||||
|
import type { VariantProps } from 'class-variance-authority';
|
||||||
|
|
||||||
const toggleVariants = cva(
|
const toggleVariants = cva(
|
||||||
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
|
'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
import { api } from '@/trpc/client';
|
||||||
|
|
||||||
export function useEventNames(projectId: string) {
|
export function useEventNames(projectId: string) {
|
||||||
const query = api.chart.events.useQuery({
|
const query = api.chart.events.useQuery({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
import { api } from '@/trpc/client';
|
||||||
|
|
||||||
export function useEventProperties(projectId: string, event?: string) {
|
export function useEventProperties(projectId: string, event?: string) {
|
||||||
const query = api.chart.properties.useQuery({
|
const query = api.chart.properties.useQuery({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
import { api } from '@/trpc/client';
|
||||||
|
|
||||||
export function useEventValues(
|
export function useEventValues(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
import { api } from '@/trpc/client';
|
||||||
|
|
||||||
export function useProfileProperties(projectId: string) {
|
export function useProfileProperties(projectId: string) {
|
||||||
const query = api.profile.properties.useQuery({
|
const query = api.profile.properties.useQuery({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { api } from '@/app/_trpc/client';
|
import { api } from '@/trpc/client';
|
||||||
|
|
||||||
export function useProfileValues(projectId: string, property: string) {
|
export function useProfileValues(projectId: string, property: string) {
|
||||||
const query = api.profile.values.useQuery({
|
const query = api.profile.values.useQuery({
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import type { IChartData, IChartSerieDataItem } from '@/app/_trpc/client';
|
import type { IChartData, IChartSerieDataItem } from '@/trpc/client';
|
||||||
import { getChartColor } from '@/utils/theme';
|
import { getChartColor } from '@/utils/theme';
|
||||||
|
|
||||||
export type IRechartPayloadItem = IChartSerieDataItem & { color: string };
|
export type IRechartPayloadItem = IChartSerieDataItem & { color: string };
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import type { IChartData } from '@/app/_trpc/client';
|
import type { IChartData } from '@/trpc/client';
|
||||||
|
|
||||||
export type IVisibleSeries = ReturnType<typeof useVisibleSeries>['series'];
|
export type IVisibleSeries = ReturnType<typeof useVisibleSeries>['series'];
|
||||||
export function useVisibleSeries(data: IChartData, limit?: number | undefined) {
|
export function useVisibleSeries(data: IChartData, limit?: number | undefined) {
|
||||||
|
|||||||
@@ -1,714 +0,0 @@
|
|||||||
{
|
|
||||||
"v": "5.5.8",
|
|
||||||
"fr": 50,
|
|
||||||
"ip": 0,
|
|
||||||
"op": 147,
|
|
||||||
"w": 800,
|
|
||||||
"h": 600,
|
|
||||||
"nm": "Paperplane",
|
|
||||||
"ddd": 0,
|
|
||||||
"assets": [
|
|
||||||
{
|
|
||||||
"id": "comp_0",
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 1,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "planete Outlines - Group 4",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": [0.833], "y": [0.833] },
|
|
||||||
"o": { "x": [0.167], "y": [0.167] },
|
|
||||||
"t": 0,
|
|
||||||
"s": [0]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"i": { "x": [0.833], "y": [0.833] },
|
|
||||||
"o": { "x": [0.167], "y": [0.167] },
|
|
||||||
"t": 38,
|
|
||||||
"s": [50]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"i": { "x": [0.833], "y": [0.833] },
|
|
||||||
"o": { "x": [0.167], "y": [0.167] },
|
|
||||||
"t": 88,
|
|
||||||
"s": [50]
|
|
||||||
},
|
|
||||||
{ "t": 120, "s": [0] }
|
|
||||||
],
|
|
||||||
"ix": 11
|
|
||||||
},
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": 0.833, "y": 0.833 },
|
|
||||||
"o": { "x": 0.167, "y": 0.167 },
|
|
||||||
"t": 0,
|
|
||||||
"s": [468.336, 323.378, 0],
|
|
||||||
"to": [-29, 0, 0],
|
|
||||||
"ti": [29, 0, 0]
|
|
||||||
},
|
|
||||||
{ "t": 102, "s": [294.336, 323.378, 0] }
|
|
||||||
],
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"a": { "a": 0, "k": [453.672, 304.756, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [50, 50, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[6.742, 0],
|
|
||||||
[0.741, -0.14],
|
|
||||||
[0, 0.074],
|
|
||||||
[13.484, 0],
|
|
||||||
[1.669, -0.361],
|
|
||||||
[19.79, 0],
|
|
||||||
[3.317, -19.082],
|
|
||||||
[2.691, 0],
|
|
||||||
[0, -13.484],
|
|
||||||
[-0.048, -0.629],
|
|
||||||
[2.405, 0],
|
|
||||||
[0, -6.742],
|
|
||||||
[-6.742, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 6.743]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[-0.781, 0],
|
|
||||||
[0.001, -0.074],
|
|
||||||
[0, -13.484],
|
|
||||||
[-1.778, 0],
|
|
||||||
[-3.594, -18.742],
|
|
||||||
[-20.03, 0],
|
|
||||||
[-2.421, -0.804],
|
|
||||||
[-13.485, 0],
|
|
||||||
[0, 0.642],
|
|
||||||
[-1.89, -1.199],
|
|
||||||
[-6.742, 0],
|
|
||||||
[0, 6.743],
|
|
||||||
[0, 0],
|
|
||||||
[6.742, 0],
|
|
||||||
[0, -6.742]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[75.134, 16.175],
|
|
||||||
[72.85, 16.396],
|
|
||||||
[72.856, 16.175],
|
|
||||||
[48.44, -8.241],
|
|
||||||
[43.262, -7.685],
|
|
||||||
[3.406, -40.591],
|
|
||||||
[-36.571, -6.995],
|
|
||||||
[-44.269, -8.241],
|
|
||||||
[-68.685, 16.175],
|
|
||||||
[-68.604, 18.079],
|
|
||||||
[-75.133, 16.175],
|
|
||||||
[-87.341, 28.383],
|
|
||||||
[-75.133, 40.592],
|
|
||||||
[75.134, 40.592],
|
|
||||||
[87.342, 28.383]
|
|
||||||
],
|
|
||||||
"c": true
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "fl",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.815686334348, 0.823529471603, 0.827451040231, 1],
|
|
||||||
"ix": 4
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 5 },
|
|
||||||
"r": 1,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Fill 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Fill",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [453.672, 304.756], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Group 4",
|
|
||||||
"np": 2,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 151,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "Merged Shape Layer",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": [0.667], "y": [1] },
|
|
||||||
"o": { "x": [0.547], "y": [0] },
|
|
||||||
"t": 0,
|
|
||||||
"s": [0]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"i": { "x": [0.845], "y": [1] },
|
|
||||||
"o": { "x": [0.333], "y": [0] },
|
|
||||||
"t": 77,
|
|
||||||
"s": [35]
|
|
||||||
},
|
|
||||||
{ "t": 150, "s": [0] }
|
|
||||||
],
|
|
||||||
"ix": 10
|
|
||||||
},
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": 0.667, "y": 1 },
|
|
||||||
"o": { "x": 0.333, "y": 0 },
|
|
||||||
"t": 0,
|
|
||||||
"s": [390.319, 298.2, 0],
|
|
||||||
"to": [0, -2.583, 0],
|
|
||||||
"ti": [0, 0, 0]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"i": { "x": 0.667, "y": 1 },
|
|
||||||
"o": { "x": 0.333, "y": 0 },
|
|
||||||
"t": 44,
|
|
||||||
"s": [390.319, 282.7, 0],
|
|
||||||
"to": [0, 0, 0],
|
|
||||||
"ti": [0, 0, 0]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"i": { "x": 0.667, "y": 1 },
|
|
||||||
"o": { "x": 0.333, "y": 0 },
|
|
||||||
"t": 110,
|
|
||||||
"s": [390.319, 319.25, 0],
|
|
||||||
"to": [0, 0, 0],
|
|
||||||
"ti": [0, 0, 0]
|
|
||||||
},
|
|
||||||
{ "t": 150, "s": [390.319, 298.2, 0] }
|
|
||||||
],
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"a": { "a": 0, "k": [664.319, 256.2, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[18.967, -3.189],
|
|
||||||
[-18.967, 19.935],
|
|
||||||
[-0.949, -19.935]
|
|
||||||
],
|
|
||||||
"c": true
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "fl",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [
|
|
||||||
0.223528981209, 0.192156970501, 0.674510002136, 1
|
|
||||||
],
|
|
||||||
"ix": 4
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 5 },
|
|
||||||
"r": 1,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Fill 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Fill",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [236.879, 292.737], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Group 1",
|
|
||||||
"np": 2,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [633.939, 275.369], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [236.879, 292.737], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [50, 50], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "planete Outlines - Group 1",
|
|
||||||
"np": 1,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-98.335, 64.79],
|
|
||||||
[-105.619, 4.984],
|
|
||||||
[105.619, -64.79],
|
|
||||||
[-80.316, 24.919]
|
|
||||||
],
|
|
||||||
"c": true
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "fl",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [
|
|
||||||
0.278430998325, 0.294117987156, 0.847059011459, 1
|
|
||||||
],
|
|
||||||
"ix": 4
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 5 },
|
|
||||||
"r": 1,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Fill 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Fill",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [316.247, 247.882], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Group 2",
|
|
||||||
"np": 2,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [673.623, 252.941], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [316.247, 247.882], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [50, 50], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "planete Outlines - Group 2",
|
|
||||||
"np": 1,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 2,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 0]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[-133.812, -42.171],
|
|
||||||
[133.812, -75.141],
|
|
||||||
[5.765, 75.141],
|
|
||||||
[-61.708, 18.402],
|
|
||||||
[124.227, -71.307],
|
|
||||||
[-87.011, -1.534]
|
|
||||||
],
|
|
||||||
"c": true
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "fl",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [
|
|
||||||
0.365000009537, 0.407999992371, 0.976000010967, 1
|
|
||||||
],
|
|
||||||
"ix": 4
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 5 },
|
|
||||||
"r": 1,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Fill 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Fill",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [297.638, 254.4], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Group 3",
|
|
||||||
"np": 2,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [664.319, 256.2], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [297.638, 254.4], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [50, 50], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "planete Outlines - Group 3",
|
|
||||||
"np": 1,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 3,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 151,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"nm": "planete Outlines - Group 5",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": [0.667], "y": [1] },
|
|
||||||
"o": { "x": [0.333], "y": [0] },
|
|
||||||
"t": 0,
|
|
||||||
"s": [0]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"i": { "x": [0.667], "y": [1] },
|
|
||||||
"o": { "x": [0.333], "y": [0] },
|
|
||||||
"t": 45,
|
|
||||||
"s": [100]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"i": { "x": [0.667], "y": [1] },
|
|
||||||
"o": { "x": [0.333], "y": [0] },
|
|
||||||
"t": 102,
|
|
||||||
"s": [100]
|
|
||||||
},
|
|
||||||
{ "t": 150, "s": [0] }
|
|
||||||
],
|
|
||||||
"ix": 11
|
|
||||||
},
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"i": { "x": 0.833, "y": 0.833 },
|
|
||||||
"o": { "x": 0.167, "y": 0.167 },
|
|
||||||
"t": 0,
|
|
||||||
"s": [327.38, 267.583, 0],
|
|
||||||
"to": [25.833, 0, 0],
|
|
||||||
"ti": [-25.833, 0, 0]
|
|
||||||
},
|
|
||||||
{ "t": 150, "s": [482.38, 267.583, 0] }
|
|
||||||
],
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"a": { "a": 0, "k": [171.76, 193.166, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [50, 50, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ind": 0,
|
|
||||||
"ty": "sh",
|
|
||||||
"ix": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": 0,
|
|
||||||
"k": {
|
|
||||||
"i": [
|
|
||||||
[13.485, 0],
|
|
||||||
[4.38, -4.171],
|
|
||||||
[21.913, 0],
|
|
||||||
[3.575, -18.765],
|
|
||||||
[1.851, 0],
|
|
||||||
[0, -13.484],
|
|
||||||
[-0.011, -0.291],
|
|
||||||
[1.599, 0],
|
|
||||||
[0, -6.743],
|
|
||||||
[-6.742, 0],
|
|
||||||
[0, 0],
|
|
||||||
[0, 13.485]
|
|
||||||
],
|
|
||||||
"o": [
|
|
||||||
[-6.526, 0],
|
|
||||||
[-0.793, -21.719],
|
|
||||||
[-19.806, 0],
|
|
||||||
[-1.734, -0.391],
|
|
||||||
[-13.485, 0],
|
|
||||||
[0, 0.293],
|
|
||||||
[-1.4, -0.559],
|
|
||||||
[-6.742, 0],
|
|
||||||
[0, 6.742],
|
|
||||||
[0, 0],
|
|
||||||
[13.485, 0],
|
|
||||||
[0, -13.484]
|
|
||||||
],
|
|
||||||
"v": [
|
|
||||||
[59.669, -8.242],
|
|
||||||
[42.84, -1.506],
|
|
||||||
[2.287, -40.592],
|
|
||||||
[-37.576, -7.638],
|
|
||||||
[-42.962, -8.242],
|
|
||||||
[-67.378, 16.174],
|
|
||||||
[-67.356, 17.049],
|
|
||||||
[-71.878, 16.174],
|
|
||||||
[-84.086, 28.383],
|
|
||||||
[-71.878, 40.591],
|
|
||||||
[59.669, 40.591],
|
|
||||||
[84.086, 16.174]
|
|
||||||
],
|
|
||||||
"c": true
|
|
||||||
},
|
|
||||||
"ix": 2
|
|
||||||
},
|
|
||||||
"nm": "Path 1",
|
|
||||||
"mn": "ADBE Vector Shape - Group",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "fl",
|
|
||||||
"c": {
|
|
||||||
"a": 0,
|
|
||||||
"k": [0.816000007181, 0.823999980852, 0.827000038297, 1],
|
|
||||||
"ix": 4
|
|
||||||
},
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 5 },
|
|
||||||
"r": 1,
|
|
||||||
"bm": 0,
|
|
||||||
"nm": "Fill 1",
|
|
||||||
"mn": "ADBE Vector Graphic - Fill",
|
|
||||||
"hd": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "tr",
|
|
||||||
"p": { "a": 0, "k": [171.76, 193.166], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [0, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [100, 100], "ix": 3 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 6 },
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 7 },
|
|
||||||
"sk": { "a": 0, "k": 0, "ix": 4 },
|
|
||||||
"sa": { "a": 0, "k": 0, "ix": 5 },
|
|
||||||
"nm": "Transform"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nm": "Group 5",
|
|
||||||
"np": 2,
|
|
||||||
"cix": 2,
|
|
||||||
"bm": 0,
|
|
||||||
"ix": 1,
|
|
||||||
"mn": "ADBE Vector Group",
|
|
||||||
"hd": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ip": 0,
|
|
||||||
"op": 151,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ddd": 0,
|
|
||||||
"ind": 1,
|
|
||||||
"ty": 0,
|
|
||||||
"nm": "Pre-comp 1",
|
|
||||||
"refId": "comp_0",
|
|
||||||
"sr": 1,
|
|
||||||
"ks": {
|
|
||||||
"o": { "a": 0, "k": 100, "ix": 11 },
|
|
||||||
"r": { "a": 0, "k": 0, "ix": 10 },
|
|
||||||
"p": { "a": 0, "k": [406, 306, 0], "ix": 2 },
|
|
||||||
"a": { "a": 0, "k": [400, 300, 0], "ix": 1 },
|
|
||||||
"s": { "a": 0, "k": [179, 179, 100], "ix": 6 }
|
|
||||||
},
|
|
||||||
"ao": 0,
|
|
||||||
"w": 800,
|
|
||||||
"h": 600,
|
|
||||||
"ip": 0,
|
|
||||||
"op": 147,
|
|
||||||
"st": 0,
|
|
||||||
"bm": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"markers": []
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { CreateClientSuccess } from '@/components/clients/create-client-success';
|
import { CreateClientSuccess } from '@/components/clients/create-client-success';
|
||||||
import { Button, buttonVariants } from '@/components/ui/button';
|
import { Button, buttonVariants } from '@/components/ui/button';
|
||||||
import { Combobox } from '@/components/ui/combobox';
|
import { Combobox } from '@/components/ui/combobox';
|
||||||
@@ -9,6 +8,7 @@ import { Input } from '@/components/ui/input';
|
|||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { cn } from '@/utils/cn';
|
import { cn } from '@/utils/cn';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { SaveIcon, WallpaperIcon } from 'lucide-react';
|
import { SaveIcon, WallpaperIcon } from 'lucide-react';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Calendar } from '@/components/ui/calendar';
|
import { Calendar } from '@/components/ui/calendar';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Combobox } from '@/components/ui/combobox';
|
import { Combobox } from '@/components/ui/combobox';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { api, handleError } from '@/app/_trpc/client';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import { useAppParams } from '@/hooks/useAppParams';
|
import { useAppParams } from '@/hooks/useAppParams';
|
||||||
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createTRPCRouter } from '@/server/api/trpc';
|
import { createTRPCRouter } from '@/trpc/api/trpc';
|
||||||
|
|
||||||
import { chartRouter } from './routers/chart';
|
import { chartRouter } from './routers/chart';
|
||||||
import { clientRouter } from './routers/client';
|
import { clientRouter } from './routers/client';
|
||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
protectedProcedure,
|
protectedProcedure,
|
||||||
publicProcedure,
|
publicProcedure,
|
||||||
} from '@/server/api/trpc';
|
} from '@/trpc/api/trpc';
|
||||||
import { average, max, min, round, sum } from '@/utils/math';
|
import { average, max, min, round, sum } from '@/utils/math';
|
||||||
import { flatten, map, pipe, prop, sort, uniq } from 'ramda';
|
import { flatten, map, pipe, prop, sort, uniq } from 'ramda';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { hashPassword, stripTrailingSlash } from '@openpanel/common';
|
import { hashPassword, stripTrailingSlash } from '@openpanel/common';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import { getId } from '@/utils/getDbId';
|
import { getId } from '@/utils/getDbId';
|
||||||
import { PrismaError } from 'prisma-error-enum';
|
import { PrismaError } from 'prisma-error-enum';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { db } from '@openpanel/db';
|
import { db } from '@openpanel/db';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import { clerkClient } from '@clerk/nextjs';
|
import { clerkClient } from '@clerk/nextjs';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import { clerkClient } from '@clerk/nextjs';
|
import { clerkClient } from '@clerk/nextjs';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
protectedProcedure,
|
protectedProcedure,
|
||||||
publicProcedure,
|
publicProcedure,
|
||||||
} from '@/server/api/trpc';
|
} from '@/trpc/api/trpc';
|
||||||
import { flatten, map, pipe, prop, sort, uniq } from 'ramda';
|
import { flatten, map, pipe, prop, sort, uniq } from 'ramda';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import { getId } from '@/utils/getDbId';
|
import { getId } from '@/utils/getDbId';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
protectedProcedure,
|
protectedProcedure,
|
||||||
publicProcedure,
|
publicProcedure,
|
||||||
} from '@/server/api/trpc';
|
} from '@/trpc/api/trpc';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { db, getReferences } from '@openpanel/db';
|
import { db, getReferences } from '@openpanel/db';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { db } from '@openpanel/db';
|
import { db } from '@openpanel/db';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import ShortUniqueId from 'short-unique-id';
|
import ShortUniqueId from 'short-unique-id';
|
||||||
|
|
||||||
import { db } from '@openpanel/db';
|
import { db } from '@openpanel/db';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createTRPCRouter, protectedProcedure } from '@/server/api/trpc';
|
import { createTRPCRouter, protectedProcedure } from '@/trpc/api/trpc';
|
||||||
import { clerkClient } from '@clerk/nextjs';
|
import { clerkClient } from '@clerk/nextjs';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { AppRouter } from '@/server/api/root';
|
import type { AppRouter } from '@/trpc/api/root';
|
||||||
import type { TRPCClientErrorBase } from '@trpc/react-query';
|
import type { TRPCClientErrorBase } from '@trpc/react-query';
|
||||||
import { createTRPCReact } from '@trpc/react-query';
|
import { createTRPCReact } from '@trpc/react-query';
|
||||||
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
||||||
@@ -6,7 +6,7 @@ export function DeviceIdWarning() {
|
|||||||
<Callout>
|
<Callout>
|
||||||
Read more about{' '}
|
Read more about{' '}
|
||||||
<Link href="/docs/device-id">device id and why you might want it</Link>.
|
<Link href="/docs/device-id">device id and why you might want it</Link>.
|
||||||
**We recommend not to but it's up to you.**
|
**We recommend not to but it's up to you.**
|
||||||
</Callout>
|
</Callout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,5 +17,6 @@
|
|||||||
"title": "Others"
|
"title": "Others"
|
||||||
},
|
},
|
||||||
"javascript": "Javascript SDK",
|
"javascript": "Javascript SDK",
|
||||||
"web": "Web SDK"
|
"web": "Web SDK",
|
||||||
|
"api": "API"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ export default function Page() {
|
|||||||
<p>
|
<p>
|
||||||
<strong>Affiliate</strong> means an entity that controls, is
|
<strong>Affiliate</strong> means an entity that controls, is
|
||||||
controlled by or is under common control with a party, where
|
controlled by or is under common control with a party, where
|
||||||
"control" means ownership of 50% or more of the shares, equity
|
"control" means ownership of 50% or more of the shares,
|
||||||
interest or other securities entitled to vote for election of
|
equity interest or other securities entitled to vote for election
|
||||||
directors or other managing authority.
|
of directors or other managing authority.
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@@ -54,9 +54,10 @@ export default function Page() {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>
|
<p>
|
||||||
<strong>Company</strong> (referred to as either "the Company",
|
<strong>Company</strong> (referred to as either "the
|
||||||
"We", "Us" or "Our" in this Agreement) refers to Coderax AB, Sankt
|
Company", "We", "Us" or "Our"
|
||||||
Eriksgatan 100, 113 31, Stockholm.
|
in this Agreement) refers to Coderax AB, Sankt Eriksgatan 100, 113
|
||||||
|
31, Stockholm.
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@@ -151,7 +152,7 @@ export default function Page() {
|
|||||||
<h4>Usage Data</h4>
|
<h4>Usage Data</h4>
|
||||||
<p>Usage Data is collected automatically when using the Service.</p>
|
<p>Usage Data is collected automatically when using the Service.</p>
|
||||||
<p>
|
<p>
|
||||||
Usage Data may include information such as Your Device's Internet
|
Usage Data may include information such as Your Device's Internet
|
||||||
Protocol address (e.g. IP address), browser type, browser version, the
|
Protocol address (e.g. IP address), browser type, browser version, the
|
||||||
pages of our Service that You visit, the time and date of Your visit,
|
pages of our Service that You visit, the time and date of Your visit,
|
||||||
the time spent on those pages, unique device identifiers and other
|
the time spent on those pages, unique device identifiers and other
|
||||||
@@ -198,10 +199,10 @@ export default function Page() {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies
|
Cookies can be "Persistent" or "Session" Cookies.
|
||||||
remain on Your personal computer or mobile device when You go offline,
|
Persistent Cookies remain on Your personal computer or mobile device
|
||||||
while Session Cookies are deleted as soon as You close Your web
|
when You go offline, while Session Cookies are deleted as soon as You
|
||||||
browser. You can learn more about cookies{' '}
|
close Your web browser. You can learn more about cookies{' '}
|
||||||
<a
|
<a
|
||||||
href="https://www.termsfeed.com/blog/cookies/#What_Are_Cookies"
|
href="https://www.termsfeed.com/blog/cookies/#What_Are_Cookies"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -291,11 +292,11 @@ export default function Page() {
|
|||||||
<p>
|
<p>
|
||||||
<strong>To contact You:</strong> To contact You by email,
|
<strong>To contact You:</strong> To contact You by email,
|
||||||
telephone calls, SMS, or other equivalent forms of electronic
|
telephone calls, SMS, or other equivalent forms of electronic
|
||||||
communication, such as a mobile application's push notifications
|
communication, such as a mobile application's push
|
||||||
regarding updates or informative communications related to the
|
notifications regarding updates or informative communications
|
||||||
functionalities, products or contracted services, including the
|
related to the functionalities, products or contracted services,
|
||||||
security updates, when necessary or reasonable for their
|
including the security updates, when necessary or reasonable for
|
||||||
implementation.
|
their implementation.
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@@ -391,12 +392,12 @@ export default function Page() {
|
|||||||
<h3>Transfer of Your Personal Data</h3>
|
<h3>Transfer of Your Personal Data</h3>
|
||||||
<p>
|
<p>
|
||||||
Your information, including Personal Data, is processed at the
|
Your information, including Personal Data, is processed at the
|
||||||
Company's operating offices and in any other places where the parties
|
Company's operating offices and in any other places where the
|
||||||
involved in the processing are located. It means that this information
|
parties involved in the processing are located. It means that this
|
||||||
may be transferred to — and maintained on — computers located outside
|
information may be transferred to — and maintained on — computers
|
||||||
of Your state, province, country or other governmental jurisdiction
|
located outside of Your state, province, country or other governmental
|
||||||
where the data protection laws may differ than those from Your
|
jurisdiction where the data protection laws may differ than those from
|
||||||
jurisdiction.
|
Your jurisdiction.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Your consent to this Privacy Policy followed by Your submission of
|
Your consent to this Privacy Policy followed by Your submission of
|
||||||
@@ -468,7 +469,7 @@ export default function Page() {
|
|||||||
acceptable means to protect Your Personal Data, We cannot guarantee
|
acceptable means to protect Your Personal Data, We cannot guarantee
|
||||||
its absolute security.
|
its absolute security.
|
||||||
</p>
|
</p>
|
||||||
<h2>Children's Privacy</h2>
|
<h2>Children's Privacy</h2>
|
||||||
<p>
|
<p>
|
||||||
Our Service does not address anyone under the age of 13. We do not
|
Our Service does not address anyone under the age of 13. We do not
|
||||||
knowingly collect personally identifiable information from anyone
|
knowingly collect personally identifiable information from anyone
|
||||||
@@ -481,15 +482,15 @@ export default function Page() {
|
|||||||
<p>
|
<p>
|
||||||
If We need to rely on consent as a legal basis for processing Your
|
If We need to rely on consent as a legal basis for processing Your
|
||||||
information and Your country requires consent from a parent, We may
|
information and Your country requires consent from a parent, We may
|
||||||
require Your parent's consent before We collect and use that
|
require Your parent's consent before We collect and use that
|
||||||
information.
|
information.
|
||||||
</p>
|
</p>
|
||||||
<h2>Links to Other Websites</h2>
|
<h2>Links to Other Websites</h2>
|
||||||
<p>
|
<p>
|
||||||
Our Service may contain links to other websites that are not operated
|
Our Service may contain links to other websites that are not operated
|
||||||
by Us. If You click on a third party link, You will be directed to
|
by Us. If You click on a third party link, You will be directed to
|
||||||
that third party's site. We strongly advise You to review the Privacy
|
that third party's site. We strongly advise You to review the
|
||||||
Policy of every site You visit.
|
Privacy Policy of every site You visit.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
We have no control over and assume no responsibility for the content,
|
We have no control over and assume no responsibility for the content,
|
||||||
@@ -502,8 +503,8 @@ export default function Page() {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
We will let You know via email and/or a prominent notice on Our
|
We will let You know via email and/or a prominent notice on Our
|
||||||
Service, prior to the change becoming effective and update the "Last
|
Service, prior to the change becoming effective and update the
|
||||||
updated" date at the top of this Privacy Policy.
|
"Last updated" date at the top of this Privacy Policy.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You are advised to review this Privacy Policy periodically for any
|
You are advised to review this Privacy Policy periodically for any
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ export default function Page() {
|
|||||||
of the Company and any of its suppliers under any provision of this
|
of the Company and any of its suppliers under any provision of this
|
||||||
Terms and Your exclusive remedy for all of the foregoing shall be
|
Terms and Your exclusive remedy for all of the foregoing shall be
|
||||||
limited to the amount actually paid by You through the Service or 100
|
limited to the amount actually paid by You through the Service or 100
|
||||||
USD if You haven't purchased anything through the Service.
|
USD if You haven't purchased anything through the Service.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
To the maximum extent permitted by applicable law, in no event shall
|
To the maximum extent permitted by applicable law, in no event shall
|
||||||
@@ -332,8 +332,8 @@ export default function Page() {
|
|||||||
Some states do not allow the exclusion of implied warranties or
|
Some states do not allow the exclusion of implied warranties or
|
||||||
limitation of liability for incidental or consequential damages, which
|
limitation of liability for incidental or consequential damages, which
|
||||||
means that some of the above limitations may not apply. In these
|
means that some of the above limitations may not apply. In these
|
||||||
states, each party's liability will be limited to the greatest extent
|
states, each party's liability will be limited to the greatest
|
||||||
permitted by law.
|
extent permitted by law.
|
||||||
</p>
|
</p>
|
||||||
<h2>"AS IS" and "AS AVAILABLE" Disclaimer</h2>
|
<h2>"AS IS" and "AS AVAILABLE" Disclaimer</h2>
|
||||||
<p>
|
<p>
|
||||||
@@ -357,9 +357,9 @@ export default function Page() {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Without limiting the foregoing, neither the Company nor any of the
|
Without limiting the foregoing, neither the Company nor any of the
|
||||||
company's provider makes any representation or warranty of any kind,
|
company's provider makes any representation or warranty of any
|
||||||
express or implied: (i) as to the operation or availability of the
|
kind, express or implied: (i) as to the operation or availability of
|
||||||
Service, or the information, content, and materials or products
|
the Service, or the information, content, and materials or products
|
||||||
included thereon; (ii) that the Service will be uninterrupted or
|
included thereon; (ii) that the Service will be uninterrupted or
|
||||||
error-free; (iii) as to the accuracy, reliability, or currency of any
|
error-free; (iii) as to the accuracy, reliability, or currency of any
|
||||||
information or content provided through the Service; or (iv) that the
|
information or content provided through the Service; or (iv) that the
|
||||||
@@ -420,7 +420,7 @@ export default function Page() {
|
|||||||
<p>
|
<p>
|
||||||
Except as provided herein, the failure to exercise a right or to
|
Except as provided herein, the failure to exercise a right or to
|
||||||
require performance of an obligation under these Terms shall not
|
require performance of an obligation under these Terms shall not
|
||||||
affect a party's ability to exercise such right or require such
|
affect a party's ability to exercise such right or require such
|
||||||
performance at any time thereafter nor shall the waiver of a breach
|
performance at any time thereafter nor shall the waiver of a breach
|
||||||
constitute a waiver of any subsequent breach.
|
constitute a waiver of any subsequent breach.
|
||||||
</p>
|
</p>
|
||||||
@@ -434,9 +434,9 @@ export default function Page() {
|
|||||||
<p>
|
<p>
|
||||||
We reserve the right, at Our sole discretion, to modify or replace
|
We reserve the right, at Our sole discretion, to modify or replace
|
||||||
these Terms at any time. If a revision is material We will make
|
these Terms at any time. If a revision is material We will make
|
||||||
reasonable efforts to provide at least 30 days' notice prior to any
|
reasonable efforts to provide at least 30 days' notice prior to
|
||||||
new terms taking effect. What constitutes a material change will be
|
any new terms taking effect. What constitutes a material change will
|
||||||
determined at Our sole discretion.
|
be determined at Our sole discretion.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
By continuing to access or use Our Service after those revisions
|
By continuing to access or use Our Service after those revisions
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export async function POST(req: Request) {
|
|||||||
|
|
||||||
await db.waitlist.create({
|
await db.waitlist.create({
|
||||||
data: {
|
data: {
|
||||||
email: body.email.toLowerCase(),
|
email: String(body.email).toLowerCase(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ const features: FeatureItem[] = [
|
|||||||
description: (
|
description: (
|
||||||
<>
|
<>
|
||||||
<p>
|
<p>
|
||||||
Deep dive into your user's behavior and understand how they interact
|
Deep dive into your user's behavior and understand how they
|
||||||
with your app/website.
|
interact with your app/website.
|
||||||
</p>
|
</p>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ export function JoinWaitlistHero({ className }: JoinWaitlistProps) {
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Thanks so much!</DialogTitle>
|
<DialogTitle>Thanks so much!</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
You're now on the waiting list. We'll let you know when we're
|
You're now on the waiting list. We'll let you know when
|
||||||
ready. Should be within a month or two 🚀
|
we're ready. Should be within a month or two 🚀
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ export function JoinWaitlist({ className }: JoinWaitlistProps) {
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Thanks so much!</DialogTitle>
|
<DialogTitle>Thanks so much!</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
You're now on the waiting list. We'll let you know when we're
|
You're now on the waiting list. We'll let you know when
|
||||||
ready. Should be within a month or two 🚀
|
we're ready. Should be within a month or two 🚀
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
|
|||||||
@@ -57,14 +57,15 @@ export default function Page() {
|
|||||||
<h3 className="text-blue-dark text-lg font-bold">TL;DR</h3>
|
<h3 className="text-blue-dark text-lg font-bold">TL;DR</h3>
|
||||||
<Paragraph>
|
<Paragraph>
|
||||||
Our open-source analytic library fills a crucial gap by combining
|
Our open-source analytic library fills a crucial gap by combining
|
||||||
the strengths of Mixpanel's powerful features with Plausible's
|
the strengths of Mixpanel's powerful features with
|
||||||
clear overview page. Motivated by the lack of an open-source
|
Plausible's clear overview page. Motivated by the lack of an
|
||||||
alternative to Mixpanel and inspired by Plausible's simplicity, we
|
open-source alternative to Mixpanel and inspired by
|
||||||
aim to create an intuitive platform with predictable pricing. With
|
Plausible's simplicity, we aim to create an intuitive
|
||||||
a single-tier pricing model and limits only on monthly event
|
platform with predictable pricing. With a single-tier pricing
|
||||||
counts, our goal is to democratize analytics, offering
|
model and limits only on monthly event counts, our goal is to
|
||||||
unrestricted access to all features while ensuring affordability
|
democratize analytics, offering unrestricted access to all
|
||||||
and transparency for users of all project sizes.
|
features while ensuring affordability and transparency for users
|
||||||
|
of all project sizes.
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
||||||
<h3 className="text-blue-dark mt-12 text-lg font-bold">The why</h3>
|
<h3 className="text-blue-dark mt-12 text-lg font-bold">The why</h3>
|
||||||
@@ -72,10 +73,10 @@ export default function Page() {
|
|||||||
Our open-source analytic library emerged from a clear need within
|
Our open-source analytic library emerged from a clear need within
|
||||||
the analytics community. While platforms like Mixpanel offer
|
the analytics community. While platforms like Mixpanel offer
|
||||||
powerful and user-friendly features, they lack a comprehensive
|
powerful and user-friendly features, they lack a comprehensive
|
||||||
overview page akin to Plausible's, which succinctly summarizes
|
overview page akin to Plausible's, which succinctly
|
||||||
essential metrics. Recognizing this gap, we saw an opportunity to
|
summarizes essential metrics. Recognizing this gap, we saw an
|
||||||
combine the strengths of both platforms while addressing their
|
opportunity to combine the strengths of both platforms while
|
||||||
respective shortcomings.
|
addressing their respective shortcomings.
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
||||||
<Paragraph>
|
<Paragraph>
|
||||||
@@ -87,7 +88,7 @@ export default function Page() {
|
|||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
||||||
<Paragraph>
|
<Paragraph>
|
||||||
Inspired by Plausible's exemplary approach to simplicity and
|
Inspired by Plausible's exemplary approach to simplicity and
|
||||||
clarity, we aim to build upon their foundation and further refine
|
clarity, we aim to build upon their foundation and further refine
|
||||||
the user experience. By harnessing the best practices demonstrated
|
the user experience. By harnessing the best practices demonstrated
|
||||||
by Plausible, we aspire to create an intuitive and streamlined
|
by Plausible, we aspire to create an intuitive and streamlined
|
||||||
@@ -108,12 +109,13 @@ export default function Page() {
|
|||||||
<Paragraph>
|
<Paragraph>
|
||||||
In line with our commitment to fairness and accessibility, our
|
In line with our commitment to fairness and accessibility, our
|
||||||
pricing model will only impose limits on the number of events
|
pricing model will only impose limits on the number of events
|
||||||
users can send each month. This approach, akin to Plausible's,
|
users can send each month. This approach, akin to
|
||||||
ensures that users have the freedom to explore and utilize our
|
Plausible's, ensures that users have the freedom to explore
|
||||||
platform to its fullest potential without arbitrary restrictions
|
and utilize our platform to its fullest potential without
|
||||||
on reports or user counts. Ultimately, our goal is to democratize
|
arbitrary restrictions on reports or user counts. Ultimately, our
|
||||||
analytics by offering a reliable, transparent, and cost-effective
|
goal is to democratize analytics by offering a reliable,
|
||||||
solution for projects of all sizes.
|
transparent, and cost-effective solution for projects of all
|
||||||
|
sizes.
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ const items = [
|
|||||||
title: 'Own Your Own Data',
|
title: 'Own Your Own Data',
|
||||||
description: (
|
description: (
|
||||||
<p>
|
<p>
|
||||||
We believe that you should own your own data. That's why we don't sell
|
We believe that you should own your own data. That's why we
|
||||||
your data to third parties. <strong>Ever. Period.</strong>
|
don't sell your data to third parties.{' '}
|
||||||
|
<strong>Ever. Period.</strong>
|
||||||
</p>
|
</p>
|
||||||
),
|
),
|
||||||
icon: KeyIcon,
|
icon: KeyIcon,
|
||||||
|
|||||||
@@ -89,11 +89,16 @@ export interface ALinkProps
|
|||||||
extends React.AnchorHTMLAttributes<HTMLAnchorElement>,
|
extends React.AnchorHTMLAttributes<HTMLAnchorElement>,
|
||||||
VariantProps<typeof buttonVariants> {}
|
VariantProps<typeof buttonVariants> {}
|
||||||
|
|
||||||
export const ALink = ({ variant, size, className, ...props }: ALinkProps) => {
|
export const ALink = ({
|
||||||
|
variant,
|
||||||
|
size,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: ALinkProps) => {
|
||||||
return (
|
return (
|
||||||
<a
|
<a {...props} className={cn(buttonVariants({ variant, size, className }))}>
|
||||||
{...props}
|
{children}
|
||||||
className={cn(buttonVariants({ variant, size, className }))}
|
</a>
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,5 +14,5 @@
|
|||||||
"strictNullChecks": true
|
"strictNullChecks": true
|
||||||
},
|
},
|
||||||
"include": [".", ".next/types/**/*.ts"],
|
"include": [".", ".next/types/**/*.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules", "public"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
# Create T3 App
|
|
||||||
|
|
||||||
This is a [T3 Stack](https://create.t3.gg/) project bootstrapped with `create-t3-app`.
|
|
||||||
|
|
||||||
## What's next? How do I make an app with this?
|
|
||||||
|
|
||||||
We try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary.
|
|
||||||
|
|
||||||
If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help.
|
|
||||||
|
|
||||||
- [Next.js](https://nextjs.org)
|
|
||||||
- [NextAuth.js](https://next-auth.js.org)
|
|
||||||
- [Prisma](https://prisma.io)
|
|
||||||
- [Tailwind CSS](https://tailwindcss.com)
|
|
||||||
- [tRPC](https://trpc.io)
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
To learn more about the [T3 Stack](https://create.t3.gg/), take a look at the following resources:
|
|
||||||
|
|
||||||
- [Documentation](https://create.t3.gg/)
|
|
||||||
- [Learn the T3 Stack](https://create.t3.gg/en/faq#what-learning-resources-are-currently-available) — Check out these awesome tutorials
|
|
||||||
|
|
||||||
You can check out the [create-t3-app GitHub repository](https://github.com/t3-oss/create-t3-app) — your feedback and contributions are welcome!
|
|
||||||
|
|
||||||
## How do I deploy this?
|
|
||||||
|
|
||||||
Follow our deployment guides for [Vercel](https://create.t3.gg/en/deployment/vercel), [Netlify](https://create.t3.gg/en/deployment/netlify) and [Docker](https://create.t3.gg/en/deployment/docker) for more information.
|
|
||||||
6
apps/test/next-env.d.ts
vendored
6
apps/test/next-env.d.ts
vendored
@@ -1,6 +0,0 @@
|
|||||||
/// <reference types="next" />
|
|
||||||
/// <reference types="next/image-types/global" />
|
|
||||||
/// <reference types="next/navigation-types/compat/navigation" />
|
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
|
||||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/**
|
|
||||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
|
|
||||||
* for Docker builds.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @type {import("next").NextConfig} */
|
|
||||||
const config = {
|
|
||||||
reactStrictMode: false,
|
|
||||||
transpilePackages: ['@openpanel/sdk', '@openpanel/web', '@openpanel/nextjs'],
|
|
||||||
eslint: { ignoreDuringBuilds: true },
|
|
||||||
typescript: { ignoreBuildErrors: true },
|
|
||||||
/**
|
|
||||||
* If you are using `appDir` then you must comment the below `i18n` config out.
|
|
||||||
*
|
|
||||||
* @see https://github.com/vercel/next.js/issues/41980
|
|
||||||
*/
|
|
||||||
i18n: {
|
|
||||||
locales: ['en'],
|
|
||||||
defaultLocale: 'en',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user