diff --git a/frontend/src/components/layout/ProfileButton.js b/frontend/src/components/layout/ProfileButton.js
index 5843a57..5e92221 100644
--- a/frontend/src/components/layout/ProfileButton.js
+++ b/frontend/src/components/layout/ProfileButton.js
@@ -6,17 +6,16 @@ import AccountBoxIcon from "@mui/icons-material/AccountBox";
import SettingsIcon from "@mui/icons-material/Settings";
import { useNavigate } from "react-router-dom";
import { useTuitioClient } from "@flare/tuitio-client-react";
-import { useToast } from "../../hooks";
+import { blip } from "../../utils";
import { useTranslation } from "react-i18next";
const ProfileButton = () => {
const navigate = useNavigate();
- const { error } = useToast();
const { t } = useTranslation();
const { logout } = useTuitioClient({
- onLogoutFailed: errorMessage => error(errorMessage),
- onLogoutError: err => error(err.message)
+ onLogoutFailed: errorMessage => blip.error(errorMessage),
+ onLogoutError: err => blip.error(err.message)
});
const [anchorEl, setAnchorEl] = useState(null);
diff --git a/frontend/src/features/about/system/SystemVersionContainer.js b/frontend/src/features/about/system/SystemVersionContainer.js
deleted file mode 100644
index c4731fa..0000000
--- a/frontend/src/features/about/system/SystemVersionContainer.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React, { useState, useEffect } from "react";
-import SystemVersionComponent from "./SystemVersionComponent";
-import { routes, get } from "../../../utils/api";
-
-const SystemVersionContainer = () => {
- const [state, setState] = useState({ data: {}, loaded: false });
-
- useEffect(() => {
- if (state.loaded) return;
- get(routes.systemVersion, {
- onCompleted: data => setState({ data, loaded: true })
- });
- }, [state.loaded]);
-
- return <>{state.loaded && }>;
-};
-
-export default SystemVersionContainer;
diff --git a/frontend/src/features/about/system/SystemVersionContainer.tsx b/frontend/src/features/about/system/SystemVersionContainer.tsx
new file mode 100644
index 0000000..46aaa75
--- /dev/null
+++ b/frontend/src/features/about/system/SystemVersionContainer.tsx
@@ -0,0 +1,26 @@
+import React, { useState, useEffect } from "react";
+import SystemVersionComponent from "./SystemVersionComponent";
+import { routes, get, endpoints } from "../../../utils/api";
+import useSWR from "swr";
+import { fetcher } from "utils/swr";
+import { blip } from "utils";
+
+const SystemVersionContainer: React.FC = () => {
+ const { data: namespaces } = useSWR(endpoints.system.version, fetcher, {
+ revalidateOnFocus: false,
+ onError: err => blip.error(err.message)
+ });
+
+ const [state, setState] = useState({ data: {}, loaded: false });
+
+ useEffect(() => {
+ if (state.loaded) return;
+ get(routes.systemVersion, {
+ onCompleted: (data: any) => setState({ data, loaded: true })
+ });
+ }, [state.loaded]);
+
+ return <>{state.loaded && }>;
+};
+
+export default SystemVersionContainer;
diff --git a/frontend/src/features/login/components/LoginContainer.js b/frontend/src/features/login/components/LoginContainer.js
index c3f23af..150790d 100644
--- a/frontend/src/features/login/components/LoginContainer.js
+++ b/frontend/src/features/login/components/LoginContainer.js
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import LoginCard from "./LoginCard";
-import { useToast } from "../../../hooks";
+import { blip } from "../../../utils";
import { useTranslation } from "react-i18next";
import { useTuitioClient } from "@flare/tuitio-client-react";
@@ -10,11 +10,10 @@ const LoginContainer = () => {
password: ""
});
- const { error } = useToast();
const { t } = useTranslation();
const { login } = useTuitioClient({
- onLoginFailed: () => error(t("Login.IncorrectCredentials")),
- onLoginError: err => error(err.message)
+ onLoginFailed: () => blip.error(t("Login.IncorrectCredentials")),
+ onLoginError: err => blip.error(err.message)
});
const handleChange = prop => event => {
diff --git a/frontend/src/features/machines/components/MachineContainer.js b/frontend/src/features/machines/components/MachineContainer.js
index e1a3236..54fcf4e 100644
--- a/frontend/src/features/machines/components/MachineContainer.js
+++ b/frontend/src/features/machines/components/MachineContainer.js
@@ -3,15 +3,13 @@ import PropTypes from "prop-types";
import MachineTableRow from "./MachineTableRow";
import MachineAccordion from "./MachineAccordion";
import { ViewModes } from "./ViewModeSelection";
-import { useToast } from "../../../hooks";
+import { blip } from "../../../utils";
import { LastPage, RotateLeft, Launch, Stop } from "@mui/icons-material";
import { useTranslation } from "react-i18next";
import { routes, post } from "../../../utils/api";
const MachineContainer = ({ machine, viewMode }) => {
const [logs, setLogs] = useState([]);
-
- const { success, error } = useToast();
const { t } = useTranslation();
const addLog = useCallback(
@@ -25,12 +23,12 @@ const MachineContainer = ({ machine, viewMode }) => {
response => {
addLog(`Success: ${response.success}. Status: ${response.status}`);
if (response.success) {
- success(response.status);
+ blip.success(response.status);
} else {
- error(response.status);
+ blip.error(response.status);
}
},
- [error, success, addLog]
+ [addLog]
);
const pingMachine = useCallback(
diff --git a/frontend/src/features/machines/components/common/WakeComponent.js b/frontend/src/features/machines/components/common/WakeComponent.js
index 6f7b0bc..69a9d6b 100644
--- a/frontend/src/features/machines/components/common/WakeComponent.js
+++ b/frontend/src/features/machines/components/common/WakeComponent.js
@@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import { IconButton, Tooltip } from "@mui/material";
import { PowerSettingsNew } from "@mui/icons-material";
import { useTranslation } from "react-i18next";
-import { useToast } from "../../../../hooks";
+import { blip } from "../../../../utils";
import { msToMinAndSec } from "../../../../utils/time";
import { routes, post } from "../../../../utils/api";
@@ -16,7 +16,6 @@ const WakeComponent = ({ machine, addLog, disabled }) => {
const [trigger, setTrigger] = useState(false);
const { t } = useTranslation();
- const { success, error } = useToast();
const pingInterval = process.env.REACT_APP_MACHINE_PING_INTERVAL || defaultPingInterval;
const startingTime = process.env.REACT_APP_MACHINE_STARTING_TIME || defaultStartingTime;
@@ -40,7 +39,7 @@ const WakeComponent = ({ machine, addLog, disabled }) => {
setState(prev => ({ ...prev, on: result.success }));
log(`[Wake]: Success: ${result.success}. Status: ${result.status}`);
if (result.success) {
- success(result.status);
+ blip.success(result.status);
//retrigger
log(`Periodic ping will be re-triggered in ${startingTime} ms [${msToMinAndSec(startingTime)}]`);
@@ -48,12 +47,12 @@ const WakeComponent = ({ machine, addLog, disabled }) => {
setTrigger(prev => !prev);
}, startingTime);
} else {
- error(result.status);
+ blip.error(result.status);
}
}
}
);
- }, [log, success, error, startingTime, machine.machineId]);
+ }, [log, startingTime, machine.machineId]);
const pingInLoop = useCallback(async () => {
if (disabled) return;
diff --git a/frontend/src/features/settings/system/CacheSettingsContainer.js b/frontend/src/features/settings/system/CacheSettingsContainer.js
index 4283fcd..3e94592 100644
--- a/frontend/src/features/settings/system/CacheSettingsContainer.js
+++ b/frontend/src/features/settings/system/CacheSettingsContainer.js
@@ -2,7 +2,7 @@ import React, { useCallback } from "react";
import CacheSettingsComponent from "./CacheSettingsComponent";
import { useTranslation } from "react-i18next";
import { routes, post } from "utils/api";
-import { info } from "utils/toast";
+import { blip } from "utils";
const CacheSettingsContainer = () => {
const { t } = useTranslation();
@@ -11,7 +11,7 @@ const CacheSettingsContainer = () => {
routes.resetCache,
{},
{
- onCompleted: () => info(t("Settings.Cache.ResetInfo"))
+ onCompleted: () => blip.info(t("Settings.Cache.ResetInfo"))
}
);
}, [t]);
diff --git a/frontend/src/hooks/index.js b/frontend/src/hooks/index.js
index 44ec796..f28fc19 100644
--- a/frontend/src/hooks/index.js
+++ b/frontend/src/hooks/index.js
@@ -1,6 +1,5 @@
-import { useToast } from "./useToast";
import { useSensitiveInfo } from "../providers/SensitiveInfoProvider";
import { usePermissions } from "../providers/UserPermissionsProvider";
import { useClipboard } from "./useClipboard";
-export { useToast, useSensitiveInfo, usePermissions, useClipboard };
+export { useSensitiveInfo, usePermissions, useClipboard };
diff --git a/frontend/src/hooks/useClipboard.js b/frontend/src/hooks/useClipboard.js
index b2fd329..956f5e2 100644
--- a/frontend/src/hooks/useClipboard.js
+++ b/frontend/src/hooks/useClipboard.js
@@ -1,16 +1,15 @@
import { useCallback } from "react";
import { useTranslation } from "react-i18next";
-import { useToast } from "./useToast";
+import { blip } from "../utils";
const useClipboard = () => {
const { t } = useTranslation();
- const { info } = useToast();
const copy = useCallback(
url => () => {
navigator.clipboard.writeText(url);
- info(t("Generic.CopiedToClipboard"));
+ blip.info(t("Generic.CopiedToClipboard"));
},
- [info, t]
+ [t]
);
return { copy };
};
diff --git a/frontend/src/hooks/useToast.js b/frontend/src/hooks/useToast.js
deleted file mode 100644
index 2255151..0000000
--- a/frontend/src/hooks/useToast.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { info, success, warning, error, dark } from "utils/toast";
-
-export const useToast = () => {
- return { info, success, warning, error, dark };
-};
diff --git a/frontend/src/utils/api.js b/frontend/src/utils/api.js
index 08dd64b..6b9e85f 100644
--- a/frontend/src/utils/api.js
+++ b/frontend/src/utils/api.js
@@ -2,10 +2,12 @@ import * as axios from "../utils/axios";
import { toast } from "react-toastify";
import env from "../utils/env";
-const networkRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/network`;
-const systemRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/system`;
-const powerActionsRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/resurrector`;
-const securityRoute = `${env.REACT_APP_NETWORK_RESURRECTOR_API_URL}/security`;
+const apiHost = env.REACT_APP_NETWORK_RESURRECTOR_API_URL;
+
+const networkRoute = `${apiHost}/network`;
+const systemRoute = `${apiHost}/system`;
+const powerActionsRoute = `${apiHost}/resurrector`;
+const securityRoute = `${apiHost}/security`;
const routes = {
permissions: `${securityRoute}/permissions`,
@@ -16,7 +18,12 @@ const routes = {
wakeMachine: `${powerActionsRoute}/wake`,
pingMachine: `${powerActionsRoute}/ping`,
shutdownMachine: `${powerActionsRoute}/shutdown`,
- restartMachine: `${powerActionsRoute}/restart`
+ restartMachine: `${powerActionsRoute}/restart`,
+ system: {
+ version: `${systemRoute}/version`,
+ releaseNotes: `${systemRoute}/release-notes`,
+ resetCache: `${systemRoute}/reset-cache`
+ }
};
const handleError = err => {
@@ -64,4 +71,6 @@ const post = (route, data, options) => {
return promise;
};
-export { routes, get, post };
+const endpoints = routes;
+
+export { routes, get, post, endpoints };
diff --git a/frontend/src/utils/toast.js b/frontend/src/utils/blip.js
similarity index 75%
rename from frontend/src/utils/toast.js
rename to frontend/src/utils/blip.js
index 4045135..82c7f0e 100644
--- a/frontend/src/utils/toast.js
+++ b/frontend/src/utils/blip.js
@@ -6,4 +6,6 @@ const warning = message => toast.warning(message);
const error = message => toast.error(message);
const dark = message => toast.dark(message);
-export { info, success, warning, error, dark };
+const blip = { info, success, warning, error, dark };
+export { blip };
+export default blip;
diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js
deleted file mode 100644
index 0dbd747..0000000
--- a/frontend/src/utils/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import { getRandomElement } from "./random";
-
-export { getRandomElement };
diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts
new file mode 100644
index 0000000..2115555
--- /dev/null
+++ b/frontend/src/utils/index.ts
@@ -0,0 +1,4 @@
+import { getRandomElement } from "./random";
+import blip from "./blip";
+
+export { getRandomElement, blip };
diff --git a/frontend/src/utils/swr.ts b/frontend/src/utils/swr.ts
new file mode 100644
index 0000000..2c718f3
--- /dev/null
+++ b/frontend/src/utils/swr.ts
@@ -0,0 +1,40 @@
+import i18next from "i18next";
+import { acquire as fetchTuitioData } from "@flare/tuitio-client";
+
+const getHeaders = (): HeadersInit => {
+ const { token } = fetchTuitioData();
+ const language = i18next.language;
+
+ const headers: HeadersInit = {
+ "Content-Type": "application/json"
+ };
+
+ if (token) {
+ headers.Authorization = `Tuitio ${token}`;
+ }
+
+ if (language) {
+ headers["Accept-Language"] = language;
+ }
+
+ return headers;
+};
+
+const fetcher = (url: string) => fetch(url, { method: "GET", headers: getHeaders() }).then(res => res.json());
+
+async function mutationFetcher(url: string, { arg }: { arg: Command }) {
+ return fetch(url, {
+ method: "POST",
+ headers: getHeaders(),
+ body: JSON.stringify(arg)
+ }).then(res => res.json());
+}
+
+// async function deleteFetcher(url: string, { arg }: { arg: Command }) {
+// return fetch(combine(url, arg as number), {
+// method: "DELETE",
+// headers: getHeaders()
+// }).then(res => res.json());
+// }
+
+export { fetcher, mutationFetcher };