diff --git a/portal-ui/src/screens/Console/Configurations/types.ts b/portal-ui/src/screens/Console/Configurations/types.ts
index 2214a37d0..3abc113b4 100644
--- a/portal-ui/src/screens/Console/Configurations/types.ts
+++ b/portal-ui/src/screens/Console/Configurations/types.ts
@@ -54,6 +54,11 @@ export interface IElementValue {
value: string;
}
+export interface IConfigurationSys {
+ name?: string;
+ key_values: IElementValue[];
+}
+
export interface IElement {
configuration_id: string;
configuration_label: string;
diff --git a/portal-ui/src/screens/Console/NotificationEndpoints/CustomForms/EditConfiguration.tsx b/portal-ui/src/screens/Console/NotificationEndpoints/CustomForms/EditConfiguration.tsx
index ba2fc1997..acee4aaa6 100644
--- a/portal-ui/src/screens/Console/NotificationEndpoints/CustomForms/EditConfiguration.tsx
+++ b/portal-ui/src/screens/Console/NotificationEndpoints/CustomForms/EditConfiguration.tsx
@@ -15,7 +15,7 @@
// along with this program. If not, see .
import React, { Fragment, useCallback, useEffect, useState } from "react";
-import { Button } from "mds";
+import { Button, Loader } from "mds";
import { useLocation, useNavigate } from "react-router-dom";
import get from "lodash/get";
import { Theme } from "@mui/material/styles";
@@ -36,18 +36,20 @@ import {
} from "../../Configurations/utils";
import {
IConfigurationElement,
+ IConfigurationSys,
IElementValue,
} from "../../Configurations/types";
import { ErrorResponseHandler } from "../../../../common/types";
import ResetConfigurationModal from "./ResetConfigurationModal";
import {
+ configurationIsLoading,
setErrorSnackMessage,
setServerNeedsRestart,
setSnackBarMessage,
} from "../../../../systemSlice";
-import { useAppDispatch } from "../../../../store";
-import { Loader } from "mds";
-import EndpointDisplay from "./EndpointDisplay";
+import { AppState, useAppDispatch } from "../../../../store";
+import WebhookSettings from "../WebhookSettings/WebhookSettings";
+import { useSelector } from "react-redux";
const styles = (theme: Theme) =>
createStyles({
@@ -81,15 +83,20 @@ const EditConfiguration = ({
//Local States
const [valuesObj, setValueObj] = useState([]);
const [saving, setSaving] = useState(false);
- const [loadingConfig, setLoadingConfig] = useState(true);
const [configValues, setConfigValues] = useState([]);
- const [configSubsysList, setConfigSubsysList] = useState([]);
+ const [configSubsysList, setConfigSubsysList] = useState(
+ []
+ );
const [resetConfigurationOpen, setResetConfigurationOpen] =
useState(false);
+ const loadingConfig = useSelector(
+ (state: AppState) => state.system.loadingConfigurations
+ );
+
useEffect(() => {
- setLoadingConfig(true);
- }, [selConfigTab]);
+ dispatch(configurationIsLoading(true));
+ }, [selConfigTab, dispatch]);
useEffect(() => {
if (loadingConfig) {
@@ -102,16 +109,16 @@ const EditConfiguration = ({
setConfigSubsysList(res);
const keyVals = get(res[0], "key_values", []);
setConfigValues(keyVals);
- setLoadingConfig(false);
+ dispatch(configurationIsLoading(false));
})
.catch((err: ErrorResponseHandler) => {
- setLoadingConfig(false);
+ dispatch(configurationIsLoading(false));
dispatch(setErrorSnackMessage(err));
});
return;
}
- setLoadingConfig(false);
+ dispatch(configurationIsLoading(false));
}
}, [loadingConfig, selectedConfiguration, dispatch]);
@@ -129,6 +136,7 @@ const EditConfiguration = ({
.then((res) => {
setSaving(false);
dispatch(setServerNeedsRestart(res.restart));
+ dispatch(configurationIsLoading(true));
if (!res.restart) {
dispatch(setSnackBarMessage("Configuration saved successfully"));
}
@@ -157,10 +165,14 @@ const EditConfiguration = ({
setResetConfigurationOpen(false);
dispatch(setServerNeedsRestart(restart));
if (restart) {
- setLoadingConfig(true);
+ dispatch(configurationIsLoading(true));
}
};
+ const resetConfigurationMOpen = () => {
+ setResetConfigurationOpen(true);
+ };
+
return (
{resetConfigurationOpen && (
@@ -181,62 +193,66 @@ const EditConfiguration = ({
height: "100%",
}}
>
-
+ >
+
+
+
+
+
+
+
+
+
+
+ )}
)}
diff --git a/portal-ui/src/screens/Console/NotificationEndpoints/CustomForms/EndpointDisplay.tsx b/portal-ui/src/screens/Console/NotificationEndpoints/CustomForms/EndpointDisplay.tsx
deleted file mode 100644
index 0c18eb05f..000000000
--- a/portal-ui/src/screens/Console/NotificationEndpoints/CustomForms/EndpointDisplay.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-// This file is part of MinIO Console Server
-// Copyright (c) 2022 MinIO, Inc.
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-import React, { Fragment, useEffect, useState } from "react";
-
-import { Theme } from "@mui/material/styles";
-import createStyles from "@mui/styles/createStyles";
-import withStyles from "@mui/styles/withStyles";
-
-import {
- fieldBasic,
- settingsCommon,
-} from "../../Common/FormComponents/common/styleLibrary";
-
-import TableWrapper from "../../Common/TableWrapper/TableWrapper";
-
-const styles = (theme: Theme) =>
- createStyles({
- ...fieldBasic,
- ...settingsCommon,
- });
-
-interface IEndpointDisplayProps {
- // selectedConfiguration: IConfigurationElement;
- classes: any;
- configSubsysList: any[];
- className?: string;
-}
-
-const EndpointDisplay = ({
- // selectedConfiguration,
- classes,
- configSubsysList,
- className = "",
-}: IEndpointDisplayProps) => {
- const [configRecords, setConfigRecords] = useState([]);
-
- useEffect(() => {
- let records: any[] = [];
- if (configSubsysList !== null) {
- configSubsysList.forEach((config) => {
- if (config.name !== null && config.key_values !== null) {
- records.push({
- name: config.name,
- endpoint: config.key_values[0]["value"],
- });
- if (config.key_values[0]["value"] === "off") {
- records = [];
- }
- }
- });
- setConfigRecords(records);
- }
- }, [configSubsysList]);
-
- return (
-
- Currently Configured Endpoints
-
-
-
- );
-};
-
-export default withStyles(styles)(EndpointDisplay);
diff --git a/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/AddEndpointModal.tsx b/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/AddEndpointModal.tsx
new file mode 100644
index 000000000..89a57e474
--- /dev/null
+++ b/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/AddEndpointModal.tsx
@@ -0,0 +1,251 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2023 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import React, { Fragment, useState } from "react";
+import { Button, Grid } from "mds";
+import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
+import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
+import { Webhook } from "@mui/icons-material";
+import { formFieldStyles } from "../../Common/FormComponents/common/styleLibrary";
+import CallToActionIcon from "@mui/icons-material/CallToAction";
+import PendingActionsIcon from "@mui/icons-material/PendingActions";
+import api from "../../../../common/api";
+import {
+ configurationIsLoading,
+ setErrorSnackMessage,
+ setServerNeedsRestart,
+ setSnackBarMessage,
+} from "../../../../systemSlice";
+import { ErrorResponseHandler } from "../../../../common/types";
+import { useAppDispatch } from "../../../../store";
+import { LinearProgress } from "@mui/material";
+
+interface IEndpointModal {
+ open: boolean;
+ type: string;
+ onCloseEndpoint: () => void;
+}
+
+const AddEndpointModal = ({ open, type, onCloseEndpoint }: IEndpointModal) => {
+ const [name, setName] = useState("");
+ const [endpoint, setEndpoint] = useState("");
+ const [authToken, setAuthToken] = useState("");
+ const [saving, setSaving] = useState(false);
+ const [invalidInputs, setInvalidInput] = useState([
+ "name",
+ "endpoint",
+ ]);
+ const [initialInputs, setInitialInputs] = useState([
+ "name",
+ "endpoint",
+ "auth-token",
+ ]);
+
+ const dispatch = useAppDispatch();
+
+ const saveWebhook = () => {
+ if (saving) {
+ return;
+ }
+
+ if (invalidInputs.length !== 0) {
+ return;
+ }
+
+ if (name.trim() === "") {
+ setInvalidInput([...invalidInputs, "name"]);
+
+ return;
+ }
+
+ if (endpoint.trim() === "") {
+ setInvalidInput([...invalidInputs, "endpoint"]);
+
+ return;
+ }
+
+ setSaving(true);
+
+ const payload = {
+ key_values: [
+ {
+ key: "endpoint",
+ value: endpoint,
+ },
+ {
+ key: "auth_token",
+ value: authToken,
+ },
+ ],
+ arn_resource_id: name,
+ };
+
+ api
+ .invoke("PUT", `/api/v1/configs/${type}`, payload)
+ .then((res) => {
+ setSaving(false);
+ dispatch(setServerNeedsRestart(res.restart));
+ if (!res.restart) {
+ dispatch(setSnackBarMessage("Configuration saved successfully"));
+ }
+
+ onCloseEndpoint();
+ dispatch(configurationIsLoading(true));
+ })
+ .catch((err: ErrorResponseHandler) => {
+ setSaving(false);
+ dispatch(setErrorSnackMessage(err));
+ });
+ };
+
+ const initializeInput = (name: string) => {
+ setInitialInputs(initialInputs.filter((item) => item !== name));
+ };
+
+ const validateInput = (name: string, valid: boolean) => {
+ if (invalidInputs.includes(name) && valid) {
+ setInvalidInput(invalidInputs.filter((item) => item !== name));
+ return;
+ }
+
+ if (!valid && !invalidInputs.includes(name)) {
+ setInvalidInput([...invalidInputs, name]);
+ }
+ };
+
+ let title = "Add new Webhook";
+ let icon = ;
+
+ switch (type) {
+ case "logger_webhook":
+ title = "New Logger Webhook";
+ icon = ;
+ break;
+ case "audit_webhook":
+ title = "New Audit Webhook";
+ icon = ;
+ break;
+ }
+
+ return (
+
+
+
+ ) => {
+ initializeInput("name");
+ setName(event.target.value);
+ validateInput("name", event.target.validity.valid);
+ }}
+ error={
+ invalidInputs.includes("name") && !initialInputs.includes("name")
+ ? "Invalid Name"
+ : ""
+ }
+ label="Name"
+ value={name}
+ pattern={"^(?=.*[a-zA-Z0-9]).{1,}$"}
+ required
+ />
+
+
+ ) => {
+ initializeInput("endpoint");
+ setEndpoint(event.target.value);
+ validateInput("endpoint", event.target.validity.valid);
+ }}
+ error={
+ invalidInputs.includes("endpoint") &&
+ !initialInputs.includes("endpoint")
+ ? "Invalid Endpoint set"
+ : ""
+ }
+ label="Endpoint"
+ value={endpoint}
+ pattern={
+ "^(https?):\\/\\/([a-zA-Z0-9\\-.]+)(:[0-9]+)?(\\/[a-zA-Z0-9\\-.\\/]*)?$"
+ }
+ required
+ />
+
+
+ ) => {
+ initializeInput("auth-token");
+ setAuthToken(event.target.value);
+ }}
+ label="Auth Token"
+ value={authToken}
+ />
+
+ {saving && (
+
+
+
+ )}
+
+
+
+
+
+
+ );
+};
+
+export default AddEndpointModal;
diff --git a/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/DeleteWebhookEndpoint.tsx b/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/DeleteWebhookEndpoint.tsx
new file mode 100644
index 000000000..2bf00c8b3
--- /dev/null
+++ b/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/DeleteWebhookEndpoint.tsx
@@ -0,0 +1,96 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2023 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import React, { useEffect, useState } from "react";
+import { ConfirmDeleteIcon } from "mds";
+import { DialogContentText } from "@mui/material";
+import ConfirmDialog from "../../Common/ModalWrapper/ConfirmDialog";
+import api from "../../../../common/api";
+import {
+ configurationIsLoading,
+ setErrorSnackMessage,
+ setServerNeedsRestart,
+} from "../../../../systemSlice";
+import { ErrorResponseHandler } from "../../../../common/types";
+import { useAppDispatch } from "../../../../store";
+
+interface IDeleteWebhookEndpoint {
+ modalOpen: boolean;
+ onClose: () => void;
+ selectedARN: string;
+ type: string;
+}
+
+const DeleteWebhookEndpoint = ({
+ modalOpen,
+ onClose,
+ selectedARN,
+ type,
+}: IDeleteWebhookEndpoint) => {
+ const [deleteLoading, setDeleteLoading] = useState(false);
+
+ const dispatch = useAppDispatch();
+
+ useEffect(() => {
+ if (deleteLoading) {
+ api
+ .invoke("POST", `/api/v1/configs/${selectedARN}/reset`)
+ .then(() => {
+ setDeleteLoading(false);
+ dispatch(setServerNeedsRestart(true));
+ dispatch(configurationIsLoading(true));
+ onClose();
+ })
+ .catch((err: ErrorResponseHandler) => {
+ setDeleteLoading(false);
+ dispatch(setErrorSnackMessage(err));
+ });
+ }
+ }, [deleteLoading, dispatch, onClose, selectedARN]);
+
+ const onConfirmDelete = () => {
+ setDeleteLoading(true);
+ };
+
+ const defaultWH = !selectedARN.includes(":");
+
+ let message = "Are you sure you want to delete the Configured Endpoint";
+
+ // Main webhook, we just reset
+ if (defaultWH) {
+ message = "Are you sure you want to reset the Default";
+ }
+
+ return (
+ }
+ onClose={onClose}
+ confirmationContent={
+
+ {`${message} `}
+ {selectedARN}?
+
+ }
+ />
+ );
+};
+
+export default DeleteWebhookEndpoint;
diff --git a/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/EditWebhookEndpoint.tsx b/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/EditWebhookEndpoint.tsx
new file mode 100644
index 000000000..308b10379
--- /dev/null
+++ b/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/EditWebhookEndpoint.tsx
@@ -0,0 +1,280 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2023 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import React, { Fragment, useEffect, useState } from "react";
+import { Button, Grid } from "mds";
+import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
+import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
+import { Webhook } from "@mui/icons-material";
+import { formFieldStyles } from "../../Common/FormComponents/common/styleLibrary";
+import CallToActionIcon from "@mui/icons-material/CallToAction";
+import PendingActionsIcon from "@mui/icons-material/PendingActions";
+import api from "../../../../common/api";
+import {
+ configurationIsLoading,
+ setErrorSnackMessage,
+ setServerNeedsRestart,
+ setSnackBarMessage,
+} from "../../../../systemSlice";
+import { ErrorResponseHandler } from "../../../../common/types";
+import { useAppDispatch } from "../../../../store";
+import { LinearProgress } from "@mui/material";
+import { IConfigurationSys } from "../../Configurations/types";
+import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
+
+interface IEndpointModal {
+ open: boolean;
+ type: string;
+ endpointInfo: IConfigurationSys;
+ onCloseEndpoint: () => void;
+}
+
+const EditEndpointModal = ({
+ open,
+ type,
+ endpointInfo,
+ onCloseEndpoint,
+}: IEndpointModal) => {
+ const [name, setName] = useState("");
+ const [endpoint, setEndpoint] = useState("");
+ const [authToken, setAuthToken] = useState("");
+ const [endpointState, setEndpointState] = useState("on");
+ const [saving, setSaving] = useState(false);
+ const [invalidInputs, setInvalidInput] = useState([]);
+
+ const dispatch = useAppDispatch();
+
+ useEffect(() => {
+ if (endpointInfo) {
+ const endpointLocate = endpointInfo.key_values.find(
+ (key) => key.key === "endpoint"
+ );
+ const tokenLocate = endpointInfo.key_values.find(
+ (key) => key.key === "auth_token"
+ );
+ const enable = endpointInfo.key_values.find(
+ (key) => key.key === "enable"
+ );
+
+ let invalidInputs: string[] = [];
+
+ if (endpointLocate) {
+ const endpointValue = endpointLocate.value;
+
+ if (endpointValue === "") {
+ invalidInputs.push("endpoint");
+ } else {
+ setEndpoint(endpointValue);
+ }
+ }
+
+ if (tokenLocate) {
+ const tokenValue = tokenLocate.value;
+
+ if (tokenValue === "") {
+ invalidInputs.push("auth-token");
+ } else {
+ setAuthToken(tokenValue);
+ }
+ }
+
+ if (enable) {
+ if (enable.value === "off") {
+ setEndpointState(enable.value);
+ }
+ }
+
+ setName(endpointInfo.name || "");
+ setInvalidInput(invalidInputs);
+ }
+ }, [endpointInfo]);
+
+ const updateWebhook = () => {
+ if (saving) {
+ return;
+ }
+
+ if (invalidInputs.length !== 0) {
+ return;
+ }
+
+ if (!endpoint || endpoint.trim() === "") {
+ setInvalidInput([...invalidInputs, "endpoint"]);
+
+ return;
+ }
+
+ setSaving(true);
+
+ const payload = {
+ key_values: [
+ {
+ key: "endpoint",
+ value: endpoint,
+ },
+ {
+ key: "auth_token",
+ value: authToken,
+ },
+ {
+ key: "enable",
+ value: endpointState,
+ },
+ ],
+ };
+
+ api
+ .invoke("PUT", `/api/v1/configs/${name}`, payload)
+ .then((res) => {
+ setSaving(false);
+ dispatch(setServerNeedsRestart(res.restart));
+ if (!res.restart) {
+ dispatch(setSnackBarMessage("Configuration saved successfully"));
+ }
+
+ onCloseEndpoint();
+ dispatch(configurationIsLoading(true));
+ })
+ .catch((err: ErrorResponseHandler) => {
+ setSaving(false);
+ dispatch(setErrorSnackMessage(err));
+ });
+ };
+
+ const validateInput = (name: string, valid: boolean) => {
+ if (invalidInputs.includes(name) && valid) {
+ setInvalidInput(invalidInputs.filter((item) => item !== name));
+ return;
+ }
+
+ if (!valid && !invalidInputs.includes(name)) {
+ setInvalidInput([...invalidInputs, name]);
+ }
+ };
+
+ const defaultWH = !name.includes(":");
+
+ let title = "Edit Webhook";
+ let icon = ;
+
+ switch (type) {
+ case "logger_webhook":
+ title = `Edit ${defaultWH ? " the Default " : ""}Logger Webhook`;
+ icon = ;
+ break;
+ case "audit_webhook":
+ title = `Edit ${defaultWH ? " the Default " : ""}Audit Webhook`;
+ icon = ;
+ break;
+ }
+
+ return (
+
+
+
+ ) => {
+ const value = e.target.checked ? "on" : "off";
+ setEndpointState(value);
+ }}
+ id={"endpoint_enabled"}
+ name={"endpoint_enabled"}
+ label={"Enabled"}
+ value={"switch_on"}
+ checked={endpointState === "on"}
+ />
+
+
+ ) => {
+ setEndpoint(event.target.value);
+ validateInput("endpoint", event.target.validity.valid);
+ }}
+ error={
+ invalidInputs.includes("endpoint") ? "Invalid Endpoint set" : ""
+ }
+ label="Endpoint"
+ value={endpoint}
+ pattern={
+ "^(https?):\\/\\/([a-zA-Z0-9\\-.]+)(:[0-9]+)?(\\/[a-zA-Z0-9\\-.\\/]*)?$"
+ }
+ required
+ />
+
+
+ ) => {
+ setAuthToken(event.target.value);
+ }}
+ label="Auth Token"
+ value={authToken}
+ />
+
+ {saving && (
+
+
+
+ )}
+
+
+
+
+
+
+ );
+};
+
+export default EditEndpointModal;
diff --git a/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/WebhookSettings.tsx b/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/WebhookSettings.tsx
new file mode 100644
index 000000000..ba5f5d185
--- /dev/null
+++ b/portal-ui/src/screens/Console/NotificationEndpoints/WebhookSettings/WebhookSettings.tsx
@@ -0,0 +1,191 @@
+// This file is part of MinIO Console Server
+// Copyright (c) 2023 MinIO, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+import React, { Fragment, useState } from "react";
+import { IConfigurationSys, IElementValue } from "../../Configurations/types";
+import { Button, DataTable, Grid, TierOfflineIcon, TierOnlineIcon } from "mds";
+import AddEndpointModal from "./AddEndpointModal";
+import DeleteWebhookEndpoint from "./DeleteWebhookEndpoint";
+import EditWebhookEndpoint from "./EditWebhookEndpoint";
+
+interface WebhookSettingsProps {
+ WebhookSettingslist: IConfigurationSys[];
+ setResetConfigurationOpen: () => void;
+ type: string;
+}
+
+const WebhookSettings = ({
+ setResetConfigurationOpen,
+ WebhookSettingslist,
+ type,
+}: WebhookSettingsProps) => {
+ const [newEndpointOpen, setNewEndpointOpen] = useState(false);
+ const [deleteWebhookOpen, setDeleteWebhookOpen] = useState(false);
+ const [editWebhookOpen, setEditWebhookOpen] = useState(false);
+ const [selectedARN, setSelectedARN] = useState("");
+ const [selectedEndpoint, setSelectedEndpoint] =
+ useState(null);
+
+ const renderEndpoint = (item: IElementValue[]) => {
+ const endpointFilter = item.find((itm) => itm.key === "endpoint");
+
+ if (endpointFilter) {
+ return endpointFilter.value;
+ }
+
+ return "";
+ };
+
+ const renderWebhookStatus = (item: IElementValue[]) => {
+ const EnableFilter = item.find((itm) => itm.key === "enable");
+
+ // If enable is not set, then enabled by default
+ if (!EnableFilter || EnableFilter.value === "on") {
+ return (
+
+
+ Enabled
+
+ );
+ }
+
+ return (
+
+
+ Disabled
+
+ );
+ };
+
+ const onCloseDelete = () => {
+ setDeleteWebhookOpen(false);
+ setSelectedARN("");
+ };
+
+ const onCloseEditWebhook = () => {
+ setEditWebhookOpen(false);
+ setSelectedEndpoint(null);
+ };
+
+ const actions = [
+ {
+ type: "view",
+ onClick: (item: IConfigurationSys) => {
+ if (item.name) {
+ setEditWebhookOpen(true);
+ setSelectedEndpoint(item);
+ }
+ },
+ },
+ {
+ type: "delete",
+ onClick: (item: IConfigurationSys) => {
+ if (item.name) {
+ setDeleteWebhookOpen(true);
+ setSelectedARN(item.name);
+ }
+ },
+ },
+ ];
+
+ return (
+
+ {newEndpointOpen && (
+ {
+ setNewEndpointOpen(false);
+ }}
+ />
+ )}
+ {deleteWebhookOpen && (
+
+ )}
+ {editWebhookOpen && selectedEndpoint && (
+
+ )}
+
+
+
+
+
+ Currently Configured Endpoints
+
+
+
+
+ );
+};
+
+export default WebhookSettings;
diff --git a/portal-ui/src/systemSlice.ts b/portal-ui/src/systemSlice.ts
index 394141c91..ddbeed915 100644
--- a/portal-ui/src/systemSlice.ts
+++ b/portal-ui/src/systemSlice.ts
@@ -35,6 +35,7 @@ export interface SystemState {
userName: string;
serverNeedsRestart: boolean;
serverIsLoading: boolean;
+ loadingConfigurations: boolean;
loadingProgress: number;
snackBar: snackBarMessage;
modalSnackBar: snackBarMessage;
@@ -58,6 +59,7 @@ const initialState: SystemState = {
siteReplicationInfo: { siteName: "", curSite: false, enabled: false },
serverNeedsRestart: false,
serverIsLoading: false,
+ loadingConfigurations: true,
loadingProgress: 100,
snackBar: {
message: "",
@@ -106,6 +108,9 @@ export const systemSlice = createSlice({
serverIsLoading: (state, action: PayloadAction) => {
state.serverIsLoading = action.payload;
},
+ configurationIsLoading: (state, action: PayloadAction) => {
+ state.loadingConfigurations = action.payload;
+ },
setLoadingProgress: (state, action: PayloadAction) => {
state.loadingProgress = action.payload;
},
@@ -192,6 +197,7 @@ export const {
setOverrideStyles,
setAnonymousMode,
resetSystem,
+ configurationIsLoading,
} = systemSlice.actions;
export const selDistSet = (state: AppState) => state.system.distributedSetup;