diff --git a/resources/scripts/api/getServers.ts b/resources/scripts/api/getServers.ts index c67322a78..499932376 100644 --- a/resources/scripts/api/getServers.ts +++ b/resources/scripts/api/getServers.ts @@ -1,9 +1,16 @@ import { rawDataToServerObject, Server } from '@/api/server/getServer'; import http, { getPaginationSet, PaginatedResult } from '@/api/http'; -export default (query?: string): Promise> => { +export default (query?: string, includeAdmin?: boolean): Promise> => { return new Promise((resolve, reject) => { - http.get(`/api/client`, { params: { include: [ 'allocation' ], query } }) + http.get(`/api/client`, { + params: { + include: [ 'allocation' ], + // eslint-disable-next-line @typescript-eslint/camelcase + filter: includeAdmin ? 'all' : undefined, + query, + }, + }) .then(({ data }) => resolve({ items: (data.data || []).map((datum: any) => rawDataToServerObject(datum.attributes)), pagination: getPaginationSet(data.meta.pagination), diff --git a/resources/scripts/components/dashboard/DashboardContainer.tsx b/resources/scripts/components/dashboard/DashboardContainer.tsx index 767cb38b1..ad8f30d6f 100644 --- a/resources/scripts/components/dashboard/DashboardContainer.tsx +++ b/resources/scripts/components/dashboard/DashboardContainer.tsx @@ -4,30 +4,63 @@ import getServers from '@/api/getServers'; import ServerRow from '@/components/dashboard/ServerRow'; import Spinner from '@/components/elements/Spinner'; import PageContentBlock from '@/components/elements/PageContentBlock'; +import useFlash from '@/plugins/useFlash'; +import { httpErrorToHuman } from '@/api/http'; +import FlashMessageRender from '@/components/FlashMessageRender'; +import { useStoreState } from 'easy-peasy'; +import { usePersistedState } from '@/plugins/usePersistedState'; +import Switch from '@/components/elements/Switch'; export default () => { - const [ servers, setServers ] = useState(null); + const { addError, clearFlashes } = useFlash(); + const [ servers, setServers ] = useState([]); + const [ loading, setLoading ] = useState(true); + const { rootAdmin } = useStoreState(state => state.user.data!); + const [ showAdmin, setShowAdmin ] = usePersistedState('show_all_servers', false); - const loadServers = () => getServers().then(data => setServers(data.items)); + const loadServers = () => { + clearFlashes(); + setLoading(true); + + getServers(undefined, showAdmin) + .then(data => setServers(data.items)) + .catch(error => { + console.error(error); + addError({ message: httpErrorToHuman(error) }); + }) + .then(() => setLoading(false)); + }; useEffect(() => { loadServers(); - }, []); - - if (servers === null) { - return ; - } + }, [ showAdmin ]); return ( - {servers.length > 0 ? - servers.map(server => ( - - )) - : -

- It looks like you have no servers. + + {rootAdmin && +

+

+ {showAdmin ? 'Showing all servers' : 'Showing your servers'}

+ setShowAdmin(s => !s)} + /> +
+ } + {loading ? + + : + servers.length > 0 ? + servers.map(server => ( + + )) + : +

+ There are no servers associated with your account. +

}
); diff --git a/resources/scripts/components/elements/Switch.tsx b/resources/scripts/components/elements/Switch.tsx index db0801aca..606cc2281 100644 --- a/resources/scripts/components/elements/Switch.tsx +++ b/resources/scripts/components/elements/Switch.tsx @@ -36,7 +36,7 @@ const ToggleContainer = styled.div` export interface SwitchProps { name: string; - label: string; + label?: string; description?: string; defaultChecked?: boolean; onChange?: (e: React.ChangeEvent) => void; @@ -48,7 +48,7 @@ const Switch = ({ name, label, description, defaultChecked, onChange, children } return (
- + {children || -
+ {(label || description) && +
+ {label && + } {description &&

{description}

}
+ }
); }; diff --git a/resources/scripts/plugins/usePersistedState.ts b/resources/scripts/plugins/usePersistedState.ts new file mode 100644 index 000000000..18830696b --- /dev/null +++ b/resources/scripts/plugins/usePersistedState.ts @@ -0,0 +1,23 @@ +import { Dispatch, SetStateAction, useEffect, useState } from 'react'; + +export function usePersistedState (key: string, defaultValue: S): [S | undefined, Dispatch>] { + const [state, setState] = useState( + () => { + try { + const item = localStorage.getItem(key); + + return JSON.parse(item || (String(defaultValue))); + } catch (e) { + console.warn('Failed to retrieve persisted value from store.', e); + + return defaultValue; + } + } + ); + + useEffect(() => { + localStorage.setItem(key, JSON.stringify(state)) + }, [key, state]); + + return [ state, setState ]; +}