diff --git a/pwa/src/apiService/apiService.ts b/pwa/src/apiService/apiService.ts index b035aab1..3dde8d6b 100644 --- a/pwa/src/apiService/apiService.ts +++ b/pwa/src/apiService/apiService.ts @@ -32,6 +32,7 @@ import Upload from "./resources/upload"; interface PromiseMessage { loading?: string; success?: string; + error?: string; } export type TSendFunction = ( @@ -255,37 +256,35 @@ export default class APIService { switch (action) { case "GET": const response = instance.get(endpoint); - - response.catch((err) => toast.error(err.message)); - + response.catch((err) => toast.error(promiseMessage?.error ?? err.message)); return response; case "POST": return toast.promise(instance.post(endpoint, _payload), { loading: promiseMessage?.loading ?? "Creating item...", success: promiseMessage?.success ?? "Succesfully created item", - error: (err) => err.message, + error: (err) => promiseMessage?.error ?? err.message, }); case "PUT": return toast.promise(instance.put(endpoint, _payload), { loading: promiseMessage?.loading ?? "Updating item...", success: promiseMessage?.success ?? "Succesfully updated item", - error: (err) => err.message, + error: (err) => promiseMessage?.error ?? err.message, }); case "DELETE": return toast.promise(instance.delete(endpoint), { loading: promiseMessage?.loading ?? "Deleting item...", success: promiseMessage?.success ?? "Succesfully deleted item", - error: (err) => err.message, + error: (err) => promiseMessage?.error ?? err.message, }); case "DOWNLOAD": return toast.promise(instance.get(endpoint), { loading: promiseMessage?.loading ?? "Downloading item...", success: promiseMessage?.success ?? "Succesfully downloaded item", - error: (err) => err.message, + error: (err) => promiseMessage?.error ?? err.message, }); } }; diff --git a/pwa/src/apiService/resources/dashboardCards.tsx b/pwa/src/apiService/resources/dashboardCards.tsx index 7e3b866a..b9d4975e 100644 --- a/pwa/src/apiService/resources/dashboardCards.tsx +++ b/pwa/src/apiService/resources/dashboardCards.tsx @@ -25,7 +25,9 @@ export default class DashboardCards { } public getAll = async (): Promise => { - const { data } = await this._send(this._instance, "GET", "/admin/dashboardCards"); + const { data } = await this._send(this._instance, "GET", "/admin/dashboardCards", undefined, { + error: "Could not fetch Dashboardcards.", + }); return data; }; diff --git a/pwa/src/apiService/resources/source.ts b/pwa/src/apiService/resources/source.ts index dfdaadb0..82877ff0 100644 --- a/pwa/src/apiService/resources/source.ts +++ b/pwa/src/apiService/resources/source.ts @@ -16,6 +16,12 @@ export default class Source { return data; }; + public getAllSelectOptions = async (): Promise => { + const { data } = await this._send(this._instance, "GET", "/admin/gateways?limit=200"); + + return data?.map((source: any) => ({ label: source.name, value: source.id })); + }; + public getOne = async (id: string): Promise => { const { data } = await this._send(this._instance, "GET", `/admin/gateways/${id}`); diff --git a/pwa/src/context/logs.ts b/pwa/src/context/logs.ts index 74125129..f3f234b1 100644 --- a/pwa/src/context/logs.ts +++ b/pwa/src/context/logs.ts @@ -13,6 +13,7 @@ export interface ILogFiltersContext { process?: string; endpoint?: string; schema?: string; + source?: string; cronjob?: string; action?: string; user?: string; diff --git a/pwa/src/context/tableColumns.ts b/pwa/src/context/tableColumns.ts index 3d5361b7..e55b307a 100644 --- a/pwa/src/context/tableColumns.ts +++ b/pwa/src/context/tableColumns.ts @@ -21,6 +21,7 @@ const logColumns = { created: true, endpoint: true, schema: true, + source: true, cronjob: true, action: true, user: true, diff --git a/pwa/src/hooks/dashboardCards.ts b/pwa/src/hooks/dashboardCards.ts index 20f79d0e..9b321a5f 100644 --- a/pwa/src/hooks/dashboardCards.ts +++ b/pwa/src/hooks/dashboardCards.ts @@ -13,6 +13,7 @@ export const useDashboardCards = (queryClient: QueryClient) => { onError: (error) => { console.warn(error.message); }, + retry: 0, }); const getOne = (dashboardCardsId: string) => diff --git a/pwa/src/hooks/source.ts b/pwa/src/hooks/source.ts index f809615c..b0dfff2d 100644 --- a/pwa/src/hooks/source.ts +++ b/pwa/src/hooks/source.ts @@ -18,6 +18,13 @@ export const useSource = (queryClient: QueryClient) => { }, }); + const getAllSelectOptions = () => + useQuery("source_select_options", API.Sources.getAllSelectOptions, { + onError: (error) => { + console.warn(error.message); + }, + }); + const getOne = (sourceId: string) => useQuery(["sources", sourceId], () => API?.Sources.getOne(sourceId), { initialData: () => queryClient.getQueryData("sources")?.find((_sources) => _sources.id === sourceId), @@ -78,5 +85,5 @@ export const useSource = (queryClient: QueryClient) => { }, }); - return { getAll, getOne, remove, createOrEdit, getProxy }; + return { getAll, getOne, remove, createOrEdit, getProxy, getAllSelectOptions }; }; diff --git a/pwa/src/templates/gatewayDetailTemplate/GatewayDetailTemplate.tsx b/pwa/src/templates/gatewayDetailTemplate/GatewayDetailTemplate.tsx index 88b79bde..43c6f468 100644 --- a/pwa/src/templates/gatewayDetailTemplate/GatewayDetailTemplate.tsx +++ b/pwa/src/templates/gatewayDetailTemplate/GatewayDetailTemplate.tsx @@ -70,7 +70,9 @@ export const GatewayDetailTemplate: React.FC = () => { getPlugins.data.update ? getPlugins.data?.version : `Latest (${getPlugins.data?.version})` } `}

)} -

{`last update time: ${new Date(getPlugins.data?.time).toLocaleString()}`}

+

{`last update time: ${new Date( + getPlugins.data?.versions[getPlugins.data?.version].time, + ).toLocaleString()}`}

diff --git a/pwa/src/templates/logsDetailTemplate/LogsDetailTemplate.tsx b/pwa/src/templates/logsDetailTemplate/LogsDetailTemplate.tsx index 14feb4fb..2d7e6267 100644 --- a/pwa/src/templates/logsDetailTemplate/LogsDetailTemplate.tsx +++ b/pwa/src/templates/logsDetailTemplate/LogsDetailTemplate.tsx @@ -23,6 +23,8 @@ import { Button } from "../../components/button/Button"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useMapping } from "../../hooks/mapping"; import { useObject } from "../../hooks/object"; +import { CodeEditor } from "../../components/codeEditor/CodeEditor"; +import { useSource } from "../../hooks/source"; interface LogsDetailTemplateProps { logId: string; @@ -31,6 +33,10 @@ interface LogsDetailTemplateProps { export const LogsDetailTemplate: React.FC = ({ logId }) => { const { t } = useTranslation(); const { setLogFilters } = useLogFiltersContext(); + const [bodyData, setBodyData] = React.useState(""); + const [exceptionData, setExceptionData] = React.useState(""); + const [routeParametersData, setRouteParametersData] = React.useState(""); + const [sourceCallData, setSourceCallData] = React.useState(""); const queryClient = useQueryClient(); @@ -44,6 +50,7 @@ export const LogsDetailTemplate: React.FC = ({ logId }) const getOrganization = useOrganization(queryClient).getOne(getLog.data?.context?.organization); const getMapping = useMapping(queryClient).getOne(getLog.data?.context?.mapping); const getObject = useObject().getOne(getLog.data?.context?.object); + const getSource = useSource(queryClient).getOne(getLog.data?.context?.source); const handleSetContextFilter = ( context: @@ -51,6 +58,7 @@ export const LogsDetailTemplate: React.FC = ({ logId }) | "process" | "endpoint" | "schema" + | "source" | "cronjob" | "action" | "user" @@ -70,6 +78,13 @@ export const LogsDetailTemplate: React.FC = ({ logId }) navigate("/logs"); }; + React.useEffect(() => { + setBodyData(JSON.stringify(getLog.data?.context?.body, null, 2)); + setExceptionData(JSON.stringify(getLog.data?.context?.exception, null, 2)); + setRouteParametersData(JSON.stringify(getLog.data?.context?.route_parameters, null, 2)); + setSourceCallData(JSON.stringify(getLog.data?.context?.sourceCall, null, 2)); + }, [getLog]); + return ( {t("Logs detail page")} @@ -99,22 +114,120 @@ export const LogsDetailTemplate: React.FC = ({ logId }) - - Host - {getLog.data.context?.host !== "" ? getLog.data.context?.host : "-"} - - - - - - - IP - {getLog.data.context?.ip !== "" ? getLog.data.context?.ip : "-"} - - - - - + {getLog.data.context?.exception && ( + + Exception + + + + + )} + {getLog.data.context?.method && ( + + Method + {getLog.data.context?.method !== "" ? getLog.data.context?.method : "-"} + - + - + + )} + {getLog.data.context?.querystring && ( + + Querystring + + {getLog.data.context?.querystring !== "" ? getLog.data.context?.querystring : "-"} + + - + - + + )} + {getLog.data.context?.pathRaw && ( + + pathRaw + {getLog.data.context?.pathRaw !== "" ? getLog.data.context?.pathRaw : "-"} + - + - + + )} + {getLog.data.context?.request_uri && ( + + Request URI + + {getLog.data.context?.request_uri !== "" ? getLog.data.context?.request_uri : "-"} + + - + - + + )} + {getLog.data.context?.route && ( + + Route + {getLog.data.context?.route !== "" ? getLog.data.context?.route : "-"} + - + - + + )} + {getLog.data.context?.route_parameters && ( + + Route Parameters + + + + + )} + {getLog.data.context?.contentType && ( + + Content Type + + {getLog.data.context?.contentType !== "" ? getLog.data.context?.contentType : "-"} + + - + - + + )} + {getLog.data.context?.body && ( + + Body + + + + + )} + {getLog.data.context?.crude_body && ( + + Crude Body + {getLog.data.context?.crude_body} + + )} + {getLog.data.context?.mongoDBFilter && ( + + MongoDB Filter + {getLog.data.context?.mongoDBFilter} + + )} + {getLog.data.context?.plugin && ( + + Plugin + {getLog.data.context?.plugin !== "" ? getLog.data.context?.plugin : "-"} + - + - + + )} + {getLog.data.context?.sourceCall && ( + + Source Call + + + + + )} Session {getLog.data.context?.session !== "" ? getLog.data.context?.session : "-"} -
diff --git a/pwa/src/templates/templateParts/actionsForm/ActionFormTemplate.tsx b/pwa/src/templates/templateParts/actionsForm/ActionFormTemplate.tsx index 3fe5167e..af1d3315 100644 --- a/pwa/src/templates/templateParts/actionsForm/ActionFormTemplate.tsx +++ b/pwa/src/templates/templateParts/actionsForm/ActionFormTemplate.tsx @@ -275,46 +275,50 @@ export const ActionFormTemplate: React.FC = ({ action } - -
- - - {t("Date Created")} -
{translateDate(i18n.language, action.dateCreated) ?? "-"}
-
-
- - - - {t("Date Modified")} -
{translateDate(i18n.language, action.dateModified) ?? "-"}
-
-
- - - - {t("Last run")} -
{action.lastRun ? formatDateTime(t(i18n.language), action.lastRun) : "-"}
-
-
- - - - {t("Last run time")} -
{`${action.lastRunTime}s` ?? "-"}
-
-
- - - - {t("Status")} - - - -
+ {action && ( + <> + +
+ + + {t("Date Created")} +
{translateDate(i18n.language, action.dateCreated) ?? "-"}
+
+
+ + + + {t("Date Modified")} +
{translateDate(i18n.language, action.dateModified) ?? "-"}
+
+
+ + + + {t("Last run")} +
{action.lastRun ? formatDateTime(t(i18n.language), action.lastRun) : "-"}
+
+
+ + + + {t("Last run time")} +
{`${action.lastRunTime}s` ?? "-"}
+
+
+ + + + {t("Status")} + + + +
+ + )} diff --git a/pwa/src/templates/templateParts/logFilters/LogFiltersTemplate.tsx b/pwa/src/templates/templateParts/logFilters/LogFiltersTemplate.tsx index dcb4cdee..807dcb09 100644 --- a/pwa/src/templates/templateParts/logFilters/LogFiltersTemplate.tsx +++ b/pwa/src/templates/templateParts/logFilters/LogFiltersTemplate.tsx @@ -9,6 +9,7 @@ import { useUser } from "../../../hooks/user"; import { useSchema } from "../../../hooks/schema"; import { useAction } from "../../../hooks/action"; import { useObject } from "../../../hooks/object"; +import { useSource } from "../../../hooks/source"; import { useMapping } from "../../../hooks/mapping"; import { useCronjob } from "../../../hooks/cronjob"; import { useEndpoint } from "../../../hooks/endpoint"; @@ -33,6 +34,7 @@ export const LogFiltersTemplate: React.FC = ({ layoutCl const getEndpoints = useEndpoint(queryClient).getAllSelectOptions(); const getSchemas = useSchema(queryClient).getAllSelectOptions(); + const getSources = useSource(queryClient).getAllSelectOptions(); const getCronjobs = useCronjob(queryClient).getAllSelectOptions(); const getActions = useAction(queryClient).getAllSelectOptions(); const getUsers = useUser(queryClient).getAllSelectOptions(); @@ -72,6 +74,7 @@ export const LogFiltersTemplate: React.FC = ({ layoutCl process: formValues.process, endpoint: formValues.endpoints?.value, schema: formValues.schemas?.value, + source: formValues.sources?.value, cronjob: formValues.cronjobs?.value, action: formValues.actions?.value, user: formValues.users?.value, @@ -114,6 +117,11 @@ export const LogFiltersTemplate: React.FC = ({ layoutCl getSchemas.data?.find((schema) => schema.value === logFilters.context?.schema), ); + setValue( + "sources", + getSources.data?.find((source) => source.value === logFilters.context?.source), + ); + setValue( "cronjobs", getCronjobs.data?.find((cronjob) => cronjob.value === logFilters.context?.cronjob), @@ -229,6 +237,18 @@ export const LogFiltersTemplate: React.FC = ({ layoutCl + + + Sources + + {getSources.isSuccess && ( + + )} + + {getSources.isLoading && } + + + Cronjobs @@ -322,7 +342,6 @@ export const LogFiltersTemplate: React.FC = ({ layoutCl {getMappings.isLoading && } -
diff --git a/pwa/src/templates/templateParts/logsTable/LogsTableTemplate.tsx b/pwa/src/templates/templateParts/logsTable/LogsTableTemplate.tsx index 7164f965..5beb5569 100644 --- a/pwa/src/templates/templateParts/logsTable/LogsTableTemplate.tsx +++ b/pwa/src/templates/templateParts/logsTable/LogsTableTemplate.tsx @@ -78,6 +78,7 @@ export const LogsTableTemplate: React.FC = ({ logs, pagi {logColumns.created && {t("Created")}} {logColumns.endpoint && {t("Endpoint")}} {logColumns.schema && {t("Schema")}} + {logColumns.source && {t("Source")}} {logColumns.cronjob && {t("Cronjob")}} {logColumns.action && {t("Action")}} {logColumns.user && {t("User")}} @@ -144,6 +145,19 @@ export const LogsTableTemplate: React.FC = ({ logs, pagi )} + {logColumns.source && ( + +