More performance updates
This commit is contained in:
62
package-lock.json
generated
62
package-lock.json
generated
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"name": "triggerfrontend",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "triggerfrontend",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"dependencies": {
|
||||
"@gfazioli/mantine-text-animate": "^2.3.10",
|
||||
"@hello-pangea/dnd": "^18.0.1",
|
||||
"@mantine/core": "^8.3.11",
|
||||
"@mantine/dates": "^8.3.11",
|
||||
"@mantine/form": "^8.3.11",
|
||||
"@mantine/hooks": "^8.3.11",
|
||||
"@mantine/notifications": "^8.3.11",
|
||||
"@mantine/core": "^8.3.12",
|
||||
"@mantine/dates": "^8.3.12",
|
||||
"@mantine/form": "^8.3.12",
|
||||
"@mantine/hooks": "^8.3.12",
|
||||
"@mantine/notifications": "^8.3.12",
|
||||
"@tanstack/react-query": "^5.90.16",
|
||||
"@tanstack/react-query-devtools": "^5.91.2",
|
||||
"@tanstack/react-query-persist-client": "^5.90.18",
|
||||
@@ -911,9 +911,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mantine/core": {
|
||||
"version": "8.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.11.tgz",
|
||||
"integrity": "sha512-FWXp94tiTFdh8BKc7UTNdIuumD96JFxLF/VvUWGRzf5i563Ye0Ma/aZtOBwpdEtdIQkojOhoMMV76k5toOQgEQ==",
|
||||
"version": "8.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.3.12.tgz",
|
||||
"integrity": "sha512-bDEoUl4SneltfI1GeEaBk6BVDbLuB/w15YwseAmUvc8ldAbNcsVhxKxY/BdhwqUo6O3L2vhdlb3WwxR1y8741g==",
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "^0.27.16",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -923,30 +923,30 @@
|
||||
"type-fest": "^4.41.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mantine/hooks": "8.3.11",
|
||||
"@mantine/hooks": "8.3.12",
|
||||
"react": "^18.x || ^19.x",
|
||||
"react-dom": "^18.x || ^19.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@mantine/dates": {
|
||||
"version": "8.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-8.3.11.tgz",
|
||||
"integrity": "sha512-e5QBHMpTjKDkYHFEYkD3bho4Kk/M04jmXLu9Txb/XkWVDb5A0CNGg6+A8TinXING4B7kn2dMOLmL3s7r6vnJJA==",
|
||||
"version": "8.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-8.3.12.tgz",
|
||||
"integrity": "sha512-rL2kYJRTrU29l1KjQt5bdUweiZuJs3DjiIcc6VGHUuj7OwfYZbEpWzMbcu8fSrya/+kZAe8JM0irX22CjmsDGw==",
|
||||
"dependencies": {
|
||||
"clsx": "^2.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mantine/core": "8.3.11",
|
||||
"@mantine/hooks": "8.3.11",
|
||||
"@mantine/core": "8.3.12",
|
||||
"@mantine/hooks": "8.3.12",
|
||||
"dayjs": ">=1.0.0",
|
||||
"react": "^18.x || ^19.x",
|
||||
"react-dom": "^18.x || ^19.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@mantine/form": {
|
||||
"version": "8.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/form/-/form-8.3.11.tgz",
|
||||
"integrity": "sha512-546npW8gHCXUShVL/OOnKBJ1So5bcKTdmiNxzXn8q2eGhMIB+zdj7/v4QUz2j55OjDRPq0dAVJhzDjLfzeibTg==",
|
||||
"version": "8.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/form/-/form-8.3.12.tgz",
|
||||
"integrity": "sha512-bjXL1Ah3lAZYHrjrF37FeHV8DFGeXV+apn0PRQw2MTLpdUSqKsiYIDDgugzRfNXWX1cn1ELtxtDXsMfdj/LI7Q==",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"klona": "^2.0.6"
|
||||
@@ -956,32 +956,32 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@mantine/hooks": {
|
||||
"version": "8.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.11.tgz",
|
||||
"integrity": "sha512-WJFKDnJJM2fAOCkrO8qRsi3wDdicSFqElruPj5TEYWDL93vl0pITOyN0oRF93bUtx190waqela3edfGH3r5/1g==",
|
||||
"version": "8.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.3.12.tgz",
|
||||
"integrity": "sha512-lMMDzDewd3lUNtJCAHDj3g8On9X5aBl4q6EBwgOixKQSby9RG9ASEpK8oYHundHTm9tzo3MDeXWV/z32oSQWuw==",
|
||||
"peerDependencies": {
|
||||
"react": "^18.x || ^19.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@mantine/notifications": {
|
||||
"version": "8.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.3.11.tgz",
|
||||
"integrity": "sha512-bcFzw9m4uzxHMflNeWqa9imCy8T5mHCAV8WRqzAwK/Yls8GL9uJoQH/e1v6Pl4g4yvBmaF9yUHu7Zq3iyKhHhQ==",
|
||||
"version": "8.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.3.12.tgz",
|
||||
"integrity": "sha512-lqPPa11XdcndG8ywMao8yVkMA4jg/pBNbS85bR7OwHQa1yUftmfVlqJl9PZZCiWLX2AgKY3+xM5dHo4LidL+DA==",
|
||||
"dependencies": {
|
||||
"@mantine/store": "8.3.11",
|
||||
"@mantine/store": "8.3.12",
|
||||
"react-transition-group": "4.4.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mantine/core": "8.3.11",
|
||||
"@mantine/hooks": "8.3.11",
|
||||
"@mantine/core": "8.3.12",
|
||||
"@mantine/hooks": "8.3.12",
|
||||
"react": "^18.x || ^19.x",
|
||||
"react-dom": "^18.x || ^19.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@mantine/store": {
|
||||
"version": "8.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.3.11.tgz",
|
||||
"integrity": "sha512-ku48CzN9HobVUjd7o41voaaHKz2CMrtkk454vwXWAspfbpqR4hklL5zq/MzctETFCG6HBDiPRfZAvNm8WaM3Tw==",
|
||||
"version": "8.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.3.12.tgz",
|
||||
"integrity": "sha512-EC4eIKpm5s7neMbBrWsP6jGKLqrzHf63Ao3penYr7fn25dFXdbXZYw+IG8GYzxOC4yG61b2zTS+bpy5+vwzXpw==",
|
||||
"peerDependencies": {
|
||||
"react": "^18.x || ^19.x"
|
||||
}
|
||||
|
||||
10
package.json
10
package.json
@@ -12,11 +12,11 @@
|
||||
"dependencies": {
|
||||
"@gfazioli/mantine-text-animate": "^2.3.10",
|
||||
"@hello-pangea/dnd": "^18.0.1",
|
||||
"@mantine/core": "^8.3.11",
|
||||
"@mantine/dates": "^8.3.11",
|
||||
"@mantine/form": "^8.3.11",
|
||||
"@mantine/hooks": "^8.3.11",
|
||||
"@mantine/notifications": "^8.3.11",
|
||||
"@mantine/core": "^8.3.12",
|
||||
"@mantine/dates": "^8.3.12",
|
||||
"@mantine/form": "^8.3.12",
|
||||
"@mantine/hooks": "^8.3.12",
|
||||
"@mantine/notifications": "^8.3.12",
|
||||
"@tanstack/react-query": "^5.90.16",
|
||||
"@tanstack/react-query-devtools": "^5.91.2",
|
||||
"@tanstack/react-query-persist-client": "^5.90.18",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { ActionIcon, Box, Group, Text } from '@mantine/core';
|
||||
import { createColumnHelper } from '@tanstack/react-table';
|
||||
import { FaFilter, FaTrash } from 'react-icons/fa';
|
||||
import type { SearchHistoryItem } from 'types';
|
||||
|
||||
const columnHelper = createColumnHelper<any>();
|
||||
const columnHelper = createColumnHelper<SearchHistoryItem>();
|
||||
export const SearchHistoryColumns = (
|
||||
setSelectedItem: React.Dispatch<React.SetStateAction<any>>,
|
||||
deleteItemOpen: () => void,
|
||||
@@ -109,11 +110,11 @@ export const SearchHistoryColumns = (
|
||||
id: 'dateTimeStamp',
|
||||
cell: ({ cell }: any) => {
|
||||
const m = new Date(cell.getValue());
|
||||
const year = `${m.getUTCFullYear()}`.slice(-2);
|
||||
const month = `0${m.getUTCMonth() + 1}`.slice(-2);
|
||||
const day = `0${m.getUTCDate()}`.slice(-2);
|
||||
const hours = `0${m.getUTCHours()}`.slice(-2);
|
||||
const minutes = `0${m.getUTCMinutes()}`.slice(-2);
|
||||
const year = `${m.getFullYear()}`.slice(-2);
|
||||
const month = `0${m.getMonth() + 1}`.slice(-2);
|
||||
const day = `0${m.getDate()}`.slice(-2);
|
||||
const hours = `0${m.getHours()}`.slice(-2);
|
||||
const minutes = `0${m.getMinutes()}`.slice(-2);
|
||||
const dateString = `${month}/${day}/${year} ${hours}:${minutes}`;
|
||||
|
||||
return (
|
||||
|
||||
@@ -64,6 +64,7 @@ export function DataTable({
|
||||
setColumnFilters([]);
|
||||
}
|
||||
}, [filtersEnabled]);
|
||||
|
||||
return (
|
||||
<ScrollArea
|
||||
className={scrollAreaClasses.default}
|
||||
|
||||
@@ -53,7 +53,6 @@ export function Filter({
|
||||
});
|
||||
};
|
||||
return filterVariant === 'range' ? (
|
||||
<div>
|
||||
<DatePickerInput
|
||||
type='range'
|
||||
clearable
|
||||
@@ -61,7 +60,6 @@ export function Filter({
|
||||
value={columnFilterValue as [Date, Date]}
|
||||
onChange={(value) => column.setFilterValue(value)}
|
||||
/>
|
||||
</div>
|
||||
) : filterVariant === 'select' ? (
|
||||
<select
|
||||
onChange={(e) => column.setFilterValue(e.target.value)}
|
||||
|
||||
@@ -13,10 +13,6 @@ export function DebouncedInput({
|
||||
} & Omit<TextInputProps, 'onChange'>) {
|
||||
const [value, setValue] = useState(initialValue);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(initialValue);
|
||||
}, [initialValue]);
|
||||
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(() => {
|
||||
onChange(value);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Modal, Stack } from '@mantine/core';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { modalClasses } from 'styles';
|
||||
import type { Application, Provider } from 'types';
|
||||
import type { Application, GuacamoleClient, Provider } from 'types';
|
||||
import HelpSection from './HelpSection';
|
||||
|
||||
export function HelpModal({
|
||||
@@ -10,12 +10,14 @@ export function HelpModal({
|
||||
closeProviderModal,
|
||||
applicationData,
|
||||
providerData,
|
||||
clientData,
|
||||
}: {
|
||||
handleResetSearch: () => void;
|
||||
providerModalOpened: boolean;
|
||||
closeProviderModal: () => void;
|
||||
applicationData: Application[];
|
||||
providerData: Provider[];
|
||||
clientData: GuacamoleClient[];
|
||||
}) {
|
||||
const { isMobile } = useCommonHooks();
|
||||
return (
|
||||
@@ -61,6 +63,16 @@ export function HelpModal({
|
||||
};
|
||||
})}
|
||||
/>
|
||||
<Stack my={'.5rem'} />
|
||||
<HelpSection
|
||||
name={'Available Clients'}
|
||||
items={clientData.map((client: GuacamoleClient) => {
|
||||
return {
|
||||
name: `${client.clientName} (${client.clientIdentifier})`,
|
||||
command: `>${client.clientName}`,
|
||||
};
|
||||
})}
|
||||
/>
|
||||
</Stack>
|
||||
</Modal.Body>
|
||||
</Modal.Content>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Box, Card, Group, Stack, Text } from '@mantine/core';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { useSunStateAPI } from 'hooks/useAPI';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCommonHooks, useSunStateAPI } from 'hooks';
|
||||
import { FaLongArrowAltDown, FaLongArrowAltUp, FaWind } from 'react-icons/fa';
|
||||
import { WiBarometer, WiHumidity, WiSunrise, WiSunset } from 'react-icons/wi';
|
||||
import { textClasses } from 'styles';
|
||||
@@ -16,21 +14,15 @@ export default function CurrentWeather({ current }: { current: CW }) {
|
||||
lon: currentLocation.lon,
|
||||
});
|
||||
|
||||
const [sunStates, setSunStates] = useState<SunState[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (sunStateData) {
|
||||
setSunStates(
|
||||
sunStateData.results.map((item: SunState) => {
|
||||
const sunStates: SunState[] =
|
||||
sunStateData?.results.map((item: SunState) => {
|
||||
return {
|
||||
date: item.date,
|
||||
sunrise: item.sunrise,
|
||||
sunset: item.sunset,
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [sunStateData]);
|
||||
}) || [];
|
||||
|
||||
return (
|
||||
<>
|
||||
{current && (
|
||||
|
||||
@@ -7,7 +7,7 @@ function WeatherFeaturePill({
|
||||
}: {
|
||||
leftSide: React.ReactNode;
|
||||
rightSide: React.ReactNode;
|
||||
highlight?: string;
|
||||
highlight?: 'left' | 'right';
|
||||
}) {
|
||||
return (
|
||||
<Group
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Center, Group, Modal, Stack, Text } from '@mantine/core';
|
||||
import { useCommonHooks, useWeatherAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { modalClasses } from 'styles';
|
||||
|
||||
import type { CurrentWeather as CW, ExtendedForecast, HourlyForecast } from 'types';
|
||||
@@ -28,13 +27,9 @@ export function WeatherModal({
|
||||
x: currentLocation.x,
|
||||
y: currentLocation.y,
|
||||
});
|
||||
const [hourlyForecast, setHourlyForecast] = useState<HourlyForecast[]>([]);
|
||||
const hourlyForecast: HourlyForecast[] =
|
||||
hourly?.properties?.periods?.slice(1, 25) || [];
|
||||
|
||||
useEffect(() => {
|
||||
if (hourly) {
|
||||
setHourlyForecast(hourly.properties.periods.slice(1, 25));
|
||||
}
|
||||
}, [hourly]);
|
||||
return (
|
||||
<Modal.Root
|
||||
fullScreen={isMobile}
|
||||
|
||||
@@ -2,6 +2,7 @@ export {
|
||||
useMutationAPI,
|
||||
useOSMAPI,
|
||||
useQueryAPI,
|
||||
useSunStateAPI,
|
||||
useWeatherAPI,
|
||||
} from './useAPI';
|
||||
export { useCommonHooks } from './useCommonHooks';
|
||||
|
||||
@@ -76,7 +76,7 @@ export function Homepage() {
|
||||
});
|
||||
|
||||
const personal: PersonalData = personalData?.[0];
|
||||
const message: Message = messageData?.[0];
|
||||
const message: Message = messageData?.[0] || {};
|
||||
const [displayedGreeting, setDisplayedGreeting] = useState<string | undefined>('');
|
||||
const [current, setCurrent] = useState<CW>({
|
||||
icon: '',
|
||||
@@ -122,7 +122,7 @@ export function Homepage() {
|
||||
useEffect(() => {
|
||||
if (personal) {
|
||||
setDisplayedGreeting(() => {
|
||||
if (Math.floor(Math.random() * 100) > 10 || message === undefined) {
|
||||
if (Math.floor(Math.random() * 100) > 10 || message.message === undefined) {
|
||||
switch (Math.floor(new Date().getHours() / 6)) {
|
||||
case 0:
|
||||
return `Good night, ${personal?.firstName}!`;
|
||||
|
||||
@@ -632,6 +632,7 @@ export default function Search({
|
||||
handleResetSearch={handleResetSearch}
|
||||
applicationData={applications}
|
||||
providerData={providers}
|
||||
clientData={guacamoleClients}
|
||||
providerModalOpened={providerModalOpened}
|
||||
closeProviderModal={closeProviderModal}
|
||||
/>
|
||||
|
||||
@@ -15,11 +15,11 @@ function SearchSelectItem({
|
||||
const { mutateAsync } = useMutationAPI();
|
||||
const [showFillButton, setShowFillButton] = useState(false);
|
||||
const m = new Date(item.option.dateTimeStamp);
|
||||
const year = `${m.getUTCFullYear()}`.slice(-2);
|
||||
const month = `0${m.getUTCMonth() + 1}`.slice(-2);
|
||||
const day = `0${m.getUTCDate()}`.slice(-2);
|
||||
const hours = `0${m.getUTCHours()}`.slice(-2);
|
||||
const minutes = `0${m.getUTCMinutes()}`.slice(-2);
|
||||
const year = `${m.getFullYear()}`.slice(-2);
|
||||
const month = `0${m.getMonth() + 1}`.slice(-2);
|
||||
const day = `0${m.getDate()}`.slice(-2);
|
||||
const hours = `0${m.getHours()}`.slice(-2);
|
||||
const minutes = `0${m.getMinutes()}`.slice(-2);
|
||||
const dateString = isMobile
|
||||
? `${month}/${day}/${year}`
|
||||
: `${month}/${day}/${year} ${hours}:${minutes}`;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Box, Button, Group, Menu, Overlay, Stack } from '@mantine/core';
|
||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { FiMenu, FiSettings } from 'react-icons/fi';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { buttonClasses, menuClasses } from 'styles';
|
||||
@@ -10,21 +10,29 @@ import ThemingCard from './ThemingCard';
|
||||
import WakeOnLan from './WakeOnLanCard';
|
||||
|
||||
function SettingsButton() {
|
||||
const { data: appCategoryData, isFetched: appCategoryDataIsFetched } = useQueryAPI({
|
||||
const { data: appCategoryData } = useQueryAPI({
|
||||
endpoint: 'api/appCategories',
|
||||
});
|
||||
const { data: wolClientData } = useQueryAPI({
|
||||
endpoint: 'api/wolClients',
|
||||
});
|
||||
const { data: wolEnabledData, isFetched: wolEnabledDataIsFetched } = useQueryAPI({
|
||||
const { data: wolEnabledData } = useQueryAPI({
|
||||
endpoint: 'api/wolEnabled',
|
||||
});
|
||||
const wolClients: WolClient[] = wolClientData || [];
|
||||
const [enabled, setEnabled] = useState<number>(0);
|
||||
const enabled: number = wolEnabledData?.[0].enableWol || 0;
|
||||
const { mutateAsync } = useMutationAPI();
|
||||
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
|
||||
const categories = appCategoryData
|
||||
? [
|
||||
{ value: 'All', label: 'All' },
|
||||
...appCategoryData.map((category: AppCategory) => {
|
||||
return { value: category.filterName, label: category.filterName };
|
||||
}),
|
||||
]
|
||||
: [{ value: 'All', label: 'All' }];
|
||||
const [selectedClient, setSelectedClient] = useState<WolClient>(wolClientData?.[0]);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const {
|
||||
theme,
|
||||
isMobile,
|
||||
@@ -54,21 +62,6 @@ function SettingsButton() {
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (appCategoryData) {
|
||||
const list: [any] = appCategoryData.map((category: AppCategory) => {
|
||||
return { value: category.filterName, label: category.filterName };
|
||||
});
|
||||
list.unshift({ value: 'All', label: 'All' });
|
||||
setCategories(list);
|
||||
}
|
||||
}, [appCategoryData, appCategoryDataIsFetched]);
|
||||
|
||||
useEffect(() => {
|
||||
if (wolEnabledData && wolEnabledDataIsFetched) {
|
||||
setEnabled(wolEnabledData[0].enableWol);
|
||||
}
|
||||
}, [wolEnabledData, wolEnabledDataIsFetched]);
|
||||
return (
|
||||
<Menu
|
||||
classNames={menuClasses}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { useEffect, useState } from 'react';
|
||||
import * as fa6 from 'react-icons/fa6';
|
||||
import * as si from 'react-icons/si';
|
||||
import * as vsc from 'react-icons/vsc';
|
||||
import { popoverClasses, selectClasses, textInputClasses } from 'styles';
|
||||
import { buttonClasses, popoverClasses, selectClasses, textInputClasses } from 'styles';
|
||||
import type { Application } from 'types';
|
||||
import DebouncedApplication from './DebouncedApplication';
|
||||
|
||||
@@ -281,12 +281,16 @@ const ApplicationSettings = () => {
|
||||
/>
|
||||
</Group>
|
||||
<Group mt={'1rem'}>
|
||||
<Button type='submit' color={'green'}>
|
||||
<Button
|
||||
type='submit'
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleClose}
|
||||
>
|
||||
Cancel
|
||||
|
||||
@@ -14,7 +14,7 @@ import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||
import { AddItemModal, NoItemsFound, SettingsHeader } from 'components';
|
||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { textInputClasses } from 'styles';
|
||||
import { buttonClasses, textInputClasses } from 'styles';
|
||||
import type { Bookmark, BookmarkGroup } from 'types';
|
||||
import DebouncedGroupSettingsItem from './DebouncedGroupSettingsItem';
|
||||
|
||||
@@ -175,12 +175,16 @@ const BookmarkSettings = () => {
|
||||
/>
|
||||
</Group>
|
||||
<Group mt={'1rem'}>
|
||||
<Button type='submit' color={'green'}>
|
||||
<Button
|
||||
type='submit'
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleClose}
|
||||
>
|
||||
Cancel
|
||||
|
||||
@@ -420,12 +420,16 @@ function DebouncedGroupSettingsItem({
|
||||
align='center'
|
||||
justify='center'
|
||||
>
|
||||
<Button type='submit' color={'green'}>
|
||||
<Button
|
||||
type='submit'
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={() => {
|
||||
setPopoverOpened(false);
|
||||
form.reset();
|
||||
|
||||
@@ -15,10 +15,10 @@ import { isNotEmpty, useForm } from '@mantine/form';
|
||||
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||
import { AddItemModal, NoItemsFound, SettingsHeader } from 'components';
|
||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FaTerminal } from 'react-icons/fa';
|
||||
import { FaComputer, FaDesktop } from 'react-icons/fa6';
|
||||
import { popoverClasses, selectClasses, textInputClasses } from 'styles';
|
||||
import { buttonClasses, popoverClasses, selectClasses, textInputClasses } from 'styles';
|
||||
import type { GuacamoleClient } from 'types';
|
||||
import DebouncedGuacamoleClient from './DebouncedGuacamoleClient';
|
||||
import GuacamoleClientSettingsItem from './GuacamoleClientSettingsItem';
|
||||
@@ -65,6 +65,12 @@ const GuacamoleClients = () => {
|
||||
form.reset();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch === searchValue) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [debouncedSearch]);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<AddItemModal
|
||||
@@ -169,12 +175,16 @@ const GuacamoleClients = () => {
|
||||
/>
|
||||
</Group>
|
||||
<Group mt={'1rem'}>
|
||||
<Button type='submit' color={'green'}>
|
||||
<Button
|
||||
type='submit'
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleClose}
|
||||
>
|
||||
Cancel
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||
import { AddItemModal, NoItemsFound, SettingsHeader } from 'components';
|
||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { textInputClasses } from 'styles';
|
||||
import { buttonClasses, textInputClasses } from 'styles';
|
||||
import type { Message } from 'types';
|
||||
import DebouncedMessage from './DebouncedMessage';
|
||||
|
||||
@@ -53,6 +53,12 @@ const MessageSettings = () => {
|
||||
}
|
||||
}, [debounced]);
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch === searchValue) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [debouncedSearch]);
|
||||
|
||||
return (
|
||||
<Stack w={'100%'}>
|
||||
<SettingsHeader
|
||||
@@ -112,12 +118,16 @@ const MessageSettings = () => {
|
||||
}
|
||||
/>
|
||||
<Group mt={'1rem'}>
|
||||
<Button type='submit' color={'green'}>
|
||||
<Button
|
||||
type='submit'
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleClose}
|
||||
>
|
||||
Cancel
|
||||
|
||||
@@ -17,25 +17,15 @@ import type { PersonalData } from 'types';
|
||||
|
||||
const PersonalizationSettings = () => {
|
||||
const endpoint = 'api/personalData';
|
||||
const {
|
||||
data: personalData,
|
||||
isFetched: personalDataIsFetched,
|
||||
isFetching: personalDataIsFetching,
|
||||
} = useQueryAPI({
|
||||
const { data: personalData, isFetching: personalDataIsFetching } = useQueryAPI({
|
||||
endpoint: endpoint,
|
||||
});
|
||||
const [personal, setPersonal] = useState<PersonalData>();
|
||||
const [personal, setPersonal] = useState<PersonalData>(personalData?.[0] || {});
|
||||
const [update, setUpdate] = useState<any>({});
|
||||
const [debounced] = useDebouncedValue(update, 1000);
|
||||
const { mutateAsync } = useMutationAPI();
|
||||
const { isMobile, theme } = useCommonHooks();
|
||||
|
||||
useEffect(() => {
|
||||
if (personalData && personalDataIsFetched) {
|
||||
setPersonal(personalData[0]);
|
||||
}
|
||||
}, [personalData, personalDataIsFetched]);
|
||||
|
||||
useEffect(() => {
|
||||
if (Object.keys(debounced).length) {
|
||||
setPersonal(update);
|
||||
|
||||
@@ -77,6 +77,7 @@ function DebouncedSearchProvider({
|
||||
position: 'absolute',
|
||||
right: '1rem',
|
||||
top: '.5rem',
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
<ManagementPill
|
||||
|
||||
@@ -24,6 +24,7 @@ import { FiPower } from 'react-icons/fi';
|
||||
import * as si from 'react-icons/si';
|
||||
import * as vsc from 'react-icons/vsc';
|
||||
import {
|
||||
buttonClasses,
|
||||
popoverClasses,
|
||||
selectClasses,
|
||||
switchClasses,
|
||||
@@ -236,12 +237,16 @@ const SearchProviderSettings = () => {
|
||||
</Group>
|
||||
|
||||
<Group mt={'1rem'}>
|
||||
<Button type='submit' color={'green'}>
|
||||
<Button
|
||||
type='submit'
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleClose}
|
||||
>
|
||||
Cancel
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Button, Card, FileInput, Group, Image, Stack, TextInput } from '@mantine/core';
|
||||
import { useFileUploadAPI } from 'hooks/useAPI';
|
||||
import { buttonClasses } from 'styles';
|
||||
|
||||
export function AddBackground({
|
||||
fileName,
|
||||
@@ -131,7 +132,8 @@ export function AddBackground({
|
||||
Upload
|
||||
</Button>
|
||||
<Button
|
||||
color='var(--mantine-color-red-6)'
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={() => {
|
||||
handleAddBackgroundModalClose();
|
||||
}}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Button, Card, Group, Stack, Text } from '@mantine/core';
|
||||
import { useMutationAPI } from 'hooks';
|
||||
import { buttonClasses } from 'styles';
|
||||
|
||||
export function DeleteBackground({
|
||||
fileName,
|
||||
@@ -63,7 +64,12 @@ export function DeleteBackground({
|
||||
>
|
||||
DELETE
|
||||
</Button>
|
||||
<Button mt={'auto'} onClick={handleDeleteBackgroundModalClose}>
|
||||
<Button
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
mt={'auto'}
|
||||
onClick={handleDeleteBackgroundModalClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Button, Group, Image, Stack, Text, TextInput } from '@mantine/core';
|
||||
import { useCommonHooks, useMutationAPI } from 'hooks';
|
||||
import { useState } from 'react';
|
||||
import { textInputClasses } from 'styles';
|
||||
import { buttonClasses, textInputClasses } from 'styles';
|
||||
|
||||
export function EditBackground({
|
||||
fileName,
|
||||
@@ -54,7 +54,8 @@ export function EditBackground({
|
||||
<Group>
|
||||
<Button
|
||||
mt={'auto'}
|
||||
color='green'
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={() => {
|
||||
if (
|
||||
!rename.endsWith('.png') &&
|
||||
@@ -88,8 +89,9 @@ export function EditBackground({
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
mt={'auto'}
|
||||
color={'var(--mantine-color-red-6)'}
|
||||
onClick={handleEditBackgroundModalClose}
|
||||
>
|
||||
Cancel
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Button, Group, Modal, Text, TextInput } from '@mantine/core';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FaTag } from 'react-icons/fa';
|
||||
import { modalClasses, textInputClasses } from 'styles';
|
||||
import { buttonClasses, modalClasses, textInputClasses } from 'styles';
|
||||
import type { Theme, ThemePlaylist } from 'types';
|
||||
import { ThemePreviewMiddleware } from '../../Themes';
|
||||
import { TimeOfDay } from './TimeOfDay';
|
||||
@@ -115,12 +115,17 @@ export function ThemePlaylistModal({
|
||||
})}
|
||||
</Group>
|
||||
<Group mt={'1rem'}>
|
||||
<Button color={'green'} onClick={handleSavePlaylist}>
|
||||
<Button
|
||||
color={'green'}
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleSavePlaylist}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
setThemeList('[]');
|
||||
|
||||
@@ -19,6 +19,7 @@ import { useRef, useState } from 'react';
|
||||
import { FaShuffle } from 'react-icons/fa6';
|
||||
import { FiImage, FiSave, FiShuffle, FiX } from 'react-icons/fi';
|
||||
import {
|
||||
buttonClasses,
|
||||
colorSwatchClasses,
|
||||
scrollAreaClasses,
|
||||
textClasses,
|
||||
@@ -657,14 +658,15 @@ export function ThemeEditor({
|
||||
<Group>
|
||||
<Button
|
||||
disabled={JSON.stringify(defaultTheme) === JSON.stringify(selectedTheme)}
|
||||
color={'green'}
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleSaveTheme}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={() => {
|
||||
handleClose();
|
||||
closeBackgroundPicker();
|
||||
|
||||
@@ -33,11 +33,7 @@ export function Themes() {
|
||||
const allThemes: Theme[] = allThemeData?.filter((a: Theme) =>
|
||||
a.name.toLowerCase().includes((debouncedSearch as string).toLowerCase()),
|
||||
);
|
||||
const {
|
||||
data: backgroundData,
|
||||
isFetched: backgroundDataIsFetched,
|
||||
isFetching: backgroundDataIsFetching,
|
||||
} = useQueryAPI({
|
||||
const { data: backgroundData, isFetching: backgroundDataIsFetching } = useQueryAPI({
|
||||
endpoint: backgroundsEndpoint,
|
||||
});
|
||||
const { data: themePlaylistData } = useQueryAPI({
|
||||
@@ -50,7 +46,9 @@ export function Themes() {
|
||||
backgroundModalOpened,
|
||||
{ open: openBackgroundModal, close: closeBackgroundModal },
|
||||
] = useDisclosure(false);
|
||||
const [backgroundList, setBackgroundList] = useState<string[]>(['None']);
|
||||
const backgroundList = backgroundData
|
||||
? ['None', ...backgroundData.sort((a: string, b: string) => a.localeCompare(b))]
|
||||
: ['None'];
|
||||
const inUseBackgrounds: string[] = [
|
||||
...new Set(
|
||||
allThemes
|
||||
@@ -76,6 +74,7 @@ export function Themes() {
|
||||
textShadowsEnabled: 0,
|
||||
appShadowsEnabled: 0,
|
||||
});
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isNew, setIsNew] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
@@ -93,15 +92,6 @@ export function Themes() {
|
||||
openThemeModal();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (backgroundData && backgroundDataIsFetched) {
|
||||
setBackgroundList([
|
||||
'None',
|
||||
...backgroundData.sort((a: string, b: string) => a.localeCompare(b)),
|
||||
]);
|
||||
}
|
||||
}, [backgroundData, backgroundDataIsFetched]);
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch === searchValue) {
|
||||
setIsLoading(false);
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||
import { AddItemModal, NoItemsFound, SettingsHeader } from 'components';
|
||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { popoverClasses, textInputClasses } from 'styles';
|
||||
import { buttonClasses, popoverClasses, textInputClasses } from 'styles';
|
||||
import type { WolClient } from 'types';
|
||||
import DebouncedWolClient from './DebouncedWolClient';
|
||||
import WolClientSettingsItem from './WolClientSettingsItem';
|
||||
@@ -116,12 +116,16 @@ const WolClientSettings = () => {
|
||||
/>
|
||||
</Group>
|
||||
<Group mt={'1rem'}>
|
||||
<Button type='submit' color={'green'}>
|
||||
<Button
|
||||
type='submit'
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
className={buttonClasses.cancelButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleClose}
|
||||
>
|
||||
Cancel
|
||||
|
||||
@@ -74,3 +74,27 @@
|
||||
color: var(--mantine-color-background-0) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.saveButton {
|
||||
&.root {
|
||||
background-color: var(--mantine-color-green-filled);
|
||||
.label {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--mantine-color-green-filled-hover) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.cancelButton {
|
||||
&.root {
|
||||
background-color: var(--mantine-color-red-filled);
|
||||
.label {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--mantine-color-red-filled-hover) !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user