diff --git a/interface/package.json b/interface/package.json index dc09f548f..5c4fb7ae5 100644 --- a/interface/package.json +++ b/interface/package.json @@ -40,7 +40,7 @@ "react-dom": "latest", "react-dropzone": "^14.2.3", "react-icons": "^4.9.0", - "react-router-dom": "^6.12.1", + "react-router-dom": "^6.13.0", "react-toastify": "^9.1.3", "sockette": "^2.0.6", "typesafe-i18n": "^5.24.3", diff --git a/interface/src/api/ap.ts b/interface/src/api/ap.ts index f54ad1f59..a314227c2 100644 --- a/interface/src/api/ap.ts +++ b/interface/src/api/ap.ts @@ -5,11 +5,10 @@ import type { APSettings, APStatus } from 'types'; export const readAPStatus = () => alovaInstance.Get('/apStatus'); -// TODO change AXIOS to Alova +// TODO change APSettings AXIOS to Alova export function readAPSettings(): AxiosPromise { return AXIOS.get('/apSettings'); } - export function updateAPSettings(apSettings: APSettings): AxiosPromise { return AXIOS.post('/apSettings', apSettings); } diff --git a/interface/src/api/endpoints.ts b/interface/src/api/endpoints.ts index 3af7431db..987978963 100644 --- a/interface/src/api/endpoints.ts +++ b/interface/src/api/endpoints.ts @@ -6,9 +6,6 @@ import { unpack } from '../api/unpack'; import type { AxiosPromise, CancelToken, AxiosProgressEvent } from 'axios'; -export const WS_BASE_URL = '/ws/'; -export const ES_BASE_URL = '/es/'; - export const REST_BASE_URL = '/rest/'; export const API_BASE_URL = '/api/'; @@ -16,13 +13,14 @@ export const ACCESS_TOKEN = 'access_token'; const location = window.location; const webProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; +export const WS_BASE_URL = '/ws/'; +export const ES_BASE_URL = '/es/'; export const WEB_SOCKET_ROOT = webProtocol + '//' + location.host + WS_BASE_URL; export const EVENT_SOURCE_ROOT = location.protocol + '//' + location.host + ES_BASE_URL; export const alovaInstance = createAlova({ - baseURL: '/rest/', statesHook: ReactHook, - timeout: 50000, + timeout: 5000, requestAdapter: xhrRequestAdapter(), beforeRequest(method) { if (localStorage.getItem(ACCESS_TOKEN)) { diff --git a/interface/src/framework/ap/APStatusForm.tsx b/interface/src/framework/ap/APStatusForm.tsx index 611353513..ec754f796 100644 --- a/interface/src/framework/ap/APStatusForm.tsx +++ b/interface/src/framework/ap/APStatusForm.tsx @@ -28,7 +28,7 @@ export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => { }; const APStatusForm: FC = () => { - const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus()); + const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus); const { LL } = useI18nContext(); diff --git a/interface/src/framework/system/GeneralFileUpload.tsx b/interface/src/framework/system/GeneralFileUpload.tsx index 11ade4405..9c0a04e6c 100644 --- a/interface/src/framework/system/GeneralFileUpload.tsx +++ b/interface/src/framework/system/GeneralFileUpload.tsx @@ -1,5 +1,6 @@ import DownloadIcon from '@mui/icons-material/GetApp'; import { Typography, Button, Box } from '@mui/material'; +import { useRequest } from 'alova'; import { toast } from 'react-toastify'; import type { FileUploadConfig } from 'api/endpoints'; import type { AxiosPromise } from 'axios'; @@ -9,7 +10,6 @@ import { SingleUpload, useFileUpload } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; import * as EMSESP from 'project/api'; -import { extractErrorMessage } from 'utils'; interface UploadFileProps { uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise; @@ -18,6 +18,19 @@ interface UploadFileProps { const GeneralFileUpload: FC = ({ uploadGeneralFile }) => { const [uploadFile, cancelUpload, uploading, uploadProgress, md5] = useFileUpload({ upload: uploadGeneralFile }); + const { send: getSettings, onSuccess: onSuccessGetSettings } = useRequest(EMSESP.getSettings(), { + immediate: false + }); + const { send: getCustomizations, onSuccess: onSuccessgetCustomizations } = useRequest(EMSESP.getCustomizations(), { + immediate: false + }); + const { send: getEntities, onSuccess: onSuccessGetEntities } = useRequest(EMSESP.getEntities(), { + immediate: false + }); + const { send: getSchedule, onSuccess: onSuccessGetSchedule } = useRequest(EMSESP.getSchedule(), { + immediate: false + }); + const { LL } = useI18nContext(); const saveFile = (json: any, endpoint: string) => { @@ -35,56 +48,41 @@ const GeneralFileUpload: FC = ({ uploadGeneralFile }) => { toast.info(LL.DOWNLOAD_SUCCESSFUL()); }; + onSuccessGetSettings((event) => { + saveFile(event.data, 'settings'); + }); + onSuccessgetCustomizations((event) => { + saveFile(event.data, 'customizations'); + }); + onSuccessGetEntities((event) => { + saveFile(event.data, 'entities'); + }); + onSuccessGetSchedule((event) => { + saveFile(event.data, 'schedule'); + }); + const downloadSettings = async () => { - try { - const response = await EMSESP.getSettings(); - if (response.status !== 200) { - toast.error(LL.PROBLEM_LOADING()); - } else { - saveFile(response.data, 'settings'); - } - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } + await getSettings().catch((error) => { + toast.error(error.message); + }); }; const downloadCustomizations = async () => { - try { - const response = await EMSESP.getCustomizations(); - if (response.status !== 200) { - toast.error(LL.PROBLEM_LOADING()); - } else { - saveFile(response.data, 'customizations'); - } - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } + await getCustomizations().catch((error) => { + toast.error(error.message); + }); }; const downloadEntities = async () => { - try { - const response = await EMSESP.getEntities(); - if (response.status !== 200) { - toast.error(LL.PROBLEM_LOADING()); - } else { - saveFile(response.data, 'entities'); - } - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } + await getEntities().catch((error) => { + toast.error(error.message); + }); }; const downloadSchedule = async () => { - try { - const response = await EMSESP.getSchedule(); - if (response.status !== 200) { - toast.error(LL.PROBLEM_LOADING()); - } else { - saveFile(response.data, 'schedule'); - } - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } + await getSchedule().catch((error) => { + toast.error(error.message); + }); }; return ( diff --git a/interface/src/project/DashboardStatus.tsx b/interface/src/project/DashboardStatus.tsx index 9ef093b98..084c78820 100644 --- a/interface/src/project/DashboardStatus.tsx +++ b/interface/src/project/DashboardStatus.tsx @@ -170,15 +170,6 @@ const DashboardStatus: FC = () => { toast.error(err.message); }); setConfirmScan(false); - - // try { - // await EMSESP.scanDevices(); - // toast.info(LL.SCANNING() + '...'); - // } catch (error) { - // toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); - // } finally { - // setConfirmScan(false); - // } }; const renderScanDialog = () => ( diff --git a/interface/src/project/HelpInformation.tsx b/interface/src/project/HelpInformation.tsx index e849ac19e..b85720508 100644 --- a/interface/src/project/HelpInformation.tsx +++ b/interface/src/project/HelpInformation.tsx @@ -4,6 +4,7 @@ import DownloadIcon from '@mui/icons-material/GetApp'; import GitHubIcon from '@mui/icons-material/GitHub'; import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone'; import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAvatar } from '@mui/material'; +import { useRequest } from 'alova'; import { toast } from 'react-toastify'; import * as EMSESP from './api'; import type { FC } from 'react'; @@ -11,16 +12,19 @@ import type { FC } from 'react'; import { SectionContent } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; -import { extractErrorMessage } from 'utils'; const HelpInformation: FC = () => { const { LL } = useI18nContext(); - const saveFile = (json: any, endpoint: string) => { + const { send: API, onSuccess: onSuccessAPI } = useRequest((data) => EMSESP.API(data), { + immediate: false + }); + + onSuccessAPI((event) => { const a = document.createElement('a'); - const filename = 'emsesp_' + endpoint + '.txt'; + const filename = 'emsesp_info.txt'; a.href = URL.createObjectURL( - new Blob([JSON.stringify(json, null, 2)], { + new Blob([JSON.stringify(event.data, null, 2)], { type: 'text/plain' }) ); @@ -29,23 +33,12 @@ const HelpInformation: FC = () => { a.click(); document.body.removeChild(a); toast.info(LL.DOWNLOAD_SUCCESSFUL()); - }; + }); - const callAPI = async (endpoint: string) => { - try { - const response = await EMSESP.API({ - device: 'system', - entity: endpoint, - id: 0 - }); - if (response.status !== 200) { - toast.error(LL.PROBLEM_LOADING()); - } else { - saveFile(response.data, endpoint); - } - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } + const callAPI = async () => { + await API({ device: 'system', entity: 'info', id: 0 }).catch((error) => { + toast.error(error.message); + }); }; return ( @@ -96,7 +89,7 @@ const HelpInformation: FC = () => { size="small" variant="outlined" color="primary" - onClick={() => callAPI('info')} + onClick={() => callAPI()} > {LL.SUPPORT_INFO()} diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 24fa60ecc..7883cf484 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -61,7 +61,7 @@ const SettingsCustomization: FC = () => { immediate: false }); - const { data: devices } = useRequest(EMSESP.readDevices()); + const { data: devices } = useRequest(EMSESP.readDevices); const { send: writeCustomEntities } = useRequest((data) => EMSESP.writeCustomEntities(data), { immediate: false }); @@ -236,8 +236,9 @@ const SettingsCustomization: FC = () => { }; const maskDisabled = (set: boolean) => { + // TODO fix update! updateDeviceEntities( - deviceEntities?.map(function (de) { + deviceEntities.map(function (de) { if ((de.m & selectedFilters || !selectedFilters) && de.id.toLowerCase().includes(search.toLowerCase())) { return { ...de, @@ -329,7 +330,6 @@ const SettingsCustomization: FC = () => { } } ); - // does this work or use onSuccess hook? setOriginalSettings(deviceEntities); } }; diff --git a/interface/src/project/SettingsCustomizationDialog.tsx b/interface/src/project/SettingsCustomizationDialog.tsx index 065a2dd00..50601785d 100644 --- a/interface/src/project/SettingsCustomizationDialog.tsx +++ b/interface/src/project/SettingsCustomizationDialog.tsx @@ -124,7 +124,7 @@ const SettingsCustomizationDialog = ({ open, onClose, onSave, selectedItem }: Se {LL.CANCEL()} diff --git a/interface/src/project/SettingsScheduler.tsx b/interface/src/project/SettingsScheduler.tsx index 59fdee05b..8c93252e4 100644 --- a/interface/src/project/SettingsScheduler.tsx +++ b/interface/src/project/SettingsScheduler.tsx @@ -6,6 +6,7 @@ import WarningIcon from '@mui/icons-material/Warning'; import { Box, Typography, Divider, Stack, Button } from '@mui/material'; import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table'; import { useTheme } from '@table-library/react-table-library/theme'; +import { updateState, useRequest } from 'alova'; import { useState, useEffect, useCallback } from 'react'; import { unstable_useBlocker as useBlocker } from 'react-router-dom'; import { toast } from 'react-toastify'; @@ -19,23 +20,30 @@ import type { FC } from 'react'; import { ButtonRow, FormLoader, SectionContent, BlockNavigation } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; -import { extractErrorMessage } from 'utils'; const SettingsScheduler: FC = () => { const { LL, locale } = useI18nContext(); const [numChanges, setNumChanges] = useState(0); const blocker = useBlocker(numChanges !== 0); - const [schedule, setSchedule] = useState([]); const [selectedScheduleItem, setSelectedScheduleItem] = useState(); const [dow, setDow] = useState([]); - const [errorMessage, setErrorMessage] = useState(); const [creating, setCreating] = useState(false); const [dialogOpen, setDialogOpen] = useState(false); + const { + data: schedule, + send: fetchSchedule, + error + } = useRequest(EMSESP.readSchedule, { + initialData: [] + }); + + const { send: writeSchedule } = useRequest((data) => EMSESP.writeSchedule(data), { immediate: false }); + function hasScheduleChanged(si: ScheduleItem) { return ( si.id !== si.o_id || - (si?.name || '') !== (si?.o_name || '') || + (si.name || '') !== (si.o_name || '') || si.active !== si.o_active || si.deleted !== si.o_deleted || si.flags !== si.o_flags || @@ -46,10 +54,13 @@ const SettingsScheduler: FC = () => { } useEffect(() => { - if (schedule) { - setNumChanges(schedule ? schedule.filter((si) => hasScheduleChanged(si)).length : 0); - } - }, [schedule]); + const formatter = new Intl.DateTimeFormat(locale, { weekday: 'short', timeZone: 'UTC' }); + const days = [1, 2, 3, 4, 5, 6, 7].map((day) => { + const dd = day < 10 ? `0${day}` : day; + return new Date(`2017-01-${dd}T00:00:00+00:00`); + }); + setDow(days.map((date) => formatter.format(date))); + }, [locale]); const schedule_theme = useTheme({ Table: ` @@ -96,63 +107,30 @@ const SettingsScheduler: FC = () => { ` }); - const fetchSchedule = useCallback(async () => { - try { - const response = await EMSESP.readSchedule(); - setSchedule( - response.data.schedule.map((si) => ({ - ...si, - o_id: si.id, - o_active: si.active, - o_deleted: si.deleted, - o_flags: si.flags, - o_time: si.time, - o_cmd: si.cmd, - o_value: si.value, - o_name: si.name - })) - ); - } catch (error) { - setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } - }, [LL]); - - useEffect(() => { - const formatter = new Intl.DateTimeFormat(locale, { weekday: 'short', timeZone: 'UTC' }); - const days = [1, 2, 3, 4, 5, 6, 7].map((day) => { - const dd = day < 10 ? `0${day}` : day; - return new Date(`2017-01-${dd}T00:00:00+00:00`); - }); - setDow(days.map((date) => formatter.format(date))); - void fetchSchedule(); - }, [locale, fetchSchedule]); - const saveSchedule = async () => { - if (schedule) { - try { - const response = await EMSESP.writeSchedule({ - schedule: schedule - .filter((si) => !si.deleted) - .map((condensed_si) => ({ - id: condensed_si.id, - active: condensed_si.active, - flags: condensed_si.flags, - time: condensed_si.time, - cmd: condensed_si.cmd, - value: condensed_si.value, - name: condensed_si.name - })) - }); - if (response.status === 200) { - toast.success(LL.SCHEDULE_UPDATED()); - } else { - toast.error(LL.PROBLEM_UPDATING()); - } + await writeSchedule( + schedule + .filter((si) => !si.deleted) + .map((condensed_si) => ({ + id: condensed_si.id, + active: condensed_si.active, + flags: condensed_si.flags, + time: condensed_si.time, + cmd: condensed_si.cmd, + value: condensed_si.value, + name: condensed_si.name + })) + ) + .then(() => { + toast.success(LL.SCHEDULE_UPDATED()); + }) + .catch((err) => { + toast.error(err.message); + }) + .finally(async () => { await fetchSchedule(); - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); - } - } + setNumChanges(0); + }); }; const editScheduleItem = useCallback((si: ScheduleItem) => { @@ -167,11 +145,14 @@ const SettingsScheduler: FC = () => { const onDialogSave = (updatedItem: ScheduleItem) => { setDialogOpen(false); - if (schedule && creating) { - setSchedule([...schedule.filter((si) => creating || si.o_id !== updatedItem.o_id), updatedItem]); - } else { - setSchedule(schedule?.map((si) => (si.id === updatedItem.id ? { ...si, ...updatedItem } : si))); - } + + updateState('schedule', (data) => { + const new_data = creating + ? [...data.filter((si) => creating || si.o_id !== updatedItem.o_id), updatedItem] + : data.map((si) => (si.id === updatedItem.id ? { ...si, ...updatedItem } : si)); + setNumChanges(new_data.filter((si) => hasScheduleChanged(si)).length); + return new_data; + }); }; const addScheduleItem = () => { @@ -191,7 +172,7 @@ const SettingsScheduler: FC = () => { const renderSchedule = () => { if (!schedule) { - return ; + return ; } const dayBox = (si: ScheduleItem, flag: number) => ( diff --git a/interface/src/project/SettingsSchedulerDialog.tsx b/interface/src/project/SettingsSchedulerDialog.tsx index 49870a4d0..d074848a4 100644 --- a/interface/src/project/SettingsSchedulerDialog.tsx +++ b/interface/src/project/SettingsSchedulerDialog.tsx @@ -215,7 +215,7 @@ const SettingsSchedulerDialog = ({ /> alovaInstance.Get(`/coreData`); +export const readCoreData = () => alovaInstance.Get(`/rest/coreData`); export const readDeviceData = (id: number) => - alovaInstance.Get('/deviceData', { + alovaInstance.Get('/rest/deviceData', { params: { id }, responseType: 'arraybuffer' // uses msgpack }); -export const writeDeviceValue = (data: any) => alovaInstance.Post('/writeDeviceValue', data); +export const writeDeviceValue = (data: any) => alovaInstance.Post('/rest/writeDeviceValue', data); // SettingsApplication -export const readSettings = () => alovaInstance.Get('/settings'); -export const writeSettings = (data: any) => alovaInstance.Post('/settings', data); +export const readSettings = () => alovaInstance.Get('/rest/settings'); +export const writeSettings = (data: any) => alovaInstance.Post('/rest/settings', data); export const getBoardProfile = (boardProfile: string) => - alovaInstance.Get('/boardProfile', { + alovaInstance.Get('/rest/boardProfile', { params: { boardProfile } }); -export const restart = () => alovaInstance.Post('/restart'); +export const restart = () => alovaInstance.Post('/rest/restart'); // SettingsCustomization export const readDeviceEntities = (id: number) => - alovaInstance.Get('/deviceEntities', { + alovaInstance.Get('/rest/deviceEntities', { params: { id }, responseType: 'arraybuffer', - transformData(rawData: any) { - return rawData.map((de: DeviceEntity) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma })); + transformData(data: any) { + return data.map((de: DeviceEntity) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma })); } }); -export const readDevices = () => alovaInstance.Get('/devices'); -export const resetCustomizations = () => alovaInstance.Post('/resetCustomizations'); -export const writeCustomEntities = (data: any) => alovaInstance.Post('/customEntities', data); +export const readDevices = () => alovaInstance.Get('/rest/devices'); +export const resetCustomizations = () => alovaInstance.Post('/rest/resetCustomizations'); +export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customEntities', data); // DashboardSensors -export const readSensorData = () => alovaInstance.Get('/sensorData'); -export const writeTemperatureSensor = (ts: WriteTemperatureSensor) => alovaInstance.Post('/writeTemperatureSensor', ts); -export const writeAnalogSensor = (as: WriteAnalogSensor) => alovaInstance.Post('/writeAnalogSensor', as); - -// TODO think about naming, get... and not get etc... +export const readSensorData = () => alovaInstance.Get('/rest/sensorData'); +export const writeTemperatureSensor = (ts: WriteTemperatureSensor) => + alovaInstance.Post('/rest/writeTemperatureSensor', ts); +export const writeAnalogSensor = (as: WriteAnalogSensor) => alovaInstance.Post('/rest/writeAnalogSensor', as); // DashboardStatus -export const readStatus = () => alovaInstance.Get('/status'); -export const scanDevices = () => alovaInstance.Post('/scanDevices'); +export const readStatus = () => alovaInstance.Get('/rest/status'); +export const scanDevices = () => alovaInstance.Post('/rest/scanDevices'); -// ALOVA goes here.... +// HelpInformation +export const API = (apiCall: APIcall) => alovaInstance.Post('/api', apiCall); -export function API(apiCall: APIcall): AxiosPromise { - return AXIOS_API.post('/', apiCall); // command -} +// GeneralFileUpload +export const getSettings = () => alovaInstance.Get('/rest/getSettings'); +export const getCustomizations = () => alovaInstance.Get('/rest/getCustomizations'); +export const getEntities = () => alovaInstance.Get('/rest/getEntities'); +export const getSchedule = () => alovaInstance.Get('/rest/getSchedule'); -export function getSettings(): AxiosPromise { - return AXIOS.get('/getSettings'); -} - -export function getCustomizations(): AxiosPromise { - return AXIOS.get('/getCustomizations'); -} - -export function getSchedule(): AxiosPromise { - return AXIOS.get('/getSchedule'); -} - -export function readSchedule(): AxiosPromise { - return AXIOS.get('/schedule'); -} - -export function writeSchedule(schedule: Schedule): AxiosPromise { - return AXIOS.post('/schedule', schedule); -} - -export function getEntities(): AxiosPromise { - return AXIOS.get('/getEntities'); -} +// SettingsScheduler +export const readSchedule = () => + alovaInstance.Get('/rest/schedule', { + name: 'schedule', + transformData(data: any) { + return data.map((si: ScheduleItem) => ({ + ...si, + o_id: si.id, + o_active: si.active, + o_deleted: si.deleted, + o_flags: si.flags, + o_time: si.time, + o_cmd: si.cmd, + o_value: si.value, + o_name: si.name + })); + } + }); +export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule', data); +// SettingsCustomization +// TODO move last Entities* to Alova export function readEntities(): AxiosPromise { return AXIOS.get('/entities'); } - export function writeEntities(entities: Entities): AxiosPromise { return AXIOS.post('/entities', entities); } diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index a50b0281c..bdbbbd167 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -292,7 +292,7 @@ export interface ScheduleItem { time: string; cmd: string; value: string; - name?: string; // optional + name: string; // optional o_id?: number; o_active?: boolean; o_deleted?: boolean; @@ -303,10 +303,6 @@ export interface ScheduleItem { o_name?: string; } -export interface Schedule { - schedule: ScheduleItem[]; -} - export enum ScheduleFlag { SCHEDULE_SUN = 1, SCHEDULE_MON = 2, diff --git a/interface/src/project/validators.ts b/interface/src/project/validators.ts index 32b4f2505..bc7147a1d 100644 --- a/interface/src/project/validators.ts +++ b/interface/src/project/validators.ts @@ -90,6 +90,8 @@ export const schedulerItemValidation = () => new Schema({ name: [ { + // TODO name must be unique - add check + required: true, type: 'string', pattern: /^[a-zA-Z0-9_\\.]{0,15}$/, message: "Must be <15 characters: alpha numeric, '_' or '.'" diff --git a/interface/src/utils/useRest2.ts b/interface/src/utils/useRest2.ts index 7e8688da0..b71b1c9cf 100644 --- a/interface/src/utils/useRest2.ts +++ b/interface/src/utils/useRest2.ts @@ -3,15 +3,11 @@ import { useState } from 'react'; import { unstable_useBlocker as useBlocker } from 'react-router-dom'; import { toast } from 'react-toastify'; -import type { AlovaXHRRequestConfig, AlovaXHRResponse, AlovaXHRResponseHeaders } from '@alova/adapter-xhr'; - import { useI18nContext } from 'i18n/i18n-react'; export interface RestRequestOptions2 { - read: () => Method, AlovaXHRResponseHeaders>; - update: ( - value: D - ) => Method, AlovaXHRResponseHeaders>; + read: () => Method; + update: (value: D) => Method; } // TODO rename back to useRest diff --git a/interface/yarn.lock b/interface/yarn.lock index ca56b2b5d..6803c97b3 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1567,7 +1567,7 @@ __metadata: react-dom: latest react-dropzone: ^14.2.3 react-icons: ^4.9.0 - react-router-dom: ^6.12.1 + react-router-dom: ^6.13.0 react-toastify: ^9.1.3 rollup-plugin-visualizer: ^5.9.2 sockette: ^2.0.6 @@ -4807,27 +4807,27 @@ __metadata: languageName: node linkType: hard -"react-router-dom@npm:^6.12.1": - version: 6.12.1 - resolution: "react-router-dom@npm:6.12.1" +"react-router-dom@npm:^6.13.0": + version: 6.13.0 + resolution: "react-router-dom@npm:6.13.0" dependencies: "@remix-run/router": 1.6.3 - react-router: 6.12.1 + react-router: 6.13.0 peerDependencies: react: ">=16.8" react-dom: ">=16.8" - checksum: 4de0d4159a9dd2de0477d7608e9055262ebdd5dc41fc918b44b38170cc8ed407fa7dbb73bdb85e9469614502ad4772523b8a7f32c2609e62973feb41b70d871b + checksum: 760c57063e305b0623f7b39bca3c7f5c169af557867eac7d1b19419111f7b6a9ed95d2083305c40ce98fd3be27e82c61f5674c90dd066a67653cb15901d00991 languageName: node linkType: hard -"react-router@npm:6.12.1": - version: 6.12.1 - resolution: "react-router@npm:6.12.1" +"react-router@npm:6.13.0": + version: 6.13.0 + resolution: "react-router@npm:6.13.0" dependencies: "@remix-run/router": 1.6.3 peerDependencies: react: ">=16.8" - checksum: 33a39eca122f3519f1aa91d8e6585fab669b3b06b621aa624f7db1ffda6b84676facd57028652f2fba7325a208abef906a5ba6c91d55d5a5d29993583d82dd61 + checksum: c58b4b943d3a76d328c6ef299567a85d84a69b417f5f5d07596b0b9bd40632a828591d6f470b0f233ff9095f489f9fd5c8666fb03513e9470927447169a91d8a languageName: node linkType: hard diff --git a/mock-api/server.js b/mock-api/server.js index c805f7bc6..3b42ce97a 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -1798,8 +1798,9 @@ let emsesp_entities = { }; // SCHEDULE -let emsesp_schedule = { - schedule: [ +let emsesp_schedule = + // schedule: [ + [ { id: 1, active: true, @@ -1836,11 +1837,9 @@ let emsesp_schedule = { value: '', name: 'auto_restart' } - ] -}; + ]; // CUSTOMIZATIONS - const emsesp_deviceentities_1 = [{}]; const emsesp_deviceentities_3 = [{}]; const emsesp_deviceentities_5 = [{}]; @@ -2327,7 +2326,7 @@ rest_server.post(EMSESP_CUSTOM_ENTITIES_ENDPOINT, (req, res) => { rest_server.post(EMSESP_WRITE_SCHEDULE_ENDPOINT, (req, res) => { console.log('write schedule'); - console.log(req.body.schedule); + console.log(req.body); emsesp_schedule = req.body; res.sendStatus(200); }); @@ -2625,6 +2624,7 @@ rest_server.post(API_ENDPOINT_ROOT, (req, res) => { if (req.body.device === 'system') { if (req.body.entity === 'info') { console.log('sending system info: ' + JSON.stringify(emsesp_info)); + res.json(emsesp_info); } else if (req.body.entity === 'settings') { console.log('sending system settings: ' + JSON.stringify(settings)); res.json(settings); @@ -2652,25 +2652,37 @@ rest_server.get(SYSTEM_INFO_ENDPOINT, (req, res) => { const GET_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'getSettings'; rest_server.get(GET_SETTINGS_ENDPOINT, (req, res) => { - console.log('System Settings:'); + console.log('getSettings:'); res.json(settings); }); const GET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'getCustomizations'; rest_server.get(GET_CUSTOMIZATIONS_ENDPOINT, (req, res) => { - console.log('Customization'); + console.log('getCustomization'); // not implemented yet res.sendStatus(200); }); -const GET_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule'; +const GET_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'getEntities'; +rest_server.get(GET_ENTITIES_ENDPOINT, (req, res) => { + console.log('getEntities'); + res.json(emsesp_entities); +}); + +const GET_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'getSchedule'; rest_server.get(GET_SCHEDULE_ENDPOINT, (req, res) => { + console.log('getSchedule'); + res.json(emsesp_schedule); +}); + +const SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule'; +rest_server.get(SCHEDULE_ENDPOINT, (req, res) => { console.log('Sending Schedule data'); res.json(emsesp_schedule); }); -const GET_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'entities'; -rest_server.get(GET_ENTITIES_ENDPOINT, (req, res) => { +const ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'entities'; +rest_server.get(ENTITIES_ENDPOINT, (req, res) => { console.log('Sending Entities data'); res.json(emsesp_entities); });