Adding sorting to items in settings
All checks were successful
Deploy to production / build (push) Successful in 18s
All checks were successful
Deploy to production / build (push) Successful in 18s
This commit is contained in:
@@ -3,6 +3,7 @@ import {
|
||||
Button,
|
||||
Group,
|
||||
Highlight,
|
||||
Menu,
|
||||
Popover,
|
||||
Stack,
|
||||
Switch,
|
||||
@@ -10,7 +11,8 @@ import {
|
||||
} from '@mantine/core';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { useState } from 'react';
|
||||
import { FiHelpCircle, FiLoader, FiPlus, FiX } from 'react-icons/fi';
|
||||
import { FaSort } from 'react-icons/fa';
|
||||
import { FiHelpCircle, FiPlus, FiX } from 'react-icons/fi';
|
||||
import {
|
||||
actionIconClasses,
|
||||
buttonClasses,
|
||||
@@ -31,6 +33,8 @@ export function SettingsHeader({
|
||||
searchPlaceholder,
|
||||
isLoading,
|
||||
setIsLoading,
|
||||
sortBy,
|
||||
setSortBy,
|
||||
}: {
|
||||
setDragging: undefined | ((dragging: boolean) => void);
|
||||
openModal: undefined | (() => void);
|
||||
@@ -45,6 +49,8 @@ export function SettingsHeader({
|
||||
searchPlaceholder: string | undefined;
|
||||
isLoading: boolean;
|
||||
setIsLoading: (isLoading: boolean) => void;
|
||||
sortBy: string;
|
||||
setSortBy: undefined | ((sortBy: string) => void);
|
||||
}) {
|
||||
const { isMobile, theme } = useCommonHooks();
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
@@ -123,10 +129,15 @@ export function SettingsHeader({
|
||||
)}
|
||||
</Group>
|
||||
{searchValue !== undefined && (
|
||||
<DebouncedInput
|
||||
disabled={disabled}
|
||||
<Group
|
||||
gap={4}
|
||||
w={isMobile ? undefined : '35%'}
|
||||
pos={isMobile ? undefined : 'absolute'}
|
||||
>
|
||||
<DebouncedInput
|
||||
disabled={disabled}
|
||||
w={'90%'}
|
||||
// pos={isMobile ? undefined : 'absolute'}
|
||||
className={textInputClasses.default}
|
||||
classNames={textInputClasses}
|
||||
autoFocus={!isMobile}
|
||||
@@ -151,9 +162,7 @@ export function SettingsHeader({
|
||||
<ActionIcon
|
||||
className={actionIconClasses.loadingSpinner}
|
||||
classNames={actionIconClasses}
|
||||
>
|
||||
<FiLoader />
|
||||
</ActionIcon>
|
||||
/>
|
||||
) : (
|
||||
searchValue && (
|
||||
<ActionIcon
|
||||
@@ -167,6 +176,94 @@ export function SettingsHeader({
|
||||
)
|
||||
}
|
||||
/>
|
||||
{setSortBy !== undefined && (
|
||||
<Menu>
|
||||
<Menu.Target>
|
||||
<ActionIcon>
|
||||
<FaSort />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown>
|
||||
<Menu.Label>Sort By</Menu.Label>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
setSortBy('A>Z');
|
||||
}}
|
||||
style={{
|
||||
color:
|
||||
sortBy === 'A>Z'
|
||||
? 'var(--mantine-color-background-0)'
|
||||
: 'var(--mantine-color-primary-0)',
|
||||
backgroundColor:
|
||||
sortBy === 'A>Z' ? 'var(--mantine-color-primary-0)' : undefined,
|
||||
}}
|
||||
>
|
||||
{'A>Z'}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
setSortBy('Z>A');
|
||||
}}
|
||||
style={{
|
||||
color:
|
||||
sortBy === 'Z>A'
|
||||
? 'var(--mantine-color-background-0)'
|
||||
: 'var(--mantine-color-primary-0)',
|
||||
backgroundColor:
|
||||
sortBy === 'Z>A' ? 'var(--mantine-color-primary-0)' : undefined,
|
||||
}}
|
||||
>
|
||||
{'Z>A'}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
setSortBy('Newest');
|
||||
}}
|
||||
style={{
|
||||
color:
|
||||
sortBy === 'Newest'
|
||||
? 'var(--mantine-color-background-0)'
|
||||
: 'var(--mantine-color-primary-0)',
|
||||
backgroundColor:
|
||||
sortBy === 'Newest' ? 'var(--mantine-color-primary-0)' : undefined,
|
||||
}}
|
||||
>
|
||||
{'Newest'}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
setSortBy('Oldest');
|
||||
}}
|
||||
style={{
|
||||
color:
|
||||
sortBy === 'Oldest'
|
||||
? 'var(--mantine-color-background-0)'
|
||||
: 'var(--mantine-color-primary-0)',
|
||||
backgroundColor:
|
||||
sortBy === 'Oldest' ? 'var(--mantine-color-primary-0)' : undefined,
|
||||
}}
|
||||
>
|
||||
{'Oldest'}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
setSortBy('Custom');
|
||||
}}
|
||||
style={{
|
||||
color:
|
||||
sortBy === 'Custom'
|
||||
? 'var(--mantine-color-background-0)'
|
||||
: 'var(--mantine-color-primary-0)',
|
||||
backgroundColor:
|
||||
sortBy === 'Custom' ? 'var(--mantine-color-primary-0)' : undefined,
|
||||
}}
|
||||
>
|
||||
{'Custom'}
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
)}
|
||||
</Group>
|
||||
)}
|
||||
{setDragging && (
|
||||
<Switch
|
||||
|
||||
@@ -27,6 +27,7 @@ import type { Application } from 'types';
|
||||
import DebouncedApplication from './DebouncedApplication';
|
||||
|
||||
export function Applications() {
|
||||
const [sortBy, setSortBy] = useState('Custom');
|
||||
const allIcons: any = { ...fa6, ...vsc, ...si };
|
||||
const defaultApplication: Application = {
|
||||
id: null,
|
||||
@@ -38,6 +39,7 @@ export function Applications() {
|
||||
index: 0,
|
||||
enabled: 1,
|
||||
};
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const [searchValue, setSearchValue] = useState<string | number>('');
|
||||
const [debouncedSearch] = useDebouncedValue(searchValue, 500);
|
||||
const form = useForm({
|
||||
@@ -54,19 +56,41 @@ export function Applications() {
|
||||
const { data: applicationData, isFetching: applicationDataIsFetching } = useQueryAPI({
|
||||
endpoint: appsEndpoint,
|
||||
});
|
||||
const applications: Application[] =
|
||||
applicationData
|
||||
const applications: Application[] = applicationData
|
||||
?.filter(
|
||||
(a: Application) =>
|
||||
a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()) ||
|
||||
a.url.toLowerCase().includes((debouncedSearch as string).toLowerCase()) ||
|
||||
a.baseUrl.toLowerCase().includes((debouncedSearch as string).toLowerCase()),
|
||||
)
|
||||
.sort((a: Application, b: Application) => (a.index > b.index ? 1 : -1)) || [];
|
||||
.sort((a: Application, b: Application) => {
|
||||
if (!dragging) {
|
||||
switch (sortBy) {
|
||||
case 'A>Z':
|
||||
return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1;
|
||||
case 'Z>A':
|
||||
return a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase() ? 1 : -1;
|
||||
case 'Newest':
|
||||
if (a.id && b.id) {
|
||||
return a.id < b.id ? 1 : -1;
|
||||
}
|
||||
return -1;
|
||||
case 'Oldest':
|
||||
if (a.id && b.id) {
|
||||
return a.id > b.id ? 1 : -1;
|
||||
}
|
||||
return -1;
|
||||
case 'Custom':
|
||||
return a.index > b.index ? 1 : -1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return a.index > b.index ? 1 : -1;
|
||||
});
|
||||
const [applicationList, setApplicationList] = useState<Application[]>([]);
|
||||
const { isMobile, reorder, theme } = useCommonHooks();
|
||||
const { mutateAsync } = useMutationAPI();
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
@@ -104,7 +128,7 @@ export function Applications() {
|
||||
|
||||
useEffect(() => {
|
||||
if (applicationList.length > 0 && applicationList !== applications) {
|
||||
mutateAsync({
|
||||
void mutateAsync({
|
||||
method: 'PATCH',
|
||||
endpoint: appsOrderEndpoint,
|
||||
body: applicationList,
|
||||
@@ -114,7 +138,7 @@ export function Applications() {
|
||||
return (
|
||||
<Stack>
|
||||
<SettingsHeader
|
||||
setDragging={applications.length > 0 ? setDragging : undefined}
|
||||
setDragging={applications?.length > 0 ? setDragging : undefined}
|
||||
openModal={openModal}
|
||||
title={'Applications'}
|
||||
tooltip={{
|
||||
@@ -140,6 +164,8 @@ export function Applications() {
|
||||
searchPlaceholder={'Search Applications...'}
|
||||
isLoading={isLoading}
|
||||
setIsLoading={setIsLoading}
|
||||
sortBy={sortBy}
|
||||
setSortBy={setSortBy}
|
||||
/>
|
||||
{modalOpened && (
|
||||
<AddItemModal
|
||||
@@ -149,12 +175,12 @@ export function Applications() {
|
||||
body={
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
mutateAsync({
|
||||
void mutateAsync({
|
||||
method: 'POST',
|
||||
endpoint: appsEndpoint,
|
||||
body: {
|
||||
...values,
|
||||
index: applications.length,
|
||||
index: applications?.length,
|
||||
},
|
||||
});
|
||||
handleClose();
|
||||
@@ -318,7 +344,7 @@ export function Applications() {
|
||||
size: 'xl',
|
||||
}}
|
||||
/>
|
||||
{applications.length > 0 ? (
|
||||
{applications?.length > 0 ? (
|
||||
<Droppable droppableId={'groupList'}>
|
||||
{(provided) => (
|
||||
<Grid
|
||||
|
||||
@@ -111,7 +111,7 @@ export function Bookmarks() {
|
||||
|
||||
useEffect(() => {
|
||||
if (groupList.length > 0 && groupList !== groups) {
|
||||
mutateAsync({
|
||||
void mutateAsync({
|
||||
method: 'PATCH',
|
||||
endpoint: 'api/bookmarkCategoryOrder',
|
||||
body: groupList,
|
||||
@@ -129,7 +129,7 @@ export function Bookmarks() {
|
||||
body={
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
mutateAsync({
|
||||
void mutateAsync({
|
||||
method: 'POST',
|
||||
endpoint: categoriesEndpoint,
|
||||
body: {
|
||||
@@ -221,6 +221,8 @@ export function Bookmarks() {
|
||||
searchPlaceholder={'Search Bookmarks...'}
|
||||
isLoading={isLoading}
|
||||
setIsLoading={setIsLoading}
|
||||
sortBy={''}
|
||||
setSortBy={undefined}
|
||||
/>
|
||||
{dragging ? (
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
|
||||
@@ -80,7 +80,7 @@ export function GuacamoleClients() {
|
||||
body={
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
mutateAsync({
|
||||
void mutateAsync({
|
||||
method: 'POST',
|
||||
endpoint: endpoint,
|
||||
body: { ...values, enabled: 1 },
|
||||
@@ -210,6 +210,8 @@ export function GuacamoleClients() {
|
||||
searchPlaceholder={'Search Clients...'}
|
||||
isLoading={isLoading}
|
||||
setIsLoading={setIsLoading}
|
||||
sortBy={''}
|
||||
setSortBy={undefined}
|
||||
/>
|
||||
<Stack
|
||||
mt={isMobile ? '10rem' : '6rem'}
|
||||
|
||||
@@ -49,7 +49,7 @@ export function Messages() {
|
||||
|
||||
useEffect(() => {
|
||||
if (Object.keys(debounced).length) {
|
||||
mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced });
|
||||
void mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced });
|
||||
}
|
||||
}, [debounced]);
|
||||
|
||||
@@ -82,6 +82,8 @@ export function Messages() {
|
||||
searchPlaceholder={'Search Messages...'}
|
||||
isLoading={isLoading}
|
||||
setIsLoading={setIsLoading}
|
||||
sortBy={''}
|
||||
setSortBy={undefined}
|
||||
/>
|
||||
{modalOpened && (
|
||||
<AddItemModal
|
||||
@@ -91,7 +93,7 @@ export function Messages() {
|
||||
body={
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
mutateAsync({
|
||||
void mutateAsync({
|
||||
method: 'POST',
|
||||
endpoint: endpoint,
|
||||
body: { message: values.message },
|
||||
|
||||
@@ -37,7 +37,7 @@ export function Personalization() {
|
||||
const { isMobile, theme } = useCommonHooks();
|
||||
useEffect(() => {
|
||||
if (debounced && Object.keys(debounced).length) {
|
||||
mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced });
|
||||
void mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced });
|
||||
setUpdate(undefined);
|
||||
}
|
||||
}, [debounced]);
|
||||
@@ -87,6 +87,8 @@ export function Personalization() {
|
||||
searchPlaceholder={undefined}
|
||||
isLoading={false}
|
||||
setIsLoading={() => {}}
|
||||
sortBy={''}
|
||||
setSortBy={undefined}
|
||||
/>
|
||||
<Stack align='center' mt={'6rem'} pos={'relative'}>
|
||||
<LoadingOverlay
|
||||
|
||||
@@ -86,6 +86,8 @@ export function SearchHistory() {
|
||||
searchPlaceholder={'Search your Search History...'}
|
||||
isLoading={isLoading}
|
||||
setIsLoading={setIsLoading}
|
||||
sortBy={''}
|
||||
setSortBy={undefined}
|
||||
/>
|
||||
<Stack
|
||||
mt={isMobile ? '10rem' : '6rem'}
|
||||
|
||||
@@ -96,7 +96,7 @@ export function SearchProviders() {
|
||||
body={
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
mutateAsync({
|
||||
void mutateAsync({
|
||||
method: 'POST',
|
||||
endpoint: endpoint,
|
||||
body: values,
|
||||
@@ -281,6 +281,8 @@ export function SearchProviders() {
|
||||
searchPlaceholder={'Search Providers...'}
|
||||
isLoading={isLoading}
|
||||
setIsLoading={setIsLoading}
|
||||
sortBy={''}
|
||||
setSortBy={undefined}
|
||||
/>
|
||||
<Stack
|
||||
mt={isMobile ? '10rem' : '6rem'}
|
||||
|
||||
@@ -73,7 +73,7 @@ export function WolClients() {
|
||||
body={
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
mutateAsync({
|
||||
void mutateAsync({
|
||||
method: 'POST',
|
||||
endpoint: endpoint,
|
||||
body: values,
|
||||
@@ -151,6 +151,8 @@ export function WolClients() {
|
||||
searchPlaceholder={'Search Clients...'}
|
||||
isLoading={isLoading}
|
||||
setIsLoading={setIsLoading}
|
||||
sortBy={''}
|
||||
setSortBy={undefined}
|
||||
/>
|
||||
<Stack
|
||||
mt={isMobile ? '10rem' : '6rem'}
|
||||
|
||||
Reference in New Issue
Block a user