diff --git a/app/(customer)/dashboard/admin/page.tsx b/app/(customer)/dashboard/admin/page.tsx new file mode 100644 index 00000000..0faf6497 --- /dev/null +++ b/app/(customer)/dashboard/admin/page.tsx @@ -0,0 +1,45 @@ +import {PageParams} from "@/types/next"; + +import {Page, PageContent, PageHeader, PageTitle} from "@/features/layout/page"; +import {requiredCurrentUser} from "@/auth/current-user"; +import {prisma} from "@/prisma"; +import {AdminTabs} from "@/components/wrappers/Dashboard/admin/admin-tabs"; + + +export default async function RoutePage(props: PageParams<{}>) { + + + const user = await requiredCurrentUser() + + const users = await prisma.user.findMany({ + where: { + // id: { + // not: user.id + // }, + deleted: {not: true}, + + } + }) + + console.log(users) + + const settings = await prisma.settings.findUnique({ + where: { + name: "system" + } + }) + + return ( + + + + Administration Panel + + + + + + + + ) +} \ No newline at end of file diff --git a/app/(customer)/dashboard/settings/page.tsx b/app/(customer)/dashboard/settings/page.tsx index a2e3ee8f..c66a38be 100644 --- a/app/(customer)/dashboard/settings/page.tsx +++ b/app/(customer)/dashboard/settings/page.tsx @@ -8,12 +8,18 @@ import {SettingsTabs} from "@/components/wrappers/Dashboard/Settings/SettingsTab export default async function RoutePage(props: PageParams<{}>) { const user = await requiredCurrentUser() + const defaultOrganization = await prisma.organization.findUnique({ + where: {slug: "default"}, + }); + const users = await prisma.user.findMany({ - where:{ - id: { - not: user.id + where: { + organizations: { + some: { + organizationId: defaultOrganization.id + }, }, - deleted: { not: true }, + deleted: {not: true}, } }) @@ -21,7 +27,7 @@ export default async function RoutePage(props: PageParams<{}>) { console.log(users) const settings = await prisma.settings.findUnique({ - where:{ + where: { name: "system" } }) @@ -34,10 +40,10 @@ export default async function RoutePage(props: PageParams<{}>) { - Manage your Portabase settings + Manage your organization settings. - + ) diff --git a/src/components/wrappers/Dashboard/LoggedInDropdown/LoggedInDropdown.tsx b/src/components/wrappers/Dashboard/LoggedInDropdown/LoggedInDropdown.tsx index 04c59e72..ca049525 100644 --- a/src/components/wrappers/Dashboard/LoggedInDropdown/LoggedInDropdown.tsx +++ b/src/components/wrappers/Dashboard/LoggedInDropdown/LoggedInDropdown.tsx @@ -4,6 +4,7 @@ import {PropsWithChildren} from "react"; import {DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger} from "@/components/ui/dropdown-menu"; import {signOutAction} from "@/features/auth/auth.action"; import {redirect} from "next/navigation"; +import {CircleUser, LogOut, ShieldHalf} from "lucide-react"; export type LoggedInDropdownProps = PropsWithChildren<{}> @@ -21,15 +22,29 @@ export const LoggedInDropdown = (props: LoggedInDropdownProps) => { { redirect("/dashboard/profile") }}> - Account +
+ + Account +
+
+ { + redirect("/dashboard/admin") + }}> +
+ + Administration Panel +
{ signOutAction() }}> - Sign out +
+ + Log out +
-) -} + ) +} \ No newline at end of file diff --git a/src/components/wrappers/Dashboard/Profile/ButtonDeleteAccount/delete-account.action.ts b/src/components/wrappers/Dashboard/Profile/ButtonDeleteAccount/delete-account.action.ts index ba9dbfbe..95728db5 100644 --- a/src/components/wrappers/Dashboard/Profile/ButtonDeleteAccount/delete-account.action.ts +++ b/src/components/wrappers/Dashboard/Profile/ButtonDeleteAccount/delete-account.action.ts @@ -3,7 +3,7 @@ import {userAction} from "@/safe-actions"; import {prisma} from "@/prisma"; import {z} from "zod"; import {v4 as uuidv4} from "uuid"; -import {EmailFormSchema} from "@/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.schema"; +import {EmailFormSchema} from "@/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.schema"; export const deleteUserAction = userAction diff --git a/src/components/wrappers/Dashboard/Settings/SettingsTabs/SettingsTabs.tsx b/src/components/wrappers/Dashboard/Settings/SettingsTabs/SettingsTabs.tsx index 143a320c..fe0590ec 100644 --- a/src/components/wrappers/Dashboard/Settings/SettingsTabs/SettingsTabs.tsx +++ b/src/components/wrappers/Dashboard/Settings/SettingsTabs/SettingsTabs.tsx @@ -1,50 +1,54 @@ "use client" + import {Tabs, TabsContent, TabsList, TabsTrigger} from "@/components/ui/tabs"; import {DataTableWithPagination} from "@/components/wrappers/table/data-table-with-pagination"; import {usersColumns} from "@/components/wrappers/Dashboard/Settings/SettingsUsersTab/columns-users"; import {User, Settings} from "@prisma/client"; import {backupColumns} from "@/features/backup/columns"; -import {SettingsEmailTab} from "@/components/wrappers/Dashboard/Settings/SettingsEmailTab/SettingsEmailTab"; -import {SettingsStorageTab} from "@/components/wrappers/Dashboard/Settings/SettingsStorageTab/SettingsStorageTab"; +import {SettingsEmailTab} from "@/components/wrappers/Dashboard/admin/AdminEmailTab/SettingsEmailTab"; +import {SettingsStorageTab} from "@/components/wrappers/Dashboard/admin/AdminStorageTab/SettingsStorageTab"; import {SettingsUsersTab} from "@/components/wrappers/Dashboard/Settings/SettingsUsersTab/SettingsUsersTab"; export type SettingsTabsProps = { + currentUser: User; users: User[]; settings: Settings; } export const SettingsTabs = (props: SettingsTabsProps) => { - return( + const {currentUser, users} = props; - - - Info - Users - Email - Storage - - -
-
-
-
-
-
-
-
- - - - - - - - - - - + return ( + + // + // + // Info + // Users + // Email + // Storage + // + // + //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ // + // + + // + // + // + // + // + // + // + // ) } diff --git a/src/components/wrappers/Dashboard/Settings/SettingsUsersTab/SettingsUsersTab.tsx b/src/components/wrappers/Dashboard/Settings/SettingsUsersTab/SettingsUsersTab.tsx index 13fa5fff..91341608 100644 --- a/src/components/wrappers/Dashboard/Settings/SettingsUsersTab/SettingsUsersTab.tsx +++ b/src/components/wrappers/Dashboard/Settings/SettingsUsersTab/SettingsUsersTab.tsx @@ -1,21 +1,30 @@ +import {User} from "@prisma/client"; import {DataTableWithPagination} from "@/components/wrappers/table/data-table-with-pagination"; import {usersColumns} from "@/components/wrappers/Dashboard/Settings/SettingsUsersTab/columns-users"; -import {User} from "@prisma/client"; +import {UsersDataTable} from "@/components/wrappers/Dashboard/admin/admin-user-table"; export type SettingsUsersTabProps = { + currentUser: User; users: User[] } export const SettingsUsersTab = (props: SettingsUsersTabProps) => { - return ( + const {currentUser, users} = props; + + return (
-

List of Portabase users

+

List of organization's users

- +
) diff --git a/src/components/wrappers/Dashboard/SideBar/SideBarMenu/SideBarMenu.tsx b/src/components/wrappers/Dashboard/SideBar/SideBarMenu/SideBarMenu.tsx index 60986be1..74d6f962 100644 --- a/src/components/wrappers/Dashboard/SideBar/SideBarMenu/SideBarMenu.tsx +++ b/src/components/wrappers/Dashboard/SideBar/SideBarMenu/SideBarMenu.tsx @@ -56,13 +56,16 @@ export const SidebarMenuCustom = (props: SidebarMenuCustomProps) => { setActiveItem(title); console.log(title) } - return( + return ( {items.map((item) => ( - + handleItemClick(item.title)} > @@ -70,9 +73,47 @@ export const SidebarMenuCustom = (props: SidebarMenuCustomProps) => { {item.title} - + ))} ) -} \ No newline at end of file +} + +// export type SidebarMenuItemCustomProps = { +// title: string +// url: string +// icon: Element +// } +// +// +// export const SidebarMenuItemCustom = (props: SidebarMenuItemCustomProps) => { +// +// const {title, url, icon} = props; +// +// const BASE_URL = "/dashboard"; +// const pathname = usePathname(); +// +// const [activeItem, setActiveItem] = useState(title); +// +// return ( +// +// +// handleItemClick(item.title)} +// > +// +// {title} +// +// +// +// +// ) +// } \ No newline at end of file diff --git a/src/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/EmailForm.tsx b/src/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/EmailForm.tsx similarity index 97% rename from src/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/EmailForm.tsx rename to src/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/EmailForm.tsx index 43315a66..bb1af080 100644 --- a/src/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/EmailForm.tsx +++ b/src/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/EmailForm.tsx @@ -13,12 +13,12 @@ import {TooltipProvider} from "@/components/ui/tooltip"; import { EmailFormSchema, EmailFormType -} from "@/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.schema"; +} from "@/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.schema"; import Link from "next/link"; import {PasswordInput} from "@/components/wrappers/Auth/PaswordInput/password-input"; import { updateEmailSettingsAction -} from "@/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.action"; +} from "@/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.action"; import {toast} from "sonner"; import {useRouter} from "next/navigation"; diff --git a/src/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.action.ts b/src/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.action.ts similarity index 84% rename from src/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.action.ts rename to src/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.action.ts index a02c9749..f8652ede 100644 --- a/src/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.action.ts +++ b/src/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.action.ts @@ -2,7 +2,7 @@ import {userAction} from "@/safe-actions"; import {z} from "zod"; import {prisma} from "@/prisma"; -import {EmailFormSchema} from "@/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.schema"; +import {EmailFormSchema} from "@/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.schema"; export const updateEmailSettingsAction = userAction diff --git a/src/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.schema.ts b/src/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.schema.ts similarity index 100% rename from src/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/email-form.schema.ts rename to src/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/email-form.schema.ts diff --git a/src/components/wrappers/Dashboard/Settings/SettingsEmailTab/SettingsEmailTab.tsx b/src/components/wrappers/Dashboard/admin/AdminEmailTab/SettingsEmailTab.tsx similarity index 94% rename from src/components/wrappers/Dashboard/Settings/SettingsEmailTab/SettingsEmailTab.tsx rename to src/components/wrappers/Dashboard/admin/AdminEmailTab/SettingsEmailTab.tsx index 74a51d7d..4a6ef918 100644 --- a/src/components/wrappers/Dashboard/Settings/SettingsEmailTab/SettingsEmailTab.tsx +++ b/src/components/wrappers/Dashboard/admin/AdminEmailTab/SettingsEmailTab.tsx @@ -1,4 +1,4 @@ -import {EmailForm} from "@/components/wrappers/Dashboard/Settings/SettingsEmailTab/EmailForm/EmailForm"; +import {EmailForm} from "@/components/wrappers/Dashboard/admin/AdminEmailTab/EmailForm/EmailForm"; import {Settings} from "@prisma/client"; import {Send} from "lucide-react"; import {ButtonWithLoading} from "@/components/wrappers/Button/ButtonWithLoading/ButtonWithLoading"; diff --git a/src/components/wrappers/Dashboard/Settings/SettingsStorageTab/SettingsStorageTab.tsx b/src/components/wrappers/Dashboard/admin/AdminStorageTab/SettingsStorageTab.tsx similarity index 94% rename from src/components/wrappers/Dashboard/Settings/SettingsStorageTab/SettingsStorageTab.tsx rename to src/components/wrappers/Dashboard/admin/AdminStorageTab/SettingsStorageTab.tsx index 82c781e8..cf295c04 100644 --- a/src/components/wrappers/Dashboard/Settings/SettingsStorageTab/SettingsStorageTab.tsx +++ b/src/components/wrappers/Dashboard/admin/AdminStorageTab/SettingsStorageTab.tsx @@ -2,7 +2,7 @@ import {Alert, AlertDescription, AlertTitle} from "@/components/ui/alert"; import {Info, Send, ShieldCheck} from "lucide-react"; import {Switch} from "@/components/ui/switch"; import {Label} from "@/components/ui/label"; -import {StorageS3Form} from "@/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/StorageS3Form"; +import {StorageS3Form} from "@/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/StorageS3Form"; import {useState} from "react"; import {Settings} from "@prisma/client"; import {ButtonWithLoading} from "@/components/wrappers/Button/ButtonWithLoading/ButtonWithLoading"; @@ -13,7 +13,7 @@ import {updateUserAction} from "@/components/wrappers/Dashboard/Profile/UserForm import {useRouter} from "next/navigation"; import { updateStorageSettingsAction -} from "@/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.action"; +} from "@/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.action"; export type SettingsStorageTabProps = { diff --git a/src/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/StorageS3Form.tsx b/src/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/StorageS3Form.tsx similarity index 96% rename from src/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/StorageS3Form.tsx rename to src/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/StorageS3Form.tsx index 755cde19..93d91007 100644 --- a/src/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/StorageS3Form.tsx +++ b/src/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/StorageS3Form.tsx @@ -13,12 +13,12 @@ import {TooltipProvider} from "@/components/ui/tooltip"; import { S3FormSchema, S3FormType -} from "@/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.schema"; +} from "@/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.schema"; import {useRouter} from "next/navigation"; import {toast} from "sonner"; import { updateS3SettingsAction -} from "@/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.action"; +} from "@/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.action"; export type S3FormProps = { defaultValues?: S3FormType; diff --git a/src/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.action.ts b/src/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.action.ts similarity index 92% rename from src/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.action.ts rename to src/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.action.ts index 2c28638e..fdb549b7 100644 --- a/src/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.action.ts +++ b/src/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.action.ts @@ -5,7 +5,7 @@ import {prisma} from "@/prisma"; import { S3FormSchema, StorageSwitchSchema -} from "@/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.schema"; +} from "@/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.schema"; export const updateS3SettingsAction = userAction diff --git a/src/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.schema.ts b/src/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.schema.ts similarity index 100% rename from src/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.schema.ts rename to src/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.schema.ts diff --git a/src/components/wrappers/Dashboard/admin/admin-tabs.tsx b/src/components/wrappers/Dashboard/admin/admin-tabs.tsx new file mode 100644 index 00000000..b817efc2 --- /dev/null +++ b/src/components/wrappers/Dashboard/admin/admin-tabs.tsx @@ -0,0 +1,42 @@ +"use client" + +import {User, Settings} from "@prisma/client"; +import {Tabs, TabsContent, TabsList, TabsTrigger} from "@/components/ui/tabs"; +import {SettingsEmailTab} from "@/components/wrappers/Dashboard/admin/AdminEmailTab/SettingsEmailTab"; +import {SettingsStorageTab} from "@/components/wrappers/Dashboard/admin/AdminStorageTab/SettingsStorageTab"; +import {AdminUsersTable} from "@/components/wrappers/Dashboard/admin/admin-user-table"; + + +export type AdminTabsProps = { + currentUser: User; + users: User[]; + settings: Settings; +} + +export const AdminTabs = (props: AdminTabsProps) => { + + const {currentUser, users, settings} = props; + + return ( + + + + + Users + Email + Storage + + + + + + + + + + + + + + ) +} diff --git a/src/components/wrappers/Dashboard/admin/admin-user-table.tsx b/src/components/wrappers/Dashboard/admin/admin-user-table.tsx new file mode 100644 index 00000000..229482af --- /dev/null +++ b/src/components/wrappers/Dashboard/admin/admin-user-table.tsx @@ -0,0 +1,92 @@ +import {flexRender, Row, RowData} from "@tanstack/react-table"; + +import {User} from "@prisma/client"; +import {DataTableWithPagination} from "@/components/wrappers/table/data-table-with-pagination"; +import {usersColumns} from "@/components/wrappers/Dashboard/Settings/SettingsUsersTab/columns-users"; +import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table"; +import {cn} from "@/lib/utils"; + +export type AdminUsersTableProps = { + currentUser: User; + users: User[] +} + +export const AdminUsersTable = (props: AdminUsersTableProps) => { + + const {currentUser, users} = props; + + return ( +
+
+

List of Portabase's users

+
+
+ +
+
+ ) +} + + +export type usersDataTableProps = { + currentUser: User; + table: any, +} + +export const UsersDataTable = ({currentUser, table}: usersDataTableProps) => { + + return ( +
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ) + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row: Row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} + + ))} + + ))) : ( + + + No results. + + + )} + +
+
+ ) +} diff --git a/src/components/wrappers/Database/CronButton/CronButton.tsx b/src/components/wrappers/Database/CronButton/CronButton.tsx index e94891e4..8b11c887 100644 --- a/src/components/wrappers/Database/CronButton/CronButton.tsx +++ b/src/components/wrappers/Database/CronButton/CronButton.tsx @@ -17,7 +17,7 @@ import {useState} from "react"; import {useMutation} from "@tanstack/react-query"; import { updateStorageSettingsAction -} from "@/components/wrappers/Dashboard/Settings/SettingsStorageTab/StorageS3Form/s3-form.action"; +} from "@/components/wrappers/Dashboard/admin/AdminStorageTab/StorageS3Form/s3-form.action"; import {toast} from "sonner"; import {useRouter} from "next/navigation"; import {Database} from "@prisma/client"; diff --git a/src/components/wrappers/table/data-table-with-pagination.tsx b/src/components/wrappers/table/data-table-with-pagination.tsx index 7e693805..ca759b42 100644 --- a/src/components/wrappers/table/data-table-with-pagination.tsx +++ b/src/components/wrappers/table/data-table-with-pagination.tsx @@ -5,16 +5,21 @@ import {useState} from "react"; import { ColumnDef, getCoreRowModel, getPaginationRowModel, getSortedRowModel, SortingState, useReactTable } from "@tanstack/react-table" -import {DataTable} from "@/components/wrappers/table/data-table"; +import {DataTable as BaseDataTable} from "@/components/wrappers/table/data-table"; import {TablePagination} from "@/components/wrappers/table/table-pagination"; interface DataTableProps { columns: ColumnDef[] data: TData[] extendedProps?: any + DataTable?: any + dataTableProps?: any } -export function DataTableWithPagination({columns, data, extendedProps}: DataTableProps) { +export function DataTableWithPagination(props: DataTableProps) { + + const {columns, data, extendedProps, DataTable = BaseDataTable, dataTableProps} = props; + const [sorting, setSorting] = useState([]) @@ -35,7 +40,7 @@ export function DataTableWithPagination({columns, data, extendedP return (
- +
) diff --git a/src/components/wrappers/table/data-table.tsx b/src/components/wrappers/table/data-table.tsx index 2ff0cf5c..5e698128 100644 --- a/src/components/wrappers/table/data-table.tsx +++ b/src/components/wrappers/table/data-table.tsx @@ -1,5 +1,6 @@ import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table"; -import {flexRender} from "@tanstack/react-table"; +import {flexRender, Row, RowData} from "@tanstack/react-table"; +import {cn} from "@/lib/utils"; export type dataTableProps = { table: any, @@ -30,21 +31,25 @@ export const DataTable = ({table}: dataTableProps) => { {table.getRowModel().rows?.length ? ( - table.getRowModel().rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender( - cell.column.columnDef.cell, - cell.getContext(), - )} - - ))} - - )) + table.getRowModel().rows.map((row: Row) => { + console.log("row.original",row.original.id) + return( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} + + ))} + + ) + }) ) : (