diff --git a/interface/package.json b/interface/package.json index aa12e4a38..3dfbd7dfb 100644 --- a/interface/package.json +++ b/interface/package.json @@ -25,13 +25,12 @@ "@alova/adapter-xhr": "^2.0.4", "@emotion/react": "^11.13.0", "@emotion/styled": "^11.13.0", - "@mui/icons-material": "^5.16.6", - "@mui/material": "^5.16.6", + "@mui/icons-material": "^5.16.7", + "@mui/material": "^5.16.7", "@table-library/react-table-library": "4.1.7", "alova": "^3.0.5", "async-validator": "^4.2.5", "jwt-decode": "^4.0.0", - "lodash-es": "^4.17.21", "mime-types": "^2.1.35", "preact": "^10.23.1", "react": "^18.3.1", @@ -50,7 +49,6 @@ "@preact/preset-vite": "^2.9.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/babel__core": "^7", - "@types/lodash-es": "^4.17.12", "@types/node": "^22.1.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", diff --git a/interface/src/AppRouting.tsx b/interface/src/AppRouting.tsx index a8268a897..f7d6eac62 100644 --- a/interface/src/AppRouting.tsx +++ b/interface/src/AppRouting.tsx @@ -1,5 +1,5 @@ import { useContext, useEffect } from 'react'; -import { Navigate, Route, Routes, useLocation } from 'react-router-dom'; +import { Navigate, Route, Routes } from 'react-router-dom'; import { toast } from 'react-toastify'; import AuthenticatedRouting from 'AuthenticatedRouting'; diff --git a/interface/src/SignIn.tsx b/interface/src/SignIn.tsx index 241feef2c..409cb36e2 100644 --- a/interface/src/SignIn.tsx +++ b/interface/src/SignIn.tsx @@ -4,9 +4,7 @@ import { toast } from 'react-toastify'; import ForwardIcon from '@mui/icons-material/Forward'; import { Box, Button, Paper, Typography } from '@mui/material'; -import * as AuthenticationApi from 'api/authentication'; -import { PROJECT_NAME } from 'api/env'; - +import * as AuthenticationApi from 'components/routing/authentication'; import { useRequest } from 'alova/client'; import type { ValidateFieldsError } from 'async-validator'; import { @@ -15,6 +13,7 @@ import { ValidatedTextField } from 'components'; import { AuthenticationContext } from 'contexts/authentication'; +import { PROJECT_NAME } from 'env'; import { useI18nContext } from 'i18n/i18n-react'; import type { SignInRequest } from 'types'; import { onEnterCallback, updateValue } from 'utils'; diff --git a/interface/src/app/main/api.ts b/interface/src/api/app.ts similarity index 99% rename from interface/src/app/main/api.ts rename to interface/src/api/app.ts index 66c0f14f8..3e605e656 100644 --- a/interface/src/app/main/api.ts +++ b/interface/src/api/app.ts @@ -17,7 +17,7 @@ import type { Settings, WriteAnalogSensor, WriteTemperatureSensor -} from './types'; +} from '../app/main/types'; // DashboardDevices export const readCoreData = () => alovaInstance.Get(`/rest/coreData`); diff --git a/interface/src/api/endpoints.ts b/interface/src/api/endpoints.ts index 5e9fdb3e6..6a8f1d412 100644 --- a/interface/src/api/endpoints.ts +++ b/interface/src/api/endpoints.ts @@ -2,7 +2,7 @@ import { xhrRequestAdapter } from '@alova/adapter-xhr'; import { createAlova } from 'alova'; import ReactHook from 'alova/react'; -import { unpack } from '../api/unpack'; +import { unpack } from './unpack'; export const ACCESS_TOKEN = 'access_token'; diff --git a/interface/src/app/main/CustomEntities.tsx b/interface/src/app/main/CustomEntities.tsx index 38c7b9c47..bbaaa0903 100644 --- a/interface/src/app/main/CustomEntities.tsx +++ b/interface/src/app/main/CustomEntities.tsx @@ -29,8 +29,8 @@ import { } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; +import { readCustomEntities, writeCustomEntities } from '../../api/app'; import SettingsCustomEntitiesDialog from './CustomEntitiesDialog'; -import { readCustomEntities, writeCustomEntities } from './api'; import { DeviceValueTypeNames, DeviceValueUOM_s } from './types'; import type { Entities, EntityItem } from './types'; import { entityItemValidation } from './validators'; diff --git a/interface/src/app/main/Customizations.tsx b/interface/src/app/main/Customizations.tsx index 269302270..5dc5214bc 100644 --- a/interface/src/app/main/Customizations.tsx +++ b/interface/src/app/main/Customizations.tsx @@ -26,7 +26,7 @@ import { Typography } from '@mui/material'; -import * as SystemApi from 'api/system'; +import { restart } from 'api/system'; import { Body, @@ -50,7 +50,13 @@ import { } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; -import * as EMSESP from './api'; +import { + readDeviceEntities, + readDevices, + resetCustomizations, + writeCustomizationEntities, + writeDeviceName +} from '../../api/app'; import SettingsCustomizationsDialog from './CustomizationsDialog'; import EntityMaskToggle from './EntityMaskToggle'; import OptionIcon from './OptionIcon'; @@ -77,7 +83,7 @@ const Customizations = () => { useLayoutTitle(LL.CUSTOMIZATIONS()); // fetch devices first - const { data: devices, send: fetchDevices } = useRequest(EMSESP.readDevices); + const { data: devices, send: fetchDevices } = useRequest(readDevices); const [selectedDevice, setSelectedDevice] = useState( Number(useLocation().state) || -1 @@ -86,27 +92,26 @@ const Customizations = () => { useState(''); // needed for API URL const [selectedDeviceName, setSelectedDeviceName] = useState(''); - const { send: resetCustomizations } = useRequest(EMSESP.resetCustomizations(), { + const { send: sendResetCustomizations } = useRequest(resetCustomizations(), { immediate: false }); - const { send: writeDeviceName } = useRequest( - (data: { id: number; name: string }) => EMSESP.writeDeviceName(data), + const { send: sendDeviceName } = useRequest( + (data: { id: number; name: string }) => writeDeviceName(data), { immediate: false } ); - const { send: writeCustomizationEntities } = useRequest( - (data: { id: number; entity_ids: string[] }) => - EMSESP.writeCustomizationEntities(data), + const { send: sendCustomizationEntities } = useRequest( + (data: { id: number; entity_ids: string[] }) => writeCustomizationEntities(data), { immediate: false } ); - const { send: readDeviceEntities } = useRequest( - (data: number) => EMSESP.readDeviceEntities(data), + const { send: sendDeviceEntities } = useRequest( + (data: number) => readDeviceEntities(data), { initialData: [], immediate: false @@ -127,7 +132,7 @@ const Customizations = () => { ); }; - const { send: restartCommand } = useRequest(SystemApi.restart(), { + const { send: sendRestart } = useRequest(restart(), { immediate: false }); @@ -228,7 +233,7 @@ const Customizations = () => { useEffect(() => { if (devices && selectedDevice !== -1) { - void readDeviceEntities(selectedDevice); + void sendDeviceEntities(selectedDevice); const id = devices.devices.findIndex((d) => d.i === selectedDevice); if (id === -1) { setSelectedDevice(-1); @@ -242,8 +247,8 @@ const Customizations = () => { } }, [devices, selectedDevice]); - const restart = async () => { - await restartCommand().catch((error: Error) => { + const doRestart = async () => { + await sendRestart().catch((error: Error) => { toast.error(error.message); }); setRestarting(true); @@ -324,7 +329,7 @@ const Customizations = () => { const resetCustomization = async () => { try { - await resetCustomizations(); + await sendResetCustomizations(); toast.info(LL.CUSTOMIZATIONS_RESTART()); } catch (error) { toast.error((error as Error).message); @@ -384,7 +389,7 @@ const Customizations = () => { return; } - await writeCustomizationEntities({ + await sendCustomizationEntities({ id: selectedDevice, entity_ids: masked_entities }).catch((error: Error) => { @@ -399,7 +404,7 @@ const Customizations = () => { }; const renameDevice = async () => { - await writeDeviceName({ id: selectedDevice, name: selectedDeviceName }) + await sendDeviceName({ id: selectedDevice, name: selectedDeviceName }) .then(() => { toast.success(LL.UPDATED_OF(LL.NAME(1))); }) @@ -673,7 +678,7 @@ const Customizations = () => { startIcon={} variant="contained" color="error" - onClick={restart} + onClick={doRestart} > {LL.RESTART()} @@ -688,7 +693,7 @@ const Customizations = () => { startIcon={} variant="outlined" color="secondary" - onClick={() => devices && readDeviceEntities(selectedDevice)} + onClick={() => devices && sendDeviceEntities(selectedDevice)} > {LL.CANCEL()} diff --git a/interface/src/app/main/Devices.tsx b/interface/src/app/main/Devices.tsx index d7faf8598..4d13c09ed 100644 --- a/interface/src/app/main/Devices.tsx +++ b/interface/src/app/main/Devices.tsx @@ -61,7 +61,7 @@ import { ButtonRow, MessageBox, SectionContent, useLayoutTitle } from 'component import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; -import * as EMSESP from './api'; +import { readCoreData, readDeviceData, writeDeviceValue } from '../../api/app'; import DeviceIcon from './DeviceIcon'; import DashboardDevicesDialog from './DevicesDialog'; import { formatValue } from './deviceValue'; @@ -84,18 +84,15 @@ const Devices = () => { useLayoutTitle(LL.DEVICES()); - const { data: coreData, send: readCoreData } = useRequest( - () => EMSESP.readCoreData(), - { - initialData: { - connected: true, - devices: [] - } + const { data: coreData, send: sendCoreData } = useRequest(() => readCoreData(), { + initialData: { + connected: true, + devices: [] } - ); + }); - const { data: deviceData, send: readDeviceData } = useRequest( - (id: number) => EMSESP.readDeviceData(id), + const { data: deviceData, send: sendDeviceData } = useRequest( + (id: number) => readDeviceData(id), { initialData: { data: [] @@ -104,8 +101,8 @@ const Devices = () => { } ); - const { loading: submitting, send: writeDeviceValue } = useRequest( - (data: { id: number; c: string; v: unknown }) => EMSESP.writeDeviceValue(data), + const { loading: submitting, send: sendDeviceValue } = useRequest( + (data: { id: number; c: string; v: unknown }) => writeDeviceValue(data), { immediate: false } @@ -287,7 +284,7 @@ const Devices = () => { async function onSelectChange(action: Action, state: State) { setSelectedDevice(state.id as number); if (action.type === 'ADD_BY_ID_EXCLUSIVELY') { - await readDeviceData(state.id as number); + await sendDeviceData(state.id as number); } } @@ -322,7 +319,7 @@ const Devices = () => { const refreshData = () => { if (!deviceValueDialogOpen) { - selectedDevice ? void readDeviceData(selectedDevice) : void readCoreData(); + selectedDevice ? void sendDeviceData(selectedDevice) : void sendCoreData(); } }; @@ -444,7 +441,7 @@ const Devices = () => { const deviceValueDialogSave = async (devicevalue: DeviceValue) => { const id = Number(device_select.state.id); - await writeDeviceValue({ id, c: devicevalue.c ?? '', v: devicevalue.v }) + await sendDeviceValue({ id, c: devicevalue.c ?? '', v: devicevalue.v }) .then(() => { toast.success(LL.WRITE_CMD_SENT()); }) @@ -453,7 +450,7 @@ const Devices = () => { }) .finally(async () => { setDeviceValueDialogOpen(false); - await readDeviceData(id); + await sendDeviceData(id); setSelectedDeviceValue(undefined); }); }; diff --git a/interface/src/app/main/Help.tsx b/interface/src/app/main/Help.tsx index 697026a68..4ac0eb1ae 100644 --- a/interface/src/app/main/Help.tsx +++ b/interface/src/app/main/Help.tsx @@ -17,20 +17,20 @@ import { Typography } from '@mui/material'; -import * as SystemApi from 'api/system'; +import { readSystemStatus } from 'api/system'; -import * as EMSESP from 'app/main/api'; import { useRequest } from 'alova/client'; import { SectionContent, useLayoutTitle } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; +import { API } from '../../api/app'; import type { APIcall } from './types'; const Help = () => { const { LL } = useI18nContext(); useLayoutTitle(LL.HELP_OF('')); - const { send: getAPI } = useRequest((data: APIcall) => EMSESP.API(data), { + const { send: getAPI } = useRequest((data: APIcall) => API(data), { immediate: false }).onSuccess((event) => { const anchor = document.createElement('a'); @@ -47,7 +47,7 @@ const Help = () => { toast.info(LL.DOWNLOAD_SUCCESSFUL()); }); - const { data, loading } = useRequest(SystemApi.readSystemStatus); + const { data, loading } = useRequest(readSystemStatus); const callAPI = async (device: string, entity: string) => { await getAPI({ device, entity, id: 0 }).catch((error: Error) => { diff --git a/interface/src/app/main/Modules.tsx b/interface/src/app/main/Modules.tsx index 81bb050bf..cb366715f 100644 --- a/interface/src/app/main/Modules.tsx +++ b/interface/src/app/main/Modules.tsx @@ -27,8 +27,8 @@ import { } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; +import { readModules, writeModules } from '../../api/app'; import ModulesDialog from './ModulesDialog'; -import { readModules, writeModules } from './api'; import type { ModuleItem, Modules } from './types'; const Modules = () => { diff --git a/interface/src/app/main/Scheduler.tsx b/interface/src/app/main/Scheduler.tsx index 4b798285f..b2a526560 100644 --- a/interface/src/app/main/Scheduler.tsx +++ b/interface/src/app/main/Scheduler.tsx @@ -28,8 +28,8 @@ import { } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; +import { readSchedule, writeSchedule } from '../../api/app'; import SettingsSchedulerDialog from './SchedulerDialog'; -import { readSchedule, writeSchedule } from './api'; import { ScheduleFlag } from './types'; import type { Schedule, ScheduleItem } from './types'; import { schedulerItemValidation } from './validators'; diff --git a/interface/src/app/main/Sensors.tsx b/interface/src/app/main/Sensors.tsx index 8196514f7..58cdd02c6 100644 --- a/interface/src/app/main/Sensors.tsx +++ b/interface/src/app/main/Sensors.tsx @@ -25,7 +25,11 @@ import { ButtonRow, SectionContent, useLayoutTitle } from 'components'; import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; -import * as EMSESP from './api'; +import { + readSensorData, + writeAnalogSensor, + writeTemperatureSensor +} from '../../api/app'; import DashboardSensorsAnalogDialog from './SensorsAnalogDialog'; import DashboardSensorsTemperatureDialog from './SensorsTemperatureDialog'; import { @@ -56,8 +60,8 @@ const Sensors = () => { const [analogDialogOpen, setAnalogDialogOpen] = useState(false); const [creating, setCreating] = useState(false); - const { data: sensorData, send: fetchSensorData } = useRequest( - () => EMSESP.readSensorData(), + const { data: sensorData, send: sendSensorData } = useRequest( + () => readSensorData(), { initialData: { ts: [], @@ -68,15 +72,15 @@ const Sensors = () => { } ); - const { send: writeTemperatureSensor } = useRequest( - (data: WriteTemperatureSensor) => EMSESP.writeTemperatureSensor(data), + const { send: sendTemperatureSensor } = useRequest( + (data: WriteTemperatureSensor) => writeTemperatureSensor(data), { immediate: false } ); - const { send: writeAnalogSensor } = useRequest( - (data: WriteAnalogSensor) => EMSESP.writeAnalogSensor(data), + const { send: sendAnalogSensor } = useRequest( + (data: WriteAnalogSensor) => writeAnalogSensor(data), { immediate: false } @@ -195,7 +199,7 @@ const Sensors = () => { ); useEffect(() => { - const timer = setInterval(() => fetchSensorData(), 30000); + const timer = setInterval(() => sendSensorData(), 30000); return () => { clearInterval(timer); }; @@ -265,7 +269,7 @@ const Sensors = () => { }; const onTemperatureDialogSave = async (ts: TemperatureSensor) => { - await writeTemperatureSensor({ id: ts.id, name: ts.n, offset: ts.o }) + await sendTemperatureSensor({ id: ts.id, name: ts.n, offset: ts.o }) .then(() => { toast.success(LL.UPDATED_OF(LL.SENSOR(1))); }) @@ -275,7 +279,7 @@ const Sensors = () => { .finally(async () => { setTemperatureDialogOpen(false); setSelectedTemperatureSensor(undefined); - await fetchSensorData(); + await sendSensorData(); }); }; @@ -310,7 +314,7 @@ const Sensors = () => { }; const onAnalogDialogSave = async (as: AnalogSensor) => { - await writeAnalogSensor({ + await sendAnalogSensor({ id: as.id, gpio: as.g, name: as.n, @@ -329,7 +333,7 @@ const Sensors = () => { .finally(async () => { setAnalogDialogOpen(false); setSelectedAnalogSensor(undefined); - await fetchSensorData(); + await sendSensorData(); }); }; @@ -503,7 +507,7 @@ const Sensors = () => { startIcon={} variant="outlined" color="secondary" - onClick={fetchSensorData} + onClick={sendSensorData} > {LL.REFRESH()} diff --git a/interface/src/app/settings/APSettings.tsx b/interface/src/app/settings/APSettings.tsx index 2c828ff64..4e7a5087a 100644 --- a/interface/src/app/settings/APSettings.tsx +++ b/interface/src/app/settings/APSettings.tsx @@ -18,7 +18,6 @@ import { useLayoutTitle } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; -import { range } from 'lodash-es'; import type { APSettingsType } from 'types'; import { APProvisionMode } from 'types'; import { numberValue, updateValueDirty, useRest } from 'utils'; @@ -73,6 +72,11 @@ const APSettings = () => { } }; + // no lodash - https://asleepace.com/blog/typescript-range-without-a-loop/ + function range(a: number, b: number): number[] { + return a < b ? [a, ...range(a + 1, b)] : [b]; + } + return ( <> { - const { data: hardwareData } = useRequest(SystemApi.readHardwareStatus, { + const { data: hardwareData } = useRequest(readHardwareStatus, { initialData: { psram: false } }); @@ -66,8 +66,8 @@ const ApplicationSettings = () => { errorMessage, restartNeeded } = useRest({ - read: EMSESP.readSettings, - update: EMSESP.writeSettings + read: readSettings, + update: writeSettings }); const [restarting, setRestarting] = useState(); @@ -84,7 +84,7 @@ const ApplicationSettings = () => { const [fieldErrors, setFieldErrors] = useState(); const { loading: processingBoard, send: readBoardProfile } = useRequest( - (boardProfile: string) => EMSESP.getBoardProfile(boardProfile), + (boardProfile: string) => getBoardProfile(boardProfile), { immediate: false } @@ -105,7 +105,7 @@ const ApplicationSettings = () => { }); }); - const { send: restartCommand } = useRequest(SystemApi.restart(), { + const { send: restartCommand } = useRequest(restart(), { immediate: false }); diff --git a/interface/src/app/settings/UploadDownload.tsx b/interface/src/app/settings/UploadDownload.tsx index 67103a6c3..75cf120c8 100644 --- a/interface/src/app/settings/UploadDownload.tsx +++ b/interface/src/app/settings/UploadDownload.tsx @@ -5,8 +5,15 @@ import DownloadIcon from '@mui/icons-material/GetApp'; import { Box, Button, Divider, Link, Typography } from '@mui/material'; import * as SystemApi from 'api/system'; +import { + API, + getCustomizations, + getEntities, + getSchedule, + getSettings +} from 'api/app'; +import { getDevVersion, getStableVersion } from 'api/system'; -import * as EMSESP from 'app/main/api'; import { useRequest } from 'alova/client'; import type { APIcall } from 'app/main/types'; import { @@ -24,31 +31,31 @@ const UploadDownload = () => { const [restarting, setRestarting] = useState(); const [md5, setMd5] = useState(); - const { send: getSettings } = useRequest(EMSESP.getSettings(), { + const { send: sendSettings } = useRequest(getSettings(), { immediate: false }).onSuccess((event) => { saveFile(event.data, 'settings.json'); }); - const { send: getCustomizations } = useRequest(EMSESP.getCustomizations(), { + const { send: sendCustomizations } = useRequest(getCustomizations(), { immediate: false }).onSuccess((event) => { saveFile(event.data, 'customizations.json'); }); - const { send: getEntities } = useRequest(EMSESP.getEntities(), { + const { send: sendEntities } = useRequest(getEntities(), { immediate: false }).onSuccess((event) => { saveFile(event.data, 'entities.json'); }); - const { send: getSchedule } = useRequest(EMSESP.getSchedule(), { + const { send: sendSchedule } = useRequest(getSchedule(), { immediate: false }).onSuccess((event) => { saveFile(event.data, 'schedule.json'); }); - const { send: getAPI } = useRequest((data: APIcall) => EMSESP.API(data), { + const { send: getAPI } = useRequest((data: APIcall) => API(data), { immediate: false }).onSuccess((event) => { saveFile( @@ -64,8 +71,8 @@ const UploadDownload = () => { } = useRequest(SystemApi.readHardwareStatus); // called immediately to get the latest version, on page load - const { data: latestVersion } = useRequest(SystemApi.getStableVersion); - const { data: latestDevVersion } = useRequest(SystemApi.getDevVersion); + const { data: latestVersion } = useRequest(getStableVersion); + const { data: latestDevVersion } = useRequest(getDevVersion); const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/'; const STABLE_RELNOTES_URL = @@ -131,25 +138,25 @@ const UploadDownload = () => { }; const downloadSettings = async () => { - await getSettings().catch((error: Error) => { + await sendSettings().catch((error: Error) => { toast.error(error.message); }); }; const downloadCustomizations = async () => { - await getCustomizations().catch((error: Error) => { + await sendCustomizations().catch((error: Error) => { toast.error(error.message); }); }; const downloadEntities = async () => { - await getEntities().catch((error: Error) => { + await sendEntities().catch((error: Error) => { toast.error(error.message); }); }; const downloadSchedule = async () => { - await getSchedule().catch((error: Error) => { + await sendSchedule().catch((error: Error) => { toast.error(error.message); }); }; diff --git a/interface/src/app/status/Activity.tsx b/interface/src/app/status/Activity.tsx index 94bf4698f..ae43f3d51 100644 --- a/interface/src/app/status/Activity.tsx +++ b/interface/src/app/status/Activity.tsx @@ -18,7 +18,7 @@ import { ButtonRow, FormLoader, SectionContent, useLayoutTitle } from 'component import { useI18nContext } from 'i18n/i18n-react'; import type { Translation } from 'i18n/i18n-types'; -import * as EMSESP from '../main/api'; +import * as EMSESP from '../../api/app'; import type { Stat } from '../main/types'; const SystemActivity = () => { diff --git a/interface/src/components/layout/Layout.tsx b/interface/src/components/layout/Layout.tsx index 23f087adb..a552ea915 100644 --- a/interface/src/components/layout/Layout.tsx +++ b/interface/src/components/layout/Layout.tsx @@ -4,8 +4,7 @@ import { useLocation } from 'react-router-dom'; import { Box, Toolbar } from '@mui/material'; -import { PROJECT_NAME } from 'api/env'; - +import { PROJECT_NAME } from 'env'; import type { RequiredChildrenProps } from 'utils'; import LayoutAppBar from './LayoutAppBar'; diff --git a/interface/src/components/layout/LayoutDrawer.tsx b/interface/src/components/layout/LayoutDrawer.tsx index 645fd4182..2bdf4d735 100644 --- a/interface/src/components/layout/LayoutDrawer.tsx +++ b/interface/src/components/layout/LayoutDrawer.tsx @@ -1,6 +1,6 @@ import { Box, Divider, Drawer, Toolbar, Typography, styled } from '@mui/material'; -import { PROJECT_NAME } from 'api/env'; +import { PROJECT_NAME } from 'env'; import { DRAWER_WIDTH } from './Layout'; import LayoutMenu from './LayoutMenu'; diff --git a/interface/src/components/routing/RequireAuthenticated.tsx b/interface/src/components/routing/RequireAuthenticated.tsx index c5fb96fd9..709e79ea1 100644 --- a/interface/src/components/routing/RequireAuthenticated.tsx +++ b/interface/src/components/routing/RequireAuthenticated.tsx @@ -2,8 +2,7 @@ import { useContext, useEffect } from 'react'; import type { FC } from 'react'; import { Navigate, useLocation } from 'react-router-dom'; -import { storeLoginRedirect } from 'api/authentication'; - +import { storeLoginRedirect } from 'components/routing/authentication'; import type { AuthenticatedContextValue } from 'contexts/authentication/context'; import { AuthenticatedContext, diff --git a/interface/src/components/routing/RequireUnauthenticated.tsx b/interface/src/components/routing/RequireUnauthenticated.tsx index d8e40ccc7..f98a78ac9 100644 --- a/interface/src/components/routing/RequireUnauthenticated.tsx +++ b/interface/src/components/routing/RequireUnauthenticated.tsx @@ -2,8 +2,7 @@ import { useContext } from 'react'; import type { FC } from 'react'; import { Navigate } from 'react-router-dom'; -import * as AuthenticationApi from 'api/authentication'; - +import { fetchLoginRedirect } from 'components/routing/authentication'; import { AuthenticationContext } from 'contexts/authentication'; import type { RequiredChildrenProps } from 'utils'; @@ -11,7 +10,7 @@ const RequireUnauthenticated: FC = ({ children }) => { const authenticationContext = useContext(AuthenticationContext); return authenticationContext.me ? ( - + ) : ( <>{children} ); diff --git a/interface/src/api/authentication.ts b/interface/src/components/routing/authentication.ts similarity index 96% rename from interface/src/api/authentication.ts rename to interface/src/components/routing/authentication.ts index 076b69bd5..822417b88 100644 --- a/interface/src/api/authentication.ts +++ b/interface/src/components/routing/authentication.ts @@ -4,7 +4,7 @@ import type * as H from 'history'; import { jwtDecode } from 'jwt-decode'; import type { Me, SignInRequest, SignInResponse } from 'types'; -import { ACCESS_TOKEN, alovaInstance } from './endpoints'; +import { ACCESS_TOKEN, alovaInstance } from '../../api/endpoints'; export const SIGN_IN_PATHNAME = 'loginPathname'; export const SIGN_IN_SEARCH = 'loginSearch'; diff --git a/interface/src/contexts/authentication/Authentication.tsx b/interface/src/contexts/authentication/Authentication.tsx index 9bd621dd4..ce182c814 100644 --- a/interface/src/contexts/authentication/Authentication.tsx +++ b/interface/src/contexts/authentication/Authentication.tsx @@ -3,11 +3,12 @@ import type { FC } from 'react'; import { redirect } from 'react-router-dom'; import { toast } from 'react-toastify'; -import * as AuthenticationApi from 'api/authentication'; import { ACCESS_TOKEN } from 'api/endpoints'; +import * as AuthenticationApi from 'components/routing/authentication'; import { useRequest } from 'alova/client'; import { LoadingSpinner } from 'components'; +import { verifyAuthorization } from 'components/routing/authentication'; import { useI18nContext } from 'i18n/i18n-react'; import type { Me } from 'types'; import type { RequiredChildrenProps } from 'utils'; @@ -20,12 +21,9 @@ const Authentication: FC = ({ children }) => { const [initialized, setInitialized] = useState(false); const [me, setMe] = useState(); - const { send: verifyAuthorization } = useRequest( - AuthenticationApi.verifyAuthorization(), - { - immediate: false - } - ); + const { send: sendVerifyAuthorization } = useRequest(verifyAuthorization(), { + immediate: false + }); const signIn = (accessToken: string) => { try { @@ -51,7 +49,7 @@ const Authentication: FC = ({ children }) => { const refresh = useCallback(async () => { const accessToken = AuthenticationApi.getStorage().getItem(ACCESS_TOKEN); if (accessToken) { - await verifyAuthorization() + await sendVerifyAuthorization() .then(() => { setMe(AuthenticationApi.decodeMeJWT(accessToken)); setInitialized(true); diff --git a/interface/src/api/env.ts b/interface/src/env.ts similarity index 100% rename from interface/src/api/env.ts rename to interface/src/env.ts diff --git a/interface/yarn.lock b/interface/yarn.lock index 0933f886a..8cad5c47a 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -815,16 +815,16 @@ __metadata: languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.16.6": - version: 5.16.6 - resolution: "@mui/core-downloads-tracker@npm:5.16.6" - checksum: 10c0/ee7655eda56e8eeb18ae600b24182c10caab4468d33179de3e76a783a827be9577afe114750835f7c9c7f555c0de0845c0500e91ed2e669b16399a1ffe41c33d +"@mui/core-downloads-tracker@npm:^5.16.7": + version: 5.16.7 + resolution: "@mui/core-downloads-tracker@npm:5.16.7" + checksum: 10c0/4644c850160d01232c1abdbed141e4fa70e155891a9c68f0c2cc3054b4a3cdc1d28cf2d6665366fd8c725b2b091db677e11831552889a4e4e14f1e44450cf654 languageName: node linkType: hard -"@mui/icons-material@npm:^5.16.6": - version: 5.16.6 - resolution: "@mui/icons-material@npm:5.16.6" +"@mui/icons-material@npm:^5.16.7": + version: 5.16.7 + resolution: "@mui/icons-material@npm:5.16.7" dependencies: "@babel/runtime": "npm:^7.23.9" peerDependencies: @@ -834,17 +834,17 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10c0/9d24d95e8b4606b5fa2a2e40319255e2e6da52845db50d2d3ca6fd526102be3c498ec1aa9be8d33aad52cf531749b15d490abca5f23af92afc86cf45dc62ce24 + checksum: 10c0/49bab1754334798acaf93187d27200cf90d7c50b6a019531594aeac9e5ced9168281fec70bb040792dc86c8bc0d3bf9a876f22cfbf86ad07941ca6bc6c564921 languageName: node linkType: hard -"@mui/material@npm:^5.16.6": - version: 5.16.6 - resolution: "@mui/material@npm:5.16.6" +"@mui/material@npm:^5.16.7": + version: 5.16.7 + resolution: "@mui/material@npm:5.16.7" dependencies: "@babel/runtime": "npm:^7.23.9" - "@mui/core-downloads-tracker": "npm:^5.16.6" - "@mui/system": "npm:^5.16.6" + "@mui/core-downloads-tracker": "npm:^5.16.7" + "@mui/system": "npm:^5.16.7" "@mui/types": "npm:^7.2.15" "@mui/utils": "npm:^5.16.6" "@popperjs/core": "npm:^2.11.8" @@ -867,7 +867,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 10c0/52cbffd87a36b9f8e16ba59030e89501e680ddea4d3dcf3db5d8fb7b86205444b00162e656c79571824a74769f879f39df2e7671d1e7ca8bc23602a7bf588dc5 + checksum: 10c0/b11419c1a77835413471f9352586fed65fb5de19c6737e121669da0484c441c7dd9939aa73fdad779482c30efaa694fb9fdcf18dcf418af07881e60eaff92b4f languageName: node linkType: hard @@ -909,9 +909,9 @@ __metadata: languageName: node linkType: hard -"@mui/system@npm:^5.16.6": - version: 5.16.6 - resolution: "@mui/system@npm:5.16.6" +"@mui/system@npm:^5.16.7": + version: 5.16.7 + resolution: "@mui/system@npm:5.16.7" dependencies: "@babel/runtime": "npm:^7.23.9" "@mui/private-theming": "npm:^5.16.6" @@ -933,7 +933,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: 10c0/493900594f51d1fc84994042e5cfa000b2d7664f86c8c0d62b87dbbb51cf7e789a700512f98e18c82e605beab38c20d0714ec25c46e2f6a5024f79f16db743f7 + checksum: 10c0/c07479c0728433847c1e3d7f57b96d9e0770cc814dfd1c9e070304955984a0b706832703b22388eb83906d1a01691f37047e2bac6a5e5c083e8c29a54302d476 languageName: node linkType: hard @@ -1429,22 +1429,6 @@ __metadata: languageName: node linkType: hard -"@types/lodash-es@npm:^4.17.12": - version: 4.17.12 - resolution: "@types/lodash-es@npm:4.17.12" - dependencies: - "@types/lodash": "npm:*" - checksum: 10c0/5d12d2cede07f07ab067541371ed1b838a33edb3c35cb81b73284e93c6fd0c4bbeaefee984e69294bffb53f62d7272c5d679fdba8e595ff71e11d00f2601dde0 - languageName: node - linkType: hard - -"@types/lodash@npm:*": - version: 4.17.7 - resolution: "@types/lodash@npm:4.17.7" - checksum: 10c0/40c965b5ffdcf7ff5c9105307ee08b782da228c01b5c0529122c554c64f6b7168fc8f11dc79aa7bae4e67e17efafaba685dc3a47e294dbf52a65ed2b67100561 - languageName: node - linkType: hard - "@types/minimatch@npm:*": version: 5.1.2 resolution: "@types/minimatch@npm:5.1.2" @@ -1676,14 +1660,13 @@ __metadata: "@emotion/react": "npm:^11.13.0" "@emotion/styled": "npm:^11.13.0" "@eslint/js": "npm:^9.8.0" - "@mui/icons-material": "npm:^5.16.6" - "@mui/material": "npm:^5.16.6" + "@mui/icons-material": "npm:^5.16.7" + "@mui/material": "npm:^5.16.7" "@preact/compat": "npm:^17.1.2" "@preact/preset-vite": "npm:^2.9.0" "@table-library/react-table-library": "npm:4.1.7" "@trivago/prettier-plugin-sort-imports": "npm:^4.3.0" "@types/babel__core": "npm:^7" - "@types/lodash-es": "npm:^4.17.12" "@types/node": "npm:^22.1.0" "@types/react": "npm:^18.3.3" "@types/react-dom": "npm:^18.3.0" @@ -1694,7 +1677,6 @@ __metadata: eslint: "npm:^9.8.0" eslint-config-prettier: "npm:^9.1.0" jwt-decode: "npm:^4.0.0" - lodash-es: "npm:^4.17.21" mime-types: "npm:^2.1.35" preact: "npm:^10.23.1" prettier: "npm:^3.3.3" @@ -4695,13 +4677,6 @@ __metadata: languageName: node linkType: hard -"lodash-es@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash-es@npm:4.17.21" - checksum: 10c0/fb407355f7e6cd523a9383e76e6b455321f0f153a6c9625e21a8827d10c54c2a2341bd2ae8d034358b60e07325e1330c14c224ff582d04612a46a4f0479ff2f2 - languageName: node - linkType: hard - "lodash.merge@npm:^4.6.2": version: 4.6.2 resolution: "lodash.merge@npm:4.6.2"