Skip to content

Commit

Permalink
#93 Adding administration portal
Browse files Browse the repository at this point in the history
  • Loading branch information
santthosh committed Jun 30, 2024
1 parent 18b1dd4 commit d5a2d1f
Show file tree
Hide file tree
Showing 28 changed files with 232 additions and 200 deletions.
37 changes: 12 additions & 25 deletions src/app/admin/AdminSideNavigation.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,30 @@
'use client';

import { Avatar, Badge, Button, Card, Sidebar } from 'flowbite-react';
import { Badge, Sidebar } from 'flowbite-react';
import {
HiColorSwatch,
HiChatAlt2,
HiFolder,
HiCog,
HiChartBar,
HiPuzzle,
HiShoppingBag,
HiChip,
HiDatabase,
HiShoppingBag,
} from 'react-icons/hi';
import { Assistant } from '@/app/types/assistant';
import Image from 'next/image';
import { getImageHash } from '@/app/utils/hash';
import React, { useContext } from 'react';
import AssistantContext from '@/app/assistants/[id]/AssistantContext';
import Link from 'next/link';
import React from 'react';
import { HiPuzzlePiece } from 'react-icons/hi2';

export default function AdminSideNavigation() {
const { assistant } = useContext(AssistantContext);

const getAssistantComponentUrl = (
assistant: Assistant,
component: string
) => {
if (!assistant) return '';
return `/assistants/${assistant.id}/${component}`;
};

return (
<div className='flex flex-auto' aria-label='Sidebar'>
<Sidebar
aria-label='Sidebar'
className='z-40 flex flex-auto items-center justify-center'
>
<Sidebar.Items className='w-60 bg-gray-100'>
<Sidebar.Item className={'pt-5'}>
Administration
</Sidebar.Item>
<Sidebar.ItemGroup>
<Sidebar.Item className={'pt-5 text-xl font-bold'}>
Administration
</Sidebar.Item>
</Sidebar.ItemGroup>
<Sidebar.ItemGroup>
<Sidebar.Item href={'/admin/dashboard'} icon={HiChartBar}>
Dashboard
Expand All @@ -51,13 +35,16 @@ export default function AdminSideNavigation() {
<Sidebar.Item href={'/admin/theme'} icon={HiColorSwatch}>
Theme
</Sidebar.Item>
<Sidebar.Item href={'/admin/marketplace'} icon={HiShoppingBag}>
Marketplace
</Sidebar.Item>
<Sidebar.Item href={'/admin/providers/model'} icon={HiChip}>
Model Providers
</Sidebar.Item>
<Sidebar.Item href={'/admin/providers/data'} icon={HiDatabase}>
Data Providers
</Sidebar.Item>
<Sidebar.Item href={'/settings'} icon={HiCog}>
<Sidebar.Item href={'/admin/settings'} icon={HiCog}>
Settings
</Sidebar.Item>
</Sidebar.ItemGroup>
Expand Down
42 changes: 42 additions & 0 deletions src/app/admin/AdminSideNavigationContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use client';

import React, { useEffect, useState } from 'react';
import { Button } from 'flowbite-react';
import { HiMenuAlt2 } from 'react-icons/hi';
import AdminSideNavigation from '@/app/admin/AdminSideNavigation';

export default function AdminSideNavigationContainer() {
const [sideBarCss, setSideBarCss] = useState(
'fixed left-0 w-64 transition-transform -translate-x-full sm:translate-x-0 bg-red-50'
);

useEffect(() => {}, [sideBarCss]);

const handleToggleSideBar = () => {
if (sideBarCss.includes('sm:translate-x-0')) {
setSideBarCss(
'float left-0 w-64 transition-transform sm:translate-x-full bg-red-50'
);
} else {
setSideBarCss(
'fixed left-0 w-64 transition-transform -translate-x-full sm:translate-x-0 bg-red-50'
);
}
};

return (
<>
<Button
pill
color={'light'}
onClick={handleToggleSideBar}
className='m-2 border-0 bg-gray-50 sm:hidden'
>
<HiMenuAlt2 className='h-5 w-5' />
</Button>
<aside id='logo-sidebar' className={sideBarCss} aria-label='Sidebar'>
<AdminSideNavigation />
</aside>
</>
);
}
105 changes: 17 additions & 88 deletions src/app/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,99 +1,28 @@
'use client';

import React, { useEffect, useState } from 'react';
import React from 'react';
import { Toaster } from 'react-hot-toast';
import { Header } from '@/components/header';
import { Alert, Button, Sidebar, Spinner } from 'flowbite-react';
import {
HiArrowSmRight,
HiChartPie,
HiInbox,
HiInformationCircle,
HiMenuAlt2,
HiShoppingBag,
HiTable,
HiUser,
HiViewBoards,
} from 'react-icons/hi';
import { PageFooter } from '@/components/footer';
import AdminSideNavigation from '@/app/admin/AdminSideNavigation';
import { useUser } from '@auth0/nextjs-auth0/client';
import { useRouter } from 'next/navigation';
import Unauthenticated from '@/components/unauthenticated';

export default function AdminLayout({
import { Header } from '@/components/Header';
import { PageFooter } from '@/components/Footer';
import { redirect } from 'next/navigation';
import AdminSideNavigationContainer from '@/app/admin/AdminSideNavigationContainer';
import { getSession } from '@auth0/nextjs-auth0';
import AccessDenied from '@/components/AccessDenied';
import { isAdminUser } from '@/utils/user';

export default async function AdminLayout({
children,
}: {
children: React.ReactNode;
}) {
// @ts-ignore
const { user, error, isLoading } = useUser();

const [sideBarCss, setSideBarCss] = useState(
'fixed left-0 w-64 transition-transform -translate-x-full sm:translate-x-0 bg-red-50'
);

useEffect(() => {}, [sideBarCss]);
const session = await getSession();
if (!session) redirect('/api/auth/login?returnTo=/admin/dashboard');
const { user } = session;

const { push } = useRouter();

useEffect(() => {
console.log(user);
if (!isLoading && !user) {
push('/api/auth/login?returnTo=/admin/dashboard');
}
}, [isLoading]);

const handleToggleSideBar = () => {
if (sideBarCss.includes('sm:translate-x-0')) {
setSideBarCss(
'float left-0 w-64 transition-transform sm:translate-x-full bg-red-50'
);
} else {
setSideBarCss(
'fixed left-0 w-64 transition-transform -translate-x-full sm:translate-x-0 bg-red-50'
);
}
};

if (isLoading)
return (
<div className='bg-grey flex min-h-[calc(100vh-100px)] items-center justify-center'>
<Spinner />
</div>
);

if (!user) return <Unauthenticated />;

const isUserAuthorized = function () {
console.log(process.env.NEXT_PUBLIC_ADMIN_USERS);
if (process.env.NEXT_PUBLIC_ADMIN_USERS) {
const allowedAdmins = JSON.parse(process.env.NEXT_PUBLIC_ADMIN_USERS);

console.log(allowedAdmins);

return user && allowedAdmins.includes(user.sub);
} else {
return false;
}
};

return isUserAuthorized() ? (
return isAdminUser(user) ? (
<div className='p min-h-[calc(100vh-100px)] justify-center'>
<div className={'bg-gray-50 dark:bg-gray-900'}>
<Header />
<Toaster position='top-center' />
<Button
pill
color={'light'}
onClick={handleToggleSideBar}
className='m-2 border-0 bg-gray-50 sm:hidden'
>
<HiMenuAlt2 className='h-5 w-5' />
</Button>
<aside id='logo-sidebar' className={sideBarCss} aria-label='Sidebar'>
<AdminSideNavigation />
</aside>
<Header />
<AdminSideNavigationContainer />
<div
className={
'm-4 min-h-[calc(100vh-100px)] items-center justify-center sm:ml-64'
Expand All @@ -105,6 +34,6 @@ export default function AdminLayout({
</div>
</div>
) : (
<>Access Denied.</>
<AccessDenied />
);
}
12 changes: 12 additions & 0 deletions src/app/admin/marketplace/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

export default function Marketplace() {
return (
<div className='stack ml-5 mt-5 items-center justify-center'>
<h3 className='text-3xl font-bold dark:text-white'>Marketplace</h3>
<p className={'pb-4 text-sm text-gray-400'}>
Marketplace settings and configuration
</p>
</div>
);
}
1 change: 1 addition & 0 deletions src/app/api/auth/[auth0]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
getSession,
handleAuth,
handleLogin,
handleLogout,
handleProfile,
} from '@auth0/nextjs-auth0';
import prisma from '@/app/api/utils/prisma';
Expand Down
2 changes: 1 addition & 1 deletion src/app/assistants/[id]/chat/ChatAgent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Assistant } from '@/app/types/assistant';
import AssistantContext from '@/app/assistants/[id]/AssistantContext';
import ChatPopupFrame from '@/app/assistants/[id]/chat/ChatPopupFrame';
import { useRouter } from 'next/navigation';
import Unauthenticated from '@/components/unauthenticated';
import Unauthenticated from '@/components/Unauthenticated';

export interface ChatAgentProps {
assistant_id: string;
Expand Down
2 changes: 1 addition & 1 deletion src/app/assistants/[id]/chat/ChatConversationStarters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function ChatConversationStarters(
size={'md'}
key={conversationStarter.id}
className={'bg-gray-100 p-2 text-gray-500'}
onClick={(e:any) => {
onClick={(e: any) => {
props.onClick
? props.onClick(conversationStarter.prompt)
: undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/app/assistants/[id]/chat/ChatPageContextWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ChatPage from '@/app/assistants/[id]/chat/ChatPage';
import { Spinner } from 'flowbite-react';
import AssistantContext from '@/app/assistants/[id]/AssistantContext';
import { useRouter } from 'next/navigation';
import Unauthenticated from '@/components/unauthenticated';
import Unauthenticated from '@/components/Unauthenticated';

export default function ChatPageContextWrapper(props: { assistantId: string }) {
let { assistantLoading, assistantResponse, assistantEmpty, reload } =
Expand Down
3 changes: 1 addition & 2 deletions src/app/assistants/[id]/chat/ChatPageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import Image from 'next/image';
import { useContext } from 'react';
import AssistantContext from '@/app/assistants/[id]/AssistantContext';
import { getImageHash } from '@/app/utils/hash';
import { UserProfile } from '@/components/user-profile';
import { useUser } from '@auth0/nextjs-auth0/client';
import UserDropdown from '@/components/user-dropdown';
import UserDropdown from '@/components/UserDropdown';
import { getPrimaryBackgroundColor } from '@/app/utils/assistant';

export function ChatPageHeader() {
Expand Down
2 changes: 1 addition & 1 deletion src/app/assistants/[id]/chat/ChatWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Assistant } from '@/app/types/assistant';
import AssistantContext from '@/app/assistants/[id]/AssistantContext';
import ChatPopupFrame from '@/app/assistants/[id]/chat/ChatPopupFrame';
import { useRouter } from 'next/navigation';
import Unauthenticated from '@/components/unauthenticated';
import Unauthenticated from '@/components/Unauthenticated';

export interface ChatWindowProps {
assistant_id: string;
Expand Down
2 changes: 0 additions & 2 deletions src/app/assistants/[id]/customize/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ import { Button, Table } from 'flowbite-react';
import AvatarCropUpload from '@/app/assistants/[id]/customize/AvatarCropUpload';
import ProfileCropUpload from '@/app/assistants/[id]/customize/ProfileCropUpload';
import AssistantContext from '@/app/assistants/[id]/AssistantContext';
import ChatPopup from '@/app/assistants/[id]/chat/ChatPopup';
import ThemeSelections from '@/app/assistants/[id]/customize/ThemeSelections';
import ResetToDefaultsAlert from '@/app/assistants/[id]/customize/ResetToDefaultsAlert';
import { EditInitialPrompt } from '@/app/assistants/[id]/customize/EditInitialPrompt';
import { EditMessageLabel } from '@/app/assistants/[id]/customize/EditMessageLabel';
import ChatPopupFrame from '@/app/assistants/[id]/chat/ChatPopupFrame';
import ChatPage from '@/app/assistants/[id]/chat/ChatPage';
import { EditConversationStarters } from '@/app/assistants/[id]/customize/EditConversationStarters';

Expand Down
4 changes: 2 additions & 2 deletions src/app/assistants/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Header } from '@/components/header';
import { Header } from '@/components/Header';
import { Toaster } from 'react-hot-toast';
import { PageFooter } from '@/components/footer';
import { PageFooter } from '@/components/Footer';

export default function AdminLayout({
children,
Expand Down
6 changes: 3 additions & 3 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Header } from '@/components/header';
import { PageFooter } from '@/components/footer';
import Home from '@/components/home';
import { Header } from '@/components/Header';
import { PageFooter } from '@/components/Footer';
import Home from '@/components/Home';
import 'highlight.js/styles/github.css';

export default function Landing() {
Expand Down
4 changes: 2 additions & 2 deletions src/app/settings/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Header } from '@/components/header';
import { Header } from '@/components/Header';
import { Toaster } from 'react-hot-toast';
import { PageFooter } from '@/components/footer';
import { PageFooter } from '@/components/Footer';

export default function SettingsLayout({
children,
Expand Down
20 changes: 20 additions & 0 deletions src/components/AccessDenied.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Alert } from 'flowbite-react';
import React from 'react';
import { Header } from '@/components/Header';
import { PageFooter } from '@/components/Footer';
import { HiFingerPrint } from 'react-icons/hi';

export default function AccessDenied() {
return (
<>
<Header />
<div className='bg-grey flex min-h-[calc(100vh-100px)] items-center justify-center'>
<Alert color='failure' icon={HiFingerPrint}>
<span className='font-medium'>Access Denied.</span> You are not
authorized to access this page.
</Alert>
</div>
<PageFooter />
</>
);
}
20 changes: 20 additions & 0 deletions src/components/AdministrationMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client';

import { DropdownDivider, DropdownItem } from 'flowbite-react';
import { HiFingerPrint } from 'react-icons/hi';

export const AdministrationMenu = function () {
return (
<>
<DropdownDivider />
<DropdownItem
icon={HiFingerPrint}
href={'/admin/dashboard'}
className={'text-orange-800'}
>
Administration
</DropdownItem>
<DropdownDivider />
</>
);
};
File renamed without changes.
Loading

0 comments on commit d5a2d1f

Please sign in to comment.