From 318bccc5c0660ab4661d6e4c42ae6168c2bfac2b Mon Sep 17 00:00:00 2001 From: Luc Date: Wed, 18 Dec 2024 21:35:42 +0100 Subject: [PATCH] Update geoip & improve settings Update settings sidebar --- web/src/api/geoip.ts | 10 +- web/src/components/settings/BuildDetails.tsx | 73 ++++---- .../settings/IntelligenceDetails.tsx | 5 +- web/src/components/settings/SearchDetails.tsx | 29 ++- .../components/settings/StorageDetails.tsx | 82 ++++---- web/src/components/settings/nav.tsx | 81 ++++++++ web/src/layouts/SidebarPage.tsx | 44 +++++ web/src/layouts/SimpleCenterPage.tsx | 5 +- web/src/routeTree.gen.ts | 176 +++++++++++++++--- web/src/routes/items/index.tsx | 2 +- web/src/routes/search/index.tsx | 2 +- web/src/routes/sessions.tsx | 26 --- web/src/routes/settings/build.tsx | 17 ++ web/src/routes/settings/index.tsx | 17 +- web/src/routes/settings/intelligence.tsx | 17 ++ web/src/routes/settings/pat.tsx | 19 ++ web/src/routes/settings/search.tsx | 21 +++ web/src/routes/settings/sessions.tsx | 17 ++ web/src/routes/settings/storage.tsx | 17 ++ 19 files changed, 486 insertions(+), 174 deletions(-) create mode 100644 web/src/components/settings/nav.tsx create mode 100644 web/src/layouts/SidebarPage.tsx delete mode 100644 web/src/routes/sessions.tsx create mode 100644 web/src/routes/settings/build.tsx create mode 100644 web/src/routes/settings/intelligence.tsx create mode 100644 web/src/routes/settings/pat.tsx create mode 100644 web/src/routes/settings/search.tsx create mode 100644 web/src/routes/settings/sessions.tsx create mode 100644 web/src/routes/settings/storage.tsx diff --git a/web/src/api/geoip.ts b/web/src/api/geoip.ts index b54475c..a173846 100644 --- a/web/src/api/geoip.ts +++ b/web/src/api/geoip.ts @@ -1,7 +1,5 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query'; -import { getHttp } from './core'; - type GeoIpResponse = { ip_address: string; latitude: number; @@ -21,9 +19,11 @@ type GeoIpResponse = { export const getGeoIp = (ip: string): UseQueryOptions => ({ queryKey: ['geoip', ip], - queryFn: getHttp('/api/geoip', { - auth: 'include', - }), + queryFn: async () => { + const response = await fetch(`https://api.geoip.rs/?ip=${ip}`); + + return (await response.json()) as GeoIpResponse; + }, }); export function useGeoIp(ip: string) { diff --git a/web/src/components/settings/BuildDetails.tsx b/web/src/components/settings/BuildDetails.tsx index 11240a6..6edcbe3 100644 --- a/web/src/components/settings/BuildDetails.tsx +++ b/web/src/components/settings/BuildDetails.tsx @@ -13,49 +13,40 @@ export const BuildDetails = () => { instanceSettings.build_info.git_hash; return ( -
-

Build Details

