Added persistent sort to more locations
All checks were successful
Deploy to production / build (push) Successful in 18s

This commit is contained in:
2026-10-20 18:58:52 -05:00
parent 2cf34f86fa
commit 2f8d3ad58e
9 changed files with 63 additions and 37 deletions

View File

@@ -32,6 +32,13 @@ const initialSettings: Settings = {
guacamoleHost: 'https://domain.example.com/guacamole', guacamoleHost: 'https://domain.example.com/guacamole',
lat: 29.750950134386066, lat: 29.750950134386066,
lon: -95.36220654860034, lon: -95.36220654860034,
messageSettingsSort: 'Oldest',
appSettingsSort: 'Custom',
bookmarkSettingsSort: 'Custom',
themesSettingsSort: 'Oldest',
providerSettingsSort: 'Oldest',
wolClientsSettingsSort: 'A>Z',
guacamoleClientsSettingsSort: 'A>Z',
}; };
export function useCommonHooks() { export function useCommonHooks() {

View File

@@ -27,8 +27,8 @@ import type { Application } from 'types';
import DebouncedApplication from './DebouncedApplication'; import DebouncedApplication from './DebouncedApplication';
export function Applications() { export function Applications() {
const [sortBy, setSortBy] = useState('Custom');
const allIcons: any = { ...fa6, ...vsc, ...si }; const allIcons: any = { ...fa6, ...vsc, ...si };
const { isMobile, reorder, theme, settings, updateSetting } = useCommonHooks();
const defaultApplication: Application = { const defaultApplication: Application = {
id: null, id: null,
name: '', name: '',
@@ -65,7 +65,7 @@ export function Applications() {
) )
.sort((a: Application, b: Application) => { .sort((a: Application, b: Application) => {
if (!dragging) { if (!dragging) {
switch (sortBy) { switch (settings.appSettingsSort) {
case 'A>Z': case 'A>Z':
return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1; return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1;
case 'Z>A': case 'Z>A':
@@ -89,7 +89,6 @@ export function Applications() {
return a.index > b.index ? 1 : -1; return a.index > b.index ? 1 : -1;
}); });
const [applicationList, setApplicationList] = useState<Application[]>([]); const [applicationList, setApplicationList] = useState<Application[]>([]);
const { isMobile, reorder, theme } = useCommonHooks();
const { mutateAsync } = useMutationAPI(); const { mutateAsync } = useMutationAPI();
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@@ -166,8 +165,10 @@ export function Applications() {
searchPlaceholder={'Search Applications...'} searchPlaceholder={'Search Applications...'}
isLoading={isLoading} isLoading={isLoading}
setIsLoading={setIsLoading} setIsLoading={setIsLoading}
sortBy={sortBy} sortBy={settings.appSettingsSort}
setSortBy={setSortBy} setSortBy={(value) => {
updateSetting('appSettingsSort', value);
}}
customSearchEnabled customSearchEnabled
/> />
{modalOpened && ( {modalOpened && (

View File

@@ -19,7 +19,7 @@ import type { Bookmark, BookmarkGroup } from 'types';
import DebouncedGroupSettingsItem from './DebouncedGroupSettingsItem'; import DebouncedGroupSettingsItem from './DebouncedGroupSettingsItem';
export function Bookmarks() { export function Bookmarks() {
const [sortBy, setSortBy] = useState('Custom'); const { isMobile, reorder, theme, settings, updateSetting } = useCommonHooks();
const defaultGroup = { const defaultGroup = {
id: null, id: null,
categoryName: '', categoryName: '',
@@ -45,7 +45,6 @@ export function Bookmarks() {
}); });
const [groups, setGroups] = useState<BookmarkGroup[]>([]); const [groups, setGroups] = useState<BookmarkGroup[]>([]);
const [groupList, setGroupList] = useState<BookmarkGroup[]>([]); const [groupList, setGroupList] = useState<BookmarkGroup[]>([]);
const { isMobile, reorder, theme } = useCommonHooks();
const { mutateAsync } = useMutationAPI(); const { mutateAsync } = useMutationAPI();
const [searchValue, setSearchValue] = useState<string | number>(''); const [searchValue, setSearchValue] = useState<string | number>('');
const [debouncedGroupSearch] = useDebouncedValue(searchValue, 500); const [debouncedGroupSearch] = useDebouncedValue(searchValue, 500);
@@ -103,7 +102,7 @@ export function Bookmarks() {
const groupList = [...new Set([...foundBookmarkGroups, ...foundGroups])].sort( const groupList = [...new Set([...foundBookmarkGroups, ...foundGroups])].sort(
(a: BookmarkGroup, b: BookmarkGroup) => { (a: BookmarkGroup, b: BookmarkGroup) => {
if (!dragging) { if (!dragging) {
switch (sortBy) { switch (settings.bookmarkSettingsSort) {
case 'A>Z': case 'A>Z':
return a.categoryName.toLocaleLowerCase() > return a.categoryName.toLocaleLowerCase() >
b.categoryName.toLocaleLowerCase() b.categoryName.toLocaleLowerCase()
@@ -138,7 +137,13 @@ export function Bookmarks() {
if (debouncedGroupSearch === searchValue) { if (debouncedGroupSearch === searchValue) {
setIsLoading(false); setIsLoading(false);
} }
}, [groupData, groupsIsFetched, debouncedGroupSearch, sortBy, dragging]); }, [
groupData,
groupsIsFetched,
debouncedGroupSearch,
settings.bookmarkSettingsSort,
dragging,
]);
useEffect(() => { useEffect(() => {
if (groupList.length > 0 && groupList !== groups) { if (groupList.length > 0 && groupList !== groups) {
@@ -256,8 +261,10 @@ export function Bookmarks() {
searchPlaceholder={'Search Bookmarks...'} searchPlaceholder={'Search Bookmarks...'}
isLoading={isLoading} isLoading={isLoading}
setIsLoading={setIsLoading} setIsLoading={setIsLoading}
sortBy={sortBy} sortBy={settings.bookmarkSettingsSort}
setSortBy={setSortBy} setSortBy={(value) => {
updateSetting('bookmarkSettingsSort', value);
}}
customSearchEnabled customSearchEnabled
/> />
{dragging ? ( {dragging ? (

View File

@@ -23,7 +23,7 @@ import DebouncedGuacamoleClient from './DebouncedGuacamoleClient';
import GuacamoleClientSettingsItem from './GuacamoleClientSettingsItem'; import GuacamoleClientSettingsItem from './GuacamoleClientSettingsItem';
export function GuacamoleClients() { export function GuacamoleClients() {
const [sortBy, setSortBy] = useState('Oldest'); const { isMobile, theme, settings, updateSetting } = useCommonHooks();
const defaultGuacamoleClient: GuacamoleClient = { const defaultGuacamoleClient: GuacamoleClient = {
id: undefined, id: undefined,
clientName: '', clientName: '',
@@ -58,7 +58,7 @@ export function GuacamoleClients() {
.includes((debouncedSearch as string).toLowerCase()), .includes((debouncedSearch as string).toLowerCase()),
) )
.sort((a: GuacamoleClient, b: GuacamoleClient) => { .sort((a: GuacamoleClient, b: GuacamoleClient) => {
switch (sortBy) { switch (settings.guacamoleClientsSettingsSort) {
case 'A>Z': case 'A>Z':
return a.clientName.toLocaleLowerCase() > b.clientName.toLocaleLowerCase() return a.clientName.toLocaleLowerCase() > b.clientName.toLocaleLowerCase()
? 1 ? 1
@@ -82,7 +82,6 @@ export function GuacamoleClients() {
} }
}) || []; }) || [];
const { mutateAsync } = useMutationAPI(); const { mutateAsync } = useMutationAPI();
const { isMobile, theme } = useCommonHooks();
const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@@ -240,8 +239,10 @@ export function GuacamoleClients() {
searchPlaceholder={'Search Clients...'} searchPlaceholder={'Search Clients...'}
isLoading={isLoading} isLoading={isLoading}
setIsLoading={setIsLoading} setIsLoading={setIsLoading}
sortBy={sortBy} sortBy={settings.guacamoleClientsSettingsSort}
setSortBy={setSortBy} setSortBy={(value) => {
updateSetting('guacamoleClientsSettingsSort', value);
}}
customSearchEnabled={false} customSearchEnabled={false}
/> />
<Stack <Stack

View File

@@ -17,6 +17,7 @@ import type { Message } from 'types';
import DebouncedMessage from './DebouncedMessage'; import DebouncedMessage from './DebouncedMessage';
export function Messages() { export function Messages() {
const { isMobile, theme, settings, updateSetting } = useCommonHooks();
const endpoint = 'api/messages'; const endpoint = 'api/messages';
const { data: messageData, isFetching: messageDataIsFetching } = useQueryAPI({ const { data: messageData, isFetching: messageDataIsFetching } = useQueryAPI({
endpoint: endpoint, endpoint: endpoint,
@@ -29,10 +30,8 @@ export function Messages() {
message: isNotEmpty('Message is required'), message: isNotEmpty('Message is required'),
}, },
}); });
const [sortBy, setSortBy] = useState('Oldest');
const [searchValue, setSearchValue] = useState<string | number>(''); const [searchValue, setSearchValue] = useState<string | number>('');
const [debouncedSearch] = useDebouncedValue(searchValue, 500); const [debouncedSearch] = useDebouncedValue(searchValue, 500);
const { isMobile, theme } = useCommonHooks();
const { mutateAsync } = useMutationAPI(); const { mutateAsync } = useMutationAPI();
const messages: Message[] = const messages: Message[] =
messageData messageData
@@ -40,7 +39,7 @@ export function Messages() {
m.message.toLowerCase().includes((debouncedSearch as string).toLowerCase()), m.message.toLowerCase().includes((debouncedSearch as string).toLowerCase()),
) )
.sort((a: Message, b: Message) => { .sort((a: Message, b: Message) => {
switch (sortBy) { switch (settings.messageSettingsSort) {
case 'A>Z': case 'A>Z':
return a.message.toLocaleLowerCase() > b.message.toLocaleLowerCase() ? 1 : -1; return a.message.toLocaleLowerCase() > b.message.toLocaleLowerCase() ? 1 : -1;
case 'Z>A': case 'Z>A':
@@ -108,8 +107,10 @@ export function Messages() {
searchPlaceholder={'Search Messages...'} searchPlaceholder={'Search Messages...'}
isLoading={isLoading} isLoading={isLoading}
setIsLoading={setIsLoading} setIsLoading={setIsLoading}
sortBy={sortBy} sortBy={settings.messageSettingsSort}
setSortBy={setSortBy} setSortBy={(value) => {
updateSetting('messageSettingsSort', value);
}}
customSearchEnabled={false} customSearchEnabled={false}
/> />
{modalOpened && ( {modalOpened && (

View File

@@ -36,7 +36,7 @@ import DebouncedSearchProvider from './DebouncedSearchProvider';
import SearchProviderSettingsItem from './SearchProviderSettingsItem'; import SearchProviderSettingsItem from './SearchProviderSettingsItem';
export function SearchProviders() { export function SearchProviders() {
const [sortBy, setSortBy] = useState('Oldest'); const { isMobile, theme, iconFilter, settings, updateSetting } = useCommonHooks();
const allIcons: any = { ...fa6, ...vsc, ...si }; const allIcons: any = { ...fa6, ...vsc, ...si };
const defaultProvider: Provider = { const defaultProvider: Provider = {
id: undefined, id: undefined,
@@ -70,7 +70,7 @@ export function SearchProviders() {
a.prefix.toLowerCase().includes((debouncedSearch as string).toLowerCase()), a.prefix.toLowerCase().includes((debouncedSearch as string).toLowerCase()),
) )
.sort((a: Provider, b: Provider) => { .sort((a: Provider, b: Provider) => {
switch (sortBy) { switch (settings.providerSettingsSort) {
case 'A>Z': case 'A>Z':
return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1; return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1;
case 'Z>A': case 'Z>A':
@@ -89,7 +89,6 @@ export function SearchProviders() {
return 0; return 0;
} }
}) ?? []; }) ?? [];
const { isMobile, theme, iconFilter } = useCommonHooks();
const { mutateAsync } = useMutationAPI(); const { mutateAsync } = useMutationAPI();
const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
@@ -303,8 +302,10 @@ export function SearchProviders() {
searchPlaceholder={'Search Providers...'} searchPlaceholder={'Search Providers...'}
isLoading={isLoading} isLoading={isLoading}
setIsLoading={setIsLoading} setIsLoading={setIsLoading}
sortBy={sortBy} sortBy={settings.providerSettingsSort}
setSortBy={setSortBy} setSortBy={(value) => {
updateSetting('providerSettingsSort', value);
}}
customSearchEnabled={false} customSearchEnabled={false}
/> />
<Stack <Stack

View File

@@ -24,11 +24,11 @@ import { ThemeCard } from './ThemeCard';
import { ThemeModal } from './ThemeModal'; import { ThemeModal } from './ThemeModal';
export function Themes() { export function Themes() {
const { settings, updateSetting, theme, isMobile } = useCommonHooks();
const backgroundsEndpoint = 'api/backgrounds'; const backgroundsEndpoint = 'api/backgrounds';
const { data: allThemeData, isFetching: allThemeDataIsFetching } = useQueryAPI({ const { data: allThemeData, isFetching: allThemeDataIsFetching } = useQueryAPI({
endpoint: 'api/themes', endpoint: 'api/themes',
}); });
const [sortBy, setSortBy] = useState('Oldest');
const [searchValue, setSearchValue] = useState<string | number>(''); const [searchValue, setSearchValue] = useState<string | number>('');
const [debouncedSearch] = useDebouncedValue(searchValue, 500); const [debouncedSearch] = useDebouncedValue(searchValue, 500);
const allThemes: Theme[] = allThemeData const allThemes: Theme[] = allThemeData
@@ -36,7 +36,7 @@ export function Themes() {
a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()), a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()),
) )
.sort((a: Theme, b: Theme) => { .sort((a: Theme, b: Theme) => {
switch (sortBy) { switch (settings.themesSettingsSort) {
case 'A>Z': case 'A>Z':
return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1; return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1;
case 'Z>A': case 'Z>A':
@@ -84,8 +84,6 @@ export function Themes() {
), ),
] as string[]; ] as string[];
const { settings, updateSetting, theme, isMobile } = useCommonHooks();
const [selectedTheme, setSelectedTheme] = useState<Theme>({ const [selectedTheme, setSelectedTheme] = useState<Theme>({
id: undefined, id: undefined,
name: 'default', name: 'default',
@@ -153,8 +151,10 @@ export function Themes() {
searchPlaceholder={'Search Themes...'} searchPlaceholder={'Search Themes...'}
isLoading={isLoading} isLoading={isLoading}
setIsLoading={setIsLoading} setIsLoading={setIsLoading}
sortBy={sortBy} sortBy={settings.themesSettingsSort}
setSortBy={setSortBy} setSortBy={(value) => {
updateSetting('themesSettingsSort', value);
}}
customSearchEnabled={false} customSearchEnabled={false}
/> />
<Stack mt={isMobile ? '11rem' : '7rem'} align='center'> <Stack mt={isMobile ? '11rem' : '7rem'} align='center'>

View File

@@ -19,6 +19,7 @@ import DebouncedWolClient from './DebouncedWolClient';
import WolClientSettingsItem from './WolClientSettingsItem'; import WolClientSettingsItem from './WolClientSettingsItem';
export function WolClients() { export function WolClients() {
const { isMobile, theme, settings, updateSetting } = useCommonHooks();
const defaultWolClient: WolClient = { const defaultWolClient: WolClient = {
id: undefined, id: undefined,
hostname: '', hostname: '',
@@ -38,7 +39,6 @@ export function WolClients() {
const { data: wolClientsData, isFetching: wolClientsIsFetching } = useQueryAPI({ const { data: wolClientsData, isFetching: wolClientsIsFetching } = useQueryAPI({
endpoint: endpoint, endpoint: endpoint,
}); });
const [sortBy, setSortBy] = useState('Oldest');
const [searchValue, setSearchValue] = useState<string | number>(''); const [searchValue, setSearchValue] = useState<string | number>('');
const [debouncedSearch] = useDebouncedValue(searchValue, 500); const [debouncedSearch] = useDebouncedValue(searchValue, 500);
const wolClients: WolClient[] = const wolClients: WolClient[] =
@@ -49,7 +49,7 @@ export function WolClients() {
a.macAddress.toLowerCase().includes((debouncedSearch as string).toLowerCase()), a.macAddress.toLowerCase().includes((debouncedSearch as string).toLowerCase()),
) )
.sort((a: WolClient, b: WolClient) => { .sort((a: WolClient, b: WolClient) => {
switch (sortBy) { switch (settings.wolClientsSettingsSort) {
case 'A>Z': case 'A>Z':
return a.hostname.toLocaleLowerCase() > b.hostname.toLocaleLowerCase() return a.hostname.toLocaleLowerCase() > b.hostname.toLocaleLowerCase()
? 1 ? 1
@@ -73,7 +73,6 @@ export function WolClients() {
} }
}) || []; }) || [];
const { mutateAsync } = useMutationAPI(); const { mutateAsync } = useMutationAPI();
const { isMobile, theme } = useCommonHooks();
const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@@ -179,8 +178,10 @@ export function WolClients() {
searchPlaceholder={'Search Clients...'} searchPlaceholder={'Search Clients...'}
isLoading={isLoading} isLoading={isLoading}
setIsLoading={setIsLoading} setIsLoading={setIsLoading}
sortBy={sortBy} sortBy={settings.wolClientsSettingsSort}
setSortBy={setSortBy} setSortBy={(value) => {
updateSetting('wolClientsSettingsSort', value);
}}
customSearchEnabled={false} customSearchEnabled={false}
/> />
<Stack <Stack

View File

@@ -25,4 +25,11 @@ export interface Settings {
defaultFont: string; defaultFont: string;
lat: number; lat: number;
lon: number; lon: number;
messageSettingsSort: string;
appSettingsSort: string;
bookmarkSettingsSort: string;
themesSettingsSort: string;
providerSettingsSort: string;
wolClientsSettingsSort: string;
guacamoleClientsSettingsSort: string;
} }