move clients settings into projects

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-04-02 22:33:13 +02:00
parent 1245047a7c
commit d9e3045a5b
11 changed files with 182 additions and 124 deletions

View File

@@ -117,11 +117,6 @@ export default function LayoutMenu({ dashboards }: LayoutMenuProps) {
label="Projects"
href={`/${params.organizationId}/${projectId}/settings/projects`}
/>
<LinkWithIcon
icon={KeySquareIcon}
label="Clients"
href={`/${params.organizationId}/${projectId}/settings/clients`}
/>
<LinkWithIcon
icon={UserIcon}
label="Profile (yours)"

View File

@@ -1,32 +0,0 @@
'use client';
import { StickyBelowHeader } from '@/app/(app)/[organizationId]/[projectId]/layout-sticky-below-header';
import { columns } from '@/components/clients/table';
import { DataTable } from '@/components/data-table';
import { Button } from '@/components/ui/button';
import { pushModal } from '@/modals';
import { PlusIcon } from 'lucide-react';
import type { getClientsByOrganizationId } from '@openpanel/db';
interface ListClientsProps {
clients: Awaited<ReturnType<typeof getClientsByOrganizationId>>;
}
export default function ListClients({ clients }: ListClientsProps) {
return (
<>
<StickyBelowHeader>
<div className="flex items-center justify-between p-4">
<div />
<Button icon={PlusIcon} onClick={() => pushModal('AddClient')}>
<span className="max-sm:hidden">Create client</span>
<span className="sm:hidden">Client</span>
</Button>
</div>
</StickyBelowHeader>
<div className="p-4">
<DataTable data={clients} columns={columns} />
</div>
</>
);
}

View File

@@ -1,21 +0,0 @@
import PageLayout from '@/app/(app)/[organizationId]/[projectId]/page-layout';
import { getClientsByOrganizationId } from '@openpanel/db';
import ListClients from './list-clients';
interface PageProps {
params: {
organizationId: string;
};
}
export default async function Page({ params: { organizationId } }: PageProps) {
const clients = await getClientsByOrganizationId(organizationId);
return (
<PageLayout title="Clients" organizationSlug={organizationId}>
<ListClients clients={clients} />
</PageLayout>
);
}

View File

@@ -1,19 +1,29 @@
'use client';
import { StickyBelowHeader } from '@/app/(app)/[organizationId]/[projectId]/layout-sticky-below-header';
import { DataTable } from '@/components/data-table';
import { columns } from '@/components/projects/table';
import { ClientActions } from '@/components/clients/client-actions';
import { ProjectActions } from '@/components/projects/project-actions';
// import { columns } from '@/components/projects/table';
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@/components/ui/accordion';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import { Tooltiper } from '@/components/ui/tooltip';
import { useAppParams } from '@/hooks/useAppParams';
import { pushModal } from '@/modals';
import { PlusIcon } from 'lucide-react';
import { InfoIcon, PlusIcon, PlusSquareIcon } from 'lucide-react';
import type { getProjectsByOrganizationSlug } from '@openpanel/db';
import type { IServiceClientWithProject, IServiceProject } from '@openpanel/db';
interface ListProjectsProps {
projects: Awaited<ReturnType<typeof getProjectsByOrganizationSlug>>;
projects: IServiceProject[];
clients: IServiceClientWithProject[];
}
export default function ListProjects({ projects }: ListProjectsProps) {
export default function ListProjects({ projects, clients }: ListProjectsProps) {
const organizationId = useAppParams().organizationId;
return (
<>
@@ -34,7 +44,83 @@ export default function ListProjects({ projects }: ListProjectsProps) {
</div>
</StickyBelowHeader>
<div className="p-4">
<DataTable data={projects} columns={columns} />
<div className="card p-4">
<Alert className="mb-4">
<InfoIcon size={16} />
<AlertTitle>What is a project</AlertTitle>
<AlertDescription>
A project can be a website, mobile app or any other application
that you want to track event for. Each project can have one or
more clients. The client is used to send events to the project.
</AlertDescription>
</Alert>
<Accordion type="single" collapsible className="-mx-4">
{projects.map((project) => {
const pClients = clients.filter(
(client) => client.project_id === project.id
);
return (
<AccordionItem
value={project.id}
key={project.id}
className="last:border-b-0"
>
<AccordionTrigger className="px-4">
<div className="flex-1 text-left">
{project.name}
<span className="ml-2 text-muted-foreground">
{pClients.length > 0
? `(${pClients.length} clients)`
: 'No clients created yet'}
</span>
</div>
<div className="mx-4"></div>
</AccordionTrigger>
<AccordionContent className="px-4">
<ProjectActions {...project} />
<div className="mt-4 grid gap-4 md:grid-cols-3">
{pClients.map((item) => {
return (
<div
className="relative rounded border border-border p-4"
key={item.id}
>
<div className="mb-1 font-medium">{item.name}</div>
<Tooltiper
className="text-muted-foreground"
content={item.id}
>
Client ID: ...{item.id.slice(-12)}
</Tooltiper>
<div className="text-muted-foreground">
{item.secret
? 'Secret: Hidden'
: `Website: ${item.cors}`}
</div>
<div className="absolute right-4 top-4">
<ClientActions {...item} />
</div>
</div>
);
})}
<button
onClick={() => {
pushModal('AddClient', {
projectId: project.id,
});
}}
className="flex items-center justify-center gap-4 rounded bg-muted p-4"
>
<PlusSquareIcon />
<div className="font-medium">New client</div>
</button>
</div>
</AccordionContent>
</AccordionItem>
);
})}
</Accordion>
</div>
</div>
</>
);

View File

@@ -1,6 +1,9 @@
import PageLayout from '@/app/(app)/[organizationId]/[projectId]/page-layout';
import { getProjectsByOrganizationSlug } from '@openpanel/db';
import {
getClientsByOrganizationId,
getProjectsByOrganizationSlug,
} from '@openpanel/db';
import ListProjects from './list-projects';
@@ -11,11 +14,14 @@ interface PageProps {
}
export default async function Page({ params: { organizationId } }: PageProps) {
const projects = await getProjectsByOrganizationSlug(organizationId);
const [projects, clients] = await Promise.all([
getProjectsByOrganizationSlug(organizationId),
getClientsByOrganizationId(organizationId),
]);
return (
<PageLayout title="Projects" organizationSlug={organizationId}>
<ListProjects projects={projects} />
<ListProjects projects={projects} clients={clients} />
</PageLayout>
);
}