Skip to content

Commit

Permalink
Add "Admin" view (#104)
Browse files Browse the repository at this point in the history
# Add "Admin" view

## ♻️ Current situation & Problem
Admins need to be able to update static data and seed data.


## ⚙️ Release Notes 
* Add "Admin" view
* Update models package

![image](https://github.com/user-attachments/assets/6324d04d-bc49-4e55-9be4-cc22f1587a52)

### Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
arkadiuszbachorski authored Jan 19, 2025
1 parent 5f72377 commit 20f48af
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 7 deletions.
12 changes: 12 additions & 0 deletions modules/firebase/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import {
type GetUsersInformationOutput,
type UpdateUserInformationInput,
type UpdateUserInformationOutput,
type UpdateStaticDataInput,
type UpdateStaticDataOutput,
type DefaultSeedInput,
type DefaultSeedOutput,
} from '@stanfordbdhg/engagehf-models'
import { strategy } from '@stanfordspezi/spezi-web-design-system/utils/misc'
import {
Expand Down Expand Up @@ -286,6 +290,14 @@ export const getCallables = (functions: Functions) => ({
functions,
'dismissMessage',
),
updateStaticData: httpsCallable<
UpdateStaticDataInput,
UpdateStaticDataOutput
>(functions, 'updateStaticData'),
defaultSeed: httpsCallable<DefaultSeedInput, DefaultSeedOutput>(
functions,
'defaultSeed',
),
})

export const getDocData = async <T>(reference: DocumentReference<T>) => {
Expand Down
1 change: 1 addition & 0 deletions modules/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { PatientPageTab } from '@/routes/~_dashboard/~patients/~$id/~index'
export const routes = {
home: '/',
notifications: '/notifications',
admin: '/admin',
users: {
index: '/users',
user: (userId: string, resourceType: ResourceType) =>
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"prepush": "npm run lint:fix && tsc --noEmit"
},
"dependencies": {
"@stanfordbdhg/engagehf-models": "^0.4.0",
"@stanfordbdhg/engagehf-models": "^0.5.0",
"@stanfordspezi/spezi-web-design-system": "^0.3.0",
"@t3-oss/env-core": "^0.11.1",
"@tanstack/react-query": "^5.62.0",
Expand Down
27 changes: 27 additions & 0 deletions routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { Route as DashboardPatientsInviteImport } from './routes/~_dashboard/~pa
import { Route as DashboardUsersIndexImport } from './routes/~_dashboard/~users/~index'
import { Route as DashboardPatientsIndexImport } from './routes/~_dashboard/~patients/~index'
import { Route as DashboardNotificationsIndexImport } from './routes/~_dashboard/~notifications/~index'
import { Route as DashboardAdminIndexImport } from './routes/~_dashboard/~admin/~index'
import { Route as DashboardPatientsIdIndexImport } from './routes/~_dashboard/~patients/~$id/~index'

// Create/Update Routes
Expand Down Expand Up @@ -88,6 +89,12 @@ const DashboardNotificationsIndexRoute =
getParentRoute: () => DashboardRoute,
} as any)

const DashboardAdminIndexRoute = DashboardAdminIndexImport.update({
id: '/admin/',
path: '/admin/',
getParentRoute: () => DashboardRoute,
} as any)

const DashboardPatientsIdIndexRoute = DashboardPatientsIdIndexImport.update({
id: '/patients/$id/',
path: '/patients/$id/',
Expand Down Expand Up @@ -119,6 +126,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof SignInIndexImport
parentRoute: typeof rootRoute
}
'/_dashboard/admin/': {
id: '/_dashboard/admin/'
path: '/admin'
fullPath: '/admin'
preLoaderRoute: typeof DashboardAdminIndexImport
parentRoute: typeof DashboardImport
}
'/_dashboard/notifications/': {
id: '/_dashboard/notifications/'
path: '/notifications'
Expand Down Expand Up @@ -175,6 +189,7 @@ declare module '@tanstack/react-router' {

interface DashboardRouteChildren {
DashboardIndexRoute: typeof DashboardIndexRoute
DashboardAdminIndexRoute: typeof DashboardAdminIndexRoute
DashboardNotificationsIndexRoute: typeof DashboardNotificationsIndexRoute
DashboardPatientsIndexRoute: typeof DashboardPatientsIndexRoute
DashboardUsersIndexRoute: typeof DashboardUsersIndexRoute
Expand All @@ -186,6 +201,7 @@ interface DashboardRouteChildren {

const DashboardRouteChildren: DashboardRouteChildren = {
DashboardIndexRoute: DashboardIndexRoute,
DashboardAdminIndexRoute: DashboardAdminIndexRoute,
DashboardNotificationsIndexRoute: DashboardNotificationsIndexRoute,
DashboardPatientsIndexRoute: DashboardPatientsIndexRoute,
DashboardUsersIndexRoute: DashboardUsersIndexRoute,
Expand All @@ -203,6 +219,7 @@ export interface FileRoutesByFullPath {
'': typeof DashboardRouteWithChildren
'/': typeof DashboardIndexRoute
'/sign-in': typeof SignInIndexRoute
'/admin': typeof DashboardAdminIndexRoute
'/notifications': typeof DashboardNotificationsIndexRoute
'/patients': typeof DashboardPatientsIndexRoute
'/users': typeof DashboardUsersIndexRoute
Expand All @@ -215,6 +232,7 @@ export interface FileRoutesByFullPath {
export interface FileRoutesByTo {
'/': typeof DashboardIndexRoute
'/sign-in': typeof SignInIndexRoute
'/admin': typeof DashboardAdminIndexRoute
'/notifications': typeof DashboardNotificationsIndexRoute
'/patients': typeof DashboardPatientsIndexRoute
'/users': typeof DashboardUsersIndexRoute
Expand All @@ -229,6 +247,7 @@ export interface FileRoutesById {
'/_dashboard': typeof DashboardRouteWithChildren
'/_dashboard/': typeof DashboardIndexRoute
'/sign-in/': typeof SignInIndexRoute
'/_dashboard/admin/': typeof DashboardAdminIndexRoute
'/_dashboard/notifications/': typeof DashboardNotificationsIndexRoute
'/_dashboard/patients/': typeof DashboardPatientsIndexRoute
'/_dashboard/users/': typeof DashboardUsersIndexRoute
Expand All @@ -244,6 +263,7 @@ export interface FileRouteTypes {
| ''
| '/'
| '/sign-in'
| '/admin'
| '/notifications'
| '/patients'
| '/users'
Expand All @@ -255,6 +275,7 @@ export interface FileRouteTypes {
to:
| '/'
| '/sign-in'
| '/admin'
| '/notifications'
| '/patients'
| '/users'
Expand All @@ -267,6 +288,7 @@ export interface FileRouteTypes {
| '/_dashboard'
| '/_dashboard/'
| '/sign-in/'
| '/_dashboard/admin/'
| '/_dashboard/notifications/'
| '/_dashboard/patients/'
| '/_dashboard/users/'
Expand Down Expand Up @@ -305,6 +327,7 @@ export const routeTree = rootRoute
"filePath": "~_dashboard.tsx",
"children": [
"/_dashboard/",
"/_dashboard/admin/",
"/_dashboard/notifications/",
"/_dashboard/patients/",
"/_dashboard/users/",
Expand All @@ -321,6 +344,10 @@ export const routeTree = rootRoute
"/sign-in/": {
"filePath": "~sign-in/~index.tsx"
},
"/_dashboard/admin/": {
"filePath": "~_dashboard/~admin/~index.tsx",
"parent": "/_dashboard"
},
"/_dashboard/notifications/": {
"filePath": "~_dashboard/~notifications/~index.tsx",
"parent": "/_dashboard"
Expand Down
13 changes: 11 additions & 2 deletions routes/~_dashboard/MenuLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { UserType } from '@stanfordbdhg/engagehf-models'
import { MenuItem } from '@stanfordspezi/spezi-web-design-system/molecules/DashboardLayout'
import { useLocation } from '@tanstack/react-router'
import { Home, Users, Contact, Bell } from 'lucide-react'
import { Home, Users, Contact, Bell, MonitorCog } from 'lucide-react'
import { useHasUnreadNotification } from '@/modules/notifications/queries'
import { routes } from '@/modules/routes'

Expand All @@ -28,6 +28,8 @@ export const MenuLinks = ({ userType }: MenuLinksProps) => {

const { hasUnreadNotification } = useHasUnreadNotification()

const isRole = (roles: UserType[]) => roles.includes(userType)

return (
<>
<MenuItem
Expand All @@ -41,7 +43,7 @@ export const MenuLinks = ({ userType }: MenuLinksProps) => {
isHighlighted={hasUnreadNotification}
icon={<Bell />}
/>
{[UserType.admin, UserType.owner].includes(userType) && (
{isRole([UserType.admin, UserType.owner]) && (
<MenuItem
{...hrefProps(routes.users.index)}
label="Users"
Expand All @@ -53,6 +55,13 @@ export const MenuLinks = ({ userType }: MenuLinksProps) => {
label="Patients"
icon={<Contact />}
/>
{isRole([UserType.admin]) && (
<MenuItem
{...hrefProps(routes.admin)}
label="Admin"
icon={<MonitorCog />}
/>
)}
</>
)
}
70 changes: 70 additions & 0 deletions routes/~_dashboard/~admin/~index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//
// This source file is part of the Stanford Biodesign Digital Health ENGAGE-HF open-source project
//
// SPDX-FileCopyrightText: 2025 Stanford University and the project authors (see CONTRIBUTORS.md)
//
// SPDX-License-Identifier: MIT
//

import { UserType } from '@stanfordbdhg/engagehf-models'
import { Button } from '@stanfordspezi/spezi-web-design-system/components/Button'
import { toast } from '@stanfordspezi/spezi-web-design-system/components/Toaster'
import { PageTitle } from '@stanfordspezi/spezi-web-design-system/molecules/DashboardLayout'
import { useMutation } from '@tanstack/react-query'
import { createFileRoute } from '@tanstack/react-router'
import { MonitorCog } from 'lucide-react'
import { Helmet } from 'react-helmet'
import { callables, ensureType } from '@/modules/firebase/app'
import { DashboardLayout } from '../DashboardLayout'

const AdminPage = () => {
const updateStaticData = useMutation({
mutationFn: () => callables.updateStaticData({}),
onSuccess: () => toast.success('Successfully updated static data'),
onError: () => toast.error('Updating static data failed. Please try again'),
})

const seedData = useMutation({
mutationFn: () => callables.defaultSeed({}),
onSuccess: () => toast.success('Successfully seeded data'),
onError: () => toast.error('Seeding data failed. Please try again'),
})

return (
<DashboardLayout title={<PageTitle title="Admin" icon={<MonitorCog />} />}>
<Helmet>
<title>Admin</title>
</Helmet>
<div className="flex flex-col items-start gap-8">
<section className="flex flex-col items-start gap-2">
<Button
onClick={() => updateStaticData.mutate()}
isPending={updateStaticData.isPending}
>
Update static data
</Button>
<p className="text-sm font-light">
Updates static data, like medications, organizations and video
sections
</p>
</section>
<section className="flex flex-col items-start gap-2">
<Button
onClick={() => seedData.mutate()}
isPending={seedData.isPending}
>
Seed data
</Button>
<p className="text-sm font-light">
Seeds the application with test users
</p>
</section>
</div>
</DashboardLayout>
)
}

export const Route = createFileRoute('/_dashboard/admin/')({
component: AdminPage,
beforeLoad: () => ensureType([UserType.admin]),
})

0 comments on commit 20f48af

Please sign in to comment.