-
- {instanceVersion?.update_available ? ( -
-
Update available
-
- You are running{' '} - - {instanceVersion?.version} - {' '} - but{' '} - - {instanceVersion?.latest} - {' '} - is available! -
-
- ) : ( -
You are on the latest
- )} -
- -
- Running on - {instanceSettings?.build_info.target} -
-
- Version - v{instanceSettings?.build_info.version} -
-
- Timestamp - {instanceSettings?.build_info.timestamp} +
+ {instanceVersion?.update_available ? ( +
+
Update available
+
+ You are running{' '} + {instanceVersion?.version}{' '} + but{' '} + {instanceVersion?.latest}{' '} + is available!
+ ) : ( +
You are on the latest
+ )} +
+ +
+ Running on + {instanceSettings?.build_info.target} +
+
+ Version + v{instanceSettings?.build_info.version} +
+
+ Timestamp + {instanceSettings?.build_info.timestamp} +
); diff --git a/web/src/components/settings/IntelligenceDetails.tsx b/web/src/components/settings/IntelligenceDetails.tsx index e3a2517..dc003a2 100644 --- a/web/src/components/settings/IntelligenceDetails.tsx +++ b/web/src/components/settings/IntelligenceDetails.tsx @@ -55,8 +55,7 @@ export const IntelligenceDetails = () => { } return ( -
-

Intelligence

+ <>
@@ -129,6 +128,6 @@ export const IntelligenceDetails = () => {
)} -
+ ); }; diff --git a/web/src/components/settings/SearchDetails.tsx b/web/src/components/settings/SearchDetails.tsx index 9b1418f..2411bae 100644 --- a/web/src/components/settings/SearchDetails.tsx +++ b/web/src/components/settings/SearchDetails.tsx @@ -22,22 +22,19 @@ export const SearchDetails = () => { }); return ( -
-

Search

-
-
- -

Meilisearch

-
-

- Meilisearch is the search engine that allows you to search - for items in the database. -

-
- -
+
+
+ +

Meilisearch

+
+

+ Meilisearch is the search engine that allows you to search for + items in the database. +

+
+
); diff --git a/web/src/components/settings/StorageDetails.tsx b/web/src/components/settings/StorageDetails.tsx index ad1aed9..3d61954 100644 --- a/web/src/components/settings/StorageDetails.tsx +++ b/web/src/components/settings/StorageDetails.tsx @@ -15,54 +15,50 @@ export const StorageDetails = () => { } return ( -
-

Storage

-
-
-

S3-Compatible Object Storage

-

Your media is stored in S3-compatible object storage.

-
    - {( +
    +
    +

    S3-Compatible Object Storage

    +

    Your media is stored in S3-compatible object storage.

    +
      + {( + [ [ - [ - 'Storage Used', - prettyBytes( - storageStatistics?.bucket_disk_size ?? 0 - ), - ], - [ - 'Files', - storageStatistics?.bucket_file_count ?? 0, - ], - [ - 'Endpoint', - instanceSettings.modules.storage - .endpoint_url, - undefined, - ], - [ - 'Bucket', - instanceSettings.modules.storage.bucket, - , - ], - ] as const - ).map(([key, value, icon]) => ( -
    • - {key} - - {icon} - {value} - -
    • - ))} -
    -
    - {/*
    + 'Storage Used', + prettyBytes( + storageStatistics?.bucket_disk_size ?? 0 + ), + ], + [ + 'Files', + storageStatistics?.bucket_file_count ?? 0, + ], + [ + 'Endpoint', + instanceSettings.modules.storage.endpoint_url, + undefined, + ], + [ + 'Bucket', + instanceSettings.modules.storage.bucket, + , + ], + ] as const + ).map(([key, value, icon]) => ( +
  • + {key} + + {icon} + {value} + +
  • + ))} +
+
+ {/*
To setup storage you need to specify{' '} S3_ENDPOINT_URL, S3_BUCKET_NAME,{' '} S3_ACCESS_KEY, and S3_SECRET_KEY
*/} -
); }; diff --git a/web/src/components/settings/nav.tsx b/web/src/components/settings/nav.tsx new file mode 100644 index 0000000..879621d --- /dev/null +++ b/web/src/components/settings/nav.tsx @@ -0,0 +1,81 @@ +import { Link } from '@tanstack/react-router'; +import clsx from 'clsx'; +import { + LuBrain, + LuClock, + LuHardDrive, + LuKey, + LuScroll, + LuSearch, + LuSettings, +} from 'react-icons/lu'; + +export const SettingsNav = () => { + return ( +
    + {( + [ + ['', [['/settings', 'General', ]]], + [ + 'Instance Settings', + [ + ['/settings/search', 'Search', ], + [ + '/settings/intelligence', + 'Intelligence', + , + ], + ['/settings/storage', 'Storage', ], + ], + ], + [ + 'Authentication', + [ + ['/settings/sessions', 'Sessions', ], + [ + '/settings/pat', + 'Personal Access Token', + , + ], + ], + ], + [ + 'System', + [['/settings/build', 'Software Info', ]], + ], + ] as const + ).map(([group, items]) => ( +
    + {group != '' && ( +

    + {group} +

    + )} +
      + {items.map(([path, label, icon]) => ( +
    • + + {icon} + {label} + +
    • + ))} +
    +
    + ))} +
+ ); +}; diff --git a/web/src/layouts/SidebarPage.tsx b/web/src/layouts/SidebarPage.tsx new file mode 100644 index 0000000..dcf09cc --- /dev/null +++ b/web/src/layouts/SidebarPage.tsx @@ -0,0 +1,44 @@ +import type { ClassValue } from 'clsx'; +import { FC, PropsWithChildren, ReactNode, useEffect } from 'react'; + +import { cn } from '@/util/style'; +import { getTitle } from '@/util/title'; + +export type SidePageProperties = PropsWithChildren<{ + title: string; + width?: 'xl' | '2xl' | '3xl' | '4xl'; + suffix?: ReactNode; + className?: ClassValue; + sidebar?: ReactNode; +}>; + +export const SidePage: FC = ({ + children, + title, + width = '2xl', + suffix, + className, + sidebar, +}) => { + useEffect(() => { + document.title = getTitle(title); + }, [title]); + + return ( +
+ {sidebar &&
{sidebar}
} +
+
+

{title}

+ {suffix} +
+ {children} +
+
+ ); +}; diff --git a/web/src/layouts/SimpleCenterPage.tsx b/web/src/layouts/SimpleCenterPage.tsx index 99b2d2a..166572c 100644 --- a/web/src/layouts/SimpleCenterPage.tsx +++ b/web/src/layouts/SimpleCenterPage.tsx @@ -6,7 +6,7 @@ import { getTitle } from '@/util/title'; export type SCPageProperties = PropsWithChildren<{ title: string; - width?: 'xl' | '2xl' | '3xl' | '4xl'; + width?: 'xl' | '2xl' | '3xl' | '4xl' | '5xl'; suffix?: ReactNode; className?: ClassValue; }>; @@ -25,11 +25,12 @@ export const SCPage: FC = ({ return (
diff --git a/web/src/routeTree.gen.ts b/web/src/routeTree.gen.ts index 3eeed98..ab94d26 100644 --- a/web/src/routeTree.gen.ts +++ b/web/src/routeTree.gen.ts @@ -11,7 +11,6 @@ // Import Routes import { Route as rootRoute } from './routes/__root' -import { Route as SessionsImport } from './routes/sessions' import { Route as DebugImport } from './routes/debug' import { Route as CreateImport } from './routes/create' import { Route as AboutImport } from './routes/about' @@ -23,18 +22,18 @@ import { Route as ProductsIndexImport } from './routes/products/index' import { Route as LogsIndexImport } from './routes/logs/index' import { Route as ItemsIndexImport } from './routes/items/index' import { Route as UserUserIdImport } from './routes/user/$userId' +import { Route as SettingsStorageImport } from './routes/settings/storage' +import { Route as SettingsSessionsImport } from './routes/settings/sessions' +import { Route as SettingsSearchImport } from './routes/settings/search' +import { Route as SettingsPatImport } from './routes/settings/pat' +import { Route as SettingsIntelligenceImport } from './routes/settings/intelligence' +import { Route as SettingsBuildImport } from './routes/settings/build' import { Route as SettingsFieldsIndexImport } from './routes/settings/fields/index' import { Route as ItemItemIdIndexImport } from './routes/item/$itemId/index' import { Route as ItemItemIdEditImport } from './routes/item/$itemId/edit' // Create/Update Routes -const SessionsRoute = SessionsImport.update({ - id: '/sessions', - path: '/sessions', - getParentRoute: () => rootRoute, -} as any) - const DebugRoute = DebugImport.update({ id: '/debug', path: '/debug', @@ -101,6 +100,42 @@ const UserUserIdRoute = UserUserIdImport.update({ getParentRoute: () => rootRoute, } as any) +const SettingsStorageRoute = SettingsStorageImport.update({ + id: '/settings/storage', + path: '/settings/storage', + getParentRoute: () => rootRoute, +} as any) + +const SettingsSessionsRoute = SettingsSessionsImport.update({ + id: '/settings/sessions', + path: '/settings/sessions', + getParentRoute: () => rootRoute, +} as any) + +const SettingsSearchRoute = SettingsSearchImport.update({ + id: '/settings/search', + path: '/settings/search', + getParentRoute: () => rootRoute, +} as any) + +const SettingsPatRoute = SettingsPatImport.update({ + id: '/settings/pat', + path: '/settings/pat', + getParentRoute: () => rootRoute, +} as any) + +const SettingsIntelligenceRoute = SettingsIntelligenceImport.update({ + id: '/settings/intelligence', + path: '/settings/intelligence', + getParentRoute: () => rootRoute, +} as any) + +const SettingsBuildRoute = SettingsBuildImport.update({ + id: '/settings/build', + path: '/settings/build', + getParentRoute: () => rootRoute, +} as any) + const SettingsFieldsIndexRoute = SettingsFieldsIndexImport.update({ id: '/settings/fields/', path: '/settings/fields/', @@ -158,11 +193,46 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DebugImport parentRoute: typeof rootRoute } - '/sessions': { - id: '/sessions' - path: '/sessions' - fullPath: '/sessions' - preLoaderRoute: typeof SessionsImport + '/settings/build': { + id: '/settings/build' + path: '/settings/build' + fullPath: '/settings/build' + preLoaderRoute: typeof SettingsBuildImport + parentRoute: typeof rootRoute + } + '/settings/intelligence': { + id: '/settings/intelligence' + path: '/settings/intelligence' + fullPath: '/settings/intelligence' + preLoaderRoute: typeof SettingsIntelligenceImport + parentRoute: typeof rootRoute + } + '/settings/pat': { + id: '/settings/pat' + path: '/settings/pat' + fullPath: '/settings/pat' + preLoaderRoute: typeof SettingsPatImport + parentRoute: typeof rootRoute + } + '/settings/search': { + id: '/settings/search' + path: '/settings/search' + fullPath: '/settings/search' + preLoaderRoute: typeof SettingsSearchImport + parentRoute: typeof rootRoute + } + '/settings/sessions': { + id: '/settings/sessions' + path: '/settings/sessions' + fullPath: '/settings/sessions' + preLoaderRoute: typeof SettingsSessionsImport + parentRoute: typeof rootRoute + } + '/settings/storage': { + id: '/settings/storage' + path: '/settings/storage' + fullPath: '/settings/storage' + preLoaderRoute: typeof SettingsStorageImport parentRoute: typeof rootRoute } '/user/$userId': { @@ -239,7 +309,12 @@ export interface FileRoutesByFullPath { '/about': typeof AboutRoute '/create': typeof CreateRoute '/debug': typeof DebugRoute - '/sessions': typeof SessionsRoute + '/settings/build': typeof SettingsBuildRoute + '/settings/intelligence': typeof SettingsIntelligenceRoute + '/settings/pat': typeof SettingsPatRoute + '/settings/search': typeof SettingsSearchRoute + '/settings/sessions': typeof SettingsSessionsRoute + '/settings/storage': typeof SettingsStorageRoute '/user/$userId': typeof UserUserIdRoute '/items': typeof ItemsIndexRoute '/logs': typeof LogsIndexRoute @@ -257,7 +332,12 @@ export interface FileRoutesByTo { '/about': typeof AboutRoute '/create': typeof CreateRoute '/debug': typeof DebugRoute - '/sessions': typeof SessionsRoute + '/settings/build': typeof SettingsBuildRoute + '/settings/intelligence': typeof SettingsIntelligenceRoute + '/settings/pat': typeof SettingsPatRoute + '/settings/search': typeof SettingsSearchRoute + '/settings/sessions': typeof SettingsSessionsRoute + '/settings/storage': typeof SettingsStorageRoute '/user/$userId': typeof UserUserIdRoute '/items': typeof ItemsIndexRoute '/logs': typeof LogsIndexRoute @@ -276,7 +356,12 @@ export interface FileRoutesById { '/about': typeof AboutRoute '/create': typeof CreateRoute '/debug': typeof DebugRoute - '/sessions': typeof SessionsRoute + '/settings/build': typeof SettingsBuildRoute + '/settings/intelligence': typeof SettingsIntelligenceRoute + '/settings/pat': typeof SettingsPatRoute + '/settings/search': typeof SettingsSearchRoute + '/settings/sessions': typeof SettingsSessionsRoute + '/settings/storage': typeof SettingsStorageRoute '/user/$userId': typeof UserUserIdRoute '/items/': typeof ItemsIndexRoute '/logs/': typeof LogsIndexRoute @@ -296,7 +381,12 @@ export interface FileRouteTypes { | '/about' | '/create' | '/debug' - | '/sessions' + | '/settings/build' + | '/settings/intelligence' + | '/settings/pat' + | '/settings/search' + | '/settings/sessions' + | '/settings/storage' | '/user/$userId' | '/items' | '/logs' @@ -313,7 +403,12 @@ export interface FileRouteTypes { | '/about' | '/create' | '/debug' - | '/sessions' + | '/settings/build' + | '/settings/intelligence' + | '/settings/pat' + | '/settings/search' + | '/settings/sessions' + | '/settings/storage' | '/user/$userId' | '/items' | '/logs' @@ -330,7 +425,12 @@ export interface FileRouteTypes { | '/about' | '/create' | '/debug' - | '/sessions' + | '/settings/build' + | '/settings/intelligence' + | '/settings/pat' + | '/settings/search' + | '/settings/sessions' + | '/settings/storage' | '/user/$userId' | '/items/' | '/logs/' @@ -349,7 +449,12 @@ export interface RootRouteChildren { AboutRoute: typeof AboutRoute CreateRoute: typeof CreateRoute DebugRoute: typeof DebugRoute - SessionsRoute: typeof SessionsRoute + SettingsBuildRoute: typeof SettingsBuildRoute + SettingsIntelligenceRoute: typeof SettingsIntelligenceRoute + SettingsPatRoute: typeof SettingsPatRoute + SettingsSearchRoute: typeof SettingsSearchRoute + SettingsSessionsRoute: typeof SettingsSessionsRoute + SettingsStorageRoute: typeof SettingsStorageRoute UserUserIdRoute: typeof UserUserIdRoute ItemsIndexRoute: typeof ItemsIndexRoute LogsIndexRoute: typeof LogsIndexRoute @@ -367,7 +472,12 @@ const rootRouteChildren: RootRouteChildren = { AboutRoute: AboutRoute, CreateRoute: CreateRoute, DebugRoute: DebugRoute, - SessionsRoute: SessionsRoute, + SettingsBuildRoute: SettingsBuildRoute, + SettingsIntelligenceRoute: SettingsIntelligenceRoute, + SettingsPatRoute: SettingsPatRoute, + SettingsSearchRoute: SettingsSearchRoute, + SettingsSessionsRoute: SettingsSessionsRoute, + SettingsStorageRoute: SettingsStorageRoute, UserUserIdRoute: UserUserIdRoute, ItemsIndexRoute: ItemsIndexRoute, LogsIndexRoute: LogsIndexRoute, @@ -394,7 +504,12 @@ export const routeTree = rootRoute "/about", "/create", "/debug", - "/sessions", + "/settings/build", + "/settings/intelligence", + "/settings/pat", + "/settings/search", + "/settings/sessions", + "/settings/storage", "/user/$userId", "/items/", "/logs/", @@ -421,8 +536,23 @@ export const routeTree = rootRoute "/debug": { "filePath": "debug.tsx" }, - "/sessions": { - "filePath": "sessions.tsx" + "/settings/build": { + "filePath": "settings/build.tsx" + }, + "/settings/intelligence": { + "filePath": "settings/intelligence.tsx" + }, + "/settings/pat": { + "filePath": "settings/pat.tsx" + }, + "/settings/search": { + "filePath": "settings/search.tsx" + }, + "/settings/sessions": { + "filePath": "settings/sessions.tsx" + }, + "/settings/storage": { + "filePath": "settings/storage.tsx" }, "/user/$userId": { "filePath": "user/$userId.tsx" diff --git a/web/src/routes/items/index.tsx b/web/src/routes/items/index.tsx index b221fac..1edc8da 100644 --- a/web/src/routes/items/index.tsx +++ b/web/src/routes/items/index.tsx @@ -29,7 +29,7 @@ export const ItemsOverviewPage = () => { return (