diff --git a/portal-ui/src/screens/Console/Account/NotificationEndpointTypeSelectorHelpBox.tsx b/portal-ui/src/screens/Console/Account/NotificationEndpointTypeSelectorHelpBox.tsx index 0df50604f..23cddf9d1 100644 --- a/portal-ui/src/screens/Console/Account/NotificationEndpointTypeSelectorHelpBox.tsx +++ b/portal-ui/src/screens/Console/Account/NotificationEndpointTypeSelectorHelpBox.tsx @@ -14,84 +14,23 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import React from "react"; -import { Box } from "@mui/material"; -import { HelpIconFilled, LambdaNotificationsIcon } from "mds"; -const FeatureItem = ({ - icon, - description, -}: { - icon: any; - description: string; -}) => { - return ( - - {icon}{" "} -
- {description} -
-
- ); -}; +import { HelpBox, LambdaNotificationsIcon, Box } from "mds"; + const NotificationEndpointTypeSelectorHelpBox = () => { return ( - - - -
Learn more about Event Destinations
-
- - - } - description={`What are Event Destinations?`} - /> - - MinIO bucket notifications allow administrators to send - notifications to supported external services on certain object or - bucket events. MinIO supports bucket and object-level S3 events - similar to the Amazon S3 Event Notifications. - + } + title={"What are Event Destinations?"} + help={ + + MinIO bucket notifications allow administrators to send notifications + to supported external services on certain object or bucket events. + MinIO supports bucket and object-level S3 events similar to the Amazon + S3 Event Notifications. - - + } + /> ); }; diff --git a/portal-ui/src/screens/Console/Common/FormComponents/common/styleLibrary.ts b/portal-ui/src/screens/Console/Common/FormComponents/common/styleLibrary.ts index de5a7bf71..70a56b26b 100644 --- a/portal-ui/src/screens/Console/Common/FormComponents/common/styleLibrary.ts +++ b/portal-ui/src/screens/Console/Common/FormComponents/common/styleLibrary.ts @@ -400,7 +400,7 @@ export const typesSelection = { height: "80px", }, lambdaNotif: { - background: "#ffffff", + background: "#ffffff50", border: "#E5E5E5 1px solid", borderRadius: 5, width: 250, diff --git a/portal-ui/src/screens/Console/EventDestinations/AddEventDestination.tsx b/portal-ui/src/screens/Console/EventDestinations/AddEventDestination.tsx index 1416464f5..57ace33c5 100644 --- a/portal-ui/src/screens/Console/EventDestinations/AddEventDestination.tsx +++ b/portal-ui/src/screens/Console/EventDestinations/AddEventDestination.tsx @@ -17,19 +17,18 @@ import React, { Fragment, useCallback, useEffect, useState } from "react"; import get from "lodash/get"; -import Grid from "@mui/material/Grid"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; -import { BackLink, Button, PageLayout } from "mds"; +import { BackLink, Button, FormLayout, Grid, InputBox, PageLayout } from "mds"; import api from "../../../common/api"; import { + destinationList, notificationEndpointsFields, notifyMysql, notifyPostgres, removeEmptyFields, - destinationList, } from "./utils"; import { modalBasic, @@ -49,6 +48,8 @@ import { import { useNavigate, useParams } from "react-router-dom"; import { useAppDispatch } from "../../../store"; import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper"; +import TargetTitle from "./TargetTitle"; +import { setDestinationLoading } from "./destinationsSlice"; const ConfMySql = withSuspense( React.lazy(() => import("./CustomForms/ConfMySql")) @@ -66,43 +67,6 @@ const styles = (theme: Theme) => createStyles({ ...modalBasic, ...settingsCommon, - lambdaNotif: { - background: - "linear-gradient(90deg, rgba(249,249,250,1) 0%, rgba(250,250,251,1) 68%, rgba(254,254,254,1) 100%)", - border: "#E5E5E5 1px solid", - borderRadius: 5, - height: 80, - display: "flex", - alignItems: "center", - justifyContent: "start", - marginBottom: 16, - cursor: "pointer", - padding: 0, - overflow: "hidden", - }, - lambdaNotifIcon: { - backgroundColor: "#FEFEFE", - display: "flex", - alignItems: "center", - justifyContent: "center", - width: 80, - height: 80, - - "& img": { - maxWidth: 46, - maxHeight: 46, - }, - }, - lambdaNotifTitle: { - color: "#07193E", - fontSize: 16, - fontFamily: "Inter,sans-serif", - paddingLeft: 18, - }, - formBox: { - border: "1px solid #EAEAEA", - padding: 15, - }, }); interface IAddNotificationEndpointProps { @@ -120,20 +84,22 @@ const AddEventDestination = ({ //Local States const [valuesArr, setValueArr] = useState([]); + const [identifier, setIdentifier] = useState(""); const [saving, setSaving] = useState(false); const service = params.service || ""; - //Effects + //Effects useEffect(() => { if (saving) { const payload = { key_values: removeEmptyFields(valuesArr), }; api - .invoke("PUT", `/api/v1/configs/${service}`, payload) + .invoke("PUT", `/api/v1/configs/${service}:${identifier}`, payload) .then(() => { setSaving(false); dispatch(setServerNeedsRestart(true)); + dispatch(setDestinationLoading(true)); navigate(IAM_PAGES.EVENT_DESTINATIONS); }) .catch((err: ErrorResponseHandler) => { @@ -141,7 +107,15 @@ const AddEventDestination = ({ dispatch(setErrorSnackMessage(err)); }); } - }, [saving, service, valuesArr, saveAndRefresh, dispatch, navigate]); + }, [ + saving, + service, + valuesArr, + saveAndRefresh, + dispatch, + navigate, + identifier, + ]); //Fetch Actions const submitForm = (event: React.FormEvent) => { @@ -199,41 +173,54 @@ const AddEventDestination = ({ {targetElement && ( -
-
- {targetElement.targetTitle} -
- -
- - {targetElement ? targetElement.targetTitle : ""} Event - Destination - -
-
+ )}
-
- + + + setIdentifier(e.target.value)} + tooltip={"Unique descriptive string for this destination"} + placeholder="Enter Destination Identifier" + required + /> + + {srvComponent} - +
+
)} diff --git a/portal-ui/src/screens/Console/EventDestinations/ConfTargetGeneric.tsx b/portal-ui/src/screens/Console/EventDestinations/ConfTargetGeneric.tsx index 3f5c1d7e6..7085b0e74 100644 --- a/portal-ui/src/screens/Console/EventDestinations/ConfTargetGeneric.tsx +++ b/portal-ui/src/screens/Console/EventDestinations/ConfTargetGeneric.tsx @@ -24,12 +24,10 @@ import { formFieldStyles, modalBasic, } from "../Common/FormComponents/common/styleLibrary"; -import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; import CSVMultiSelector from "../Common/FormComponents/CSVMultiSelector/CSVMultiSelector"; import CommentBoxWrapper from "../Common/FormComponents/CommentBoxWrapper/CommentBoxWrapper"; -import FormSwitchWrapper from "../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; import PredefinedList from "../Common/FormComponents/PredefinedList/PredefinedList"; -import { ConsoleIcon, Tooltip } from "mds"; +import { ConsoleIcon, InputBox, Switch, Tooltip } from "mds"; interface IConfGenericProps { onChange: (newValue: IElementValue[]) => void; @@ -144,7 +142,7 @@ const ConfTargetGeneric = ({ const value = holderItem ? holderItem.value : "off"; return ( - ) => { const value = e.target.checked ? "on" : "off"; setValueElement(field.name, value, item); @@ -195,7 +193,7 @@ const ConfTargetGeneric = ({ ); default: return ( - ) => setValueElement(field.name, e.target.value, item) } - multiline={!!field.multiline} placeholder={field.placeholder} /> ); diff --git a/portal-ui/src/screens/Console/EventDestinations/ConfirmDeleteDestinationModal.tsx b/portal-ui/src/screens/Console/EventDestinations/ConfirmDeleteDestinationModal.tsx index 6ce07a3df..efa6ae01e 100644 --- a/portal-ui/src/screens/Console/EventDestinations/ConfirmDeleteDestinationModal.tsx +++ b/portal-ui/src/screens/Console/EventDestinations/ConfirmDeleteDestinationModal.tsx @@ -1,7 +1,22 @@ +// 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 from "react"; import ConfirmDialog from "../Common/ModalWrapper/ConfirmDialog"; import { ConfirmModalIcon } from "mds"; -import { DialogContentText } from "@mui/material"; const ConfirmDeleteDestinationModal = ({ onConfirm, @@ -25,11 +40,9 @@ const ConfirmDeleteDestinationModal = ({ onClose={onClose} confirmationContent={ - - Are you sure you want to delete the event destination ? -
- {serviceName} which is {status} -
+ Are you sure you want to delete the event destination ? +
+ {serviceName} which is {status}
} /> diff --git a/portal-ui/src/screens/Console/EventDestinations/CustomForms/ConfMySql.tsx b/portal-ui/src/screens/Console/EventDestinations/CustomForms/ConfMySql.tsx index 6a4a3d241..022dcfded 100644 --- a/portal-ui/src/screens/Console/EventDestinations/CustomForms/ConfMySql.tsx +++ b/portal-ui/src/screens/Console/EventDestinations/CustomForms/ConfMySql.tsx @@ -18,17 +18,13 @@ import React, { useCallback, useEffect, useState } from "react"; import { Theme } from "@mui/material/styles"; import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; -import Grid from "@mui/material/Grid"; -import InputBoxWrapper from "../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper"; -import RadioGroupSelector from "../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector"; import { IElementValue } from "../../Configurations/types"; import { formFieldStyles, modalBasic, } from "../../Common/FormComponents/common/styleLibrary"; import CommentBoxWrapper from "../../Common/FormComponents/CommentBoxWrapper/CommentBoxWrapper"; -import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper"; -import PredefinedList from "../../Common/FormComponents/PredefinedList/PredefinedList"; +import { Switch, InputBox, Grid, Box, ReadBox, RadioGroup } from "mds"; interface IConfMySqlProps { onChange: (newValue: IElementValue[]) => void; @@ -138,8 +134,8 @@ const ConfMySql = ({ onChange, classes }: IConfMySqlProps) => { return ( - - + { {useDsnString ? ( - { ) : ( - + - { /> - { /> - { - { /> - { }} /> - +
- - -
+ + + {dsnString} + )} - { /> - { /> - { /> - void; @@ -205,8 +200,8 @@ const ConfPostgres = ({ onChange, classes }: IConfPostgresProps) => { return ( - - + { {useConnectionString ? ( - { ) : ( - + - { /> - { /> - { /> - { - if (e.target.value !== undefined) { - setSslMode(e.target.value + ""); + onChange={(value): void => { + if (value) { + setSslMode(value + ""); } }} options={[ @@ -292,7 +295,7 @@ const ConfPostgres = ({ onChange, classes }: IConfPostgresProps) => { /> - { /> - { }} /> - + - - -
+ + + {connectionString} +
)} - { /> - { /> - { /> - . + +import React from "react"; +import get from "lodash/get"; +import { useNavigate } from "react-router-dom"; +import styled from "styled-components"; +import { IAM_PAGES } from "../../../common/SecureComponent/permissions"; + +interface IDestinationButton { + destinationType: string; + srcImage: string; + title: string; +} + +const DestinationButtonBase = styled.button(({ theme }) => ({ + background: get(theme, "boxBackground", "#FFF"), + border: `${get(theme, "borderColor", "#E2E2E2")} 1px solid`, + borderRadius: 5, + width: 250, + height: 80, + display: "flex", + alignItems: "center", + justifyContent: "start", + marginBottom: 16, + marginRight: 8, + cursor: "pointer", + overflow: "hidden", + "&:hover": { + backgroundColor: get(theme, "buttons.regular.hover.background", "#ebebeb"), + }, + "& .imageContainer": { + width: 80, + "& .logoButton": { + maxWidth: 46, + maxHeight: 46, + filter: "drop-shadow(1px 1px 8px #fff)", + }, + }, + "& .lambdaNotifTitle": { + color: get(theme, "buttons.callAction.enabled.background", "#07193E"), + fontSize: 16, + fontFamily: "Inter,sans-serif", + paddingLeft: 18, + fontWeight: "bold", + }, +})); + +const DestinationButton = ({ + destinationType, + srcImage, + title, +}: IDestinationButton) => { + const navigate = useNavigate(); + + return ( + { + navigate(`${IAM_PAGES.EVENT_DESTINATIONS_ADD}/${destinationType}`); + }} + > + + {title} + + {title} + + ); +}; + +export default DestinationButton; diff --git a/portal-ui/src/screens/Console/EventDestinations/EventTypeSelector.tsx b/portal-ui/src/screens/Console/EventDestinations/EventTypeSelector.tsx index 51324cd25..fb612e41d 100644 --- a/portal-ui/src/screens/Console/EventDestinations/EventTypeSelector.tsx +++ b/portal-ui/src/screens/Console/EventDestinations/EventTypeSelector.tsx @@ -15,24 +15,14 @@ // along with this program. If not, see . import React, { Fragment } from "react"; -import { Theme } from "@mui/material/styles"; import { useNavigate } from "react-router-dom"; -import createStyles from "@mui/styles/createStyles"; -import withStyles from "@mui/styles/withStyles"; +import { BackLink, Box, FormLayout, PageLayout } from "mds"; import { destinationList, DestType } from "./utils"; -import { - settingsCommon, - typesSelection, -} from "../Common/FormComponents/common/styleLibrary"; +import { typesSelection } from "../Common/FormComponents/common/styleLibrary"; import { IAM_PAGES } from "../../../common/SecureComponent/permissions"; -import { Box } from "@mui/material"; import NotificationEndpointTypeSelectorHelpBox from "../Account/NotificationEndpointTypeSelectorHelpBox"; -import { BackLink, PageLayout } from "mds"; import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper"; - -interface INotificationTypeSelector { - classes: any; -} +import DestinationButton from "./DestinationButton"; const withLogos = destinationList.filter((elService) => elService.logo !== ""); const database = withLogos.filter( @@ -45,13 +35,7 @@ const functions = withLogos.filter( (elService) => elService.category === DestType.Func ); -const styles = (theme: Theme) => - createStyles({ - ...settingsCommon, - ...typesSelection, - }); - -const EventTypeSelector = ({ classes }: INotificationTypeSelector) => { +const EventTypeSelector = () => { const navigate = useNavigate(); return ( @@ -67,115 +51,58 @@ const EventTypeSelector = ({ classes }: INotificationTypeSelector) => { actions={} /> - -
-
+ }> + + Queue -
-
+ + {queue.map((item) => { return ( - + /> ); })} -
-
+ + Database -
-
+ + {database.map((item) => { return ( - + /> ); })} -
-
+ + Functions -
-
+ + {functions.map((item) => { return ( - + /> ); })} -
-
- -
+ + +
); }; -export default withStyles(styles)(EventTypeSelector); +export default EventTypeSelector; diff --git a/portal-ui/src/screens/Console/EventDestinations/ListEventDestinations.tsx b/portal-ui/src/screens/Console/EventDestinations/ListEventDestinations.tsx index cd3e27e12..34af57d5a 100644 --- a/portal-ui/src/screens/Console/EventDestinations/ListEventDestinations.tsx +++ b/portal-ui/src/screens/Console/EventDestinations/ListEventDestinations.tsx @@ -19,6 +19,8 @@ import { AddIcon, Box, Button, + DataTable, + Grid, HelpBox, LambdaIcon, PageLayout, @@ -30,7 +32,6 @@ import createStyles from "@mui/styles/createStyles"; import withStyles from "@mui/styles/withStyles"; import { LinearProgress } from "@mui/material"; import { red } from "@mui/material/colors"; -import Grid from "@mui/material/Grid"; import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord"; import { NotificationEndpointItem, @@ -38,7 +39,6 @@ import { TransformedEndpointItem, } from "./types"; import { getNotificationConfigKey, notificationTransform } from "./utils"; -import TableWrapper from "../Common/TableWrapper/TableWrapper"; import { actionsTray, @@ -57,9 +57,11 @@ import { setErrorSnackMessage, setServerNeedsRestart, } from "../../../systemSlice"; -import { useAppDispatch } from "../../../store"; +import { AppState, useAppDispatch } from "../../../store"; import ConfirmDeleteDestinationModal from "./ConfirmDeleteDestinationModal"; import TooltipWrapper from "../Common/TooltipWrapper/TooltipWrapper"; +import { useSelector } from "react-redux"; +import { setDestinationLoading } from "./destinationsSlice"; interface IListNotificationEndpoints { classes: any; @@ -70,9 +72,6 @@ const styles = (theme: Theme) => ...actionsTray, ...settingsCommon, ...containerForHeader, - twHeight: { - minHeight: 400, - }, tableBlock: { ...tableStyles.tableBlock, }, @@ -92,10 +91,12 @@ const styles = (theme: Theme) => const ListEventDestinations = ({ classes }: IListNotificationEndpoints) => { const dispatch = useAppDispatch(); const navigate = useNavigate(); + // Reducer States + const isLoading = useSelector((state: AppState) => state.destination.loading); + //Local States const [records, setRecords] = useState([]); const [filter, setFilter] = useState(""); - const [isLoading, setIsLoading] = useState(false); const [isDelConfirmOpen, setIsDelConfirmOpen] = useState(false); const [selNotifyEndPoint, setSelNotifyEndpoint] = @@ -114,11 +115,11 @@ const ListEventDestinations = ({ classes }: IListNotificationEndpoints) => { resNotEndList = res.notification_endpoints; } setRecords(notificationTransform(resNotEndList)); - setIsLoading(false); + dispatch(setDestinationLoading(false)); }) .catch((err: ErrorResponseHandler) => { dispatch(setErrorSnackMessage(err)); - setIsLoading(false); + dispatch(setDestinationLoading(false)); }); }; fetchRecords(); @@ -126,8 +127,8 @@ const ListEventDestinations = ({ classes }: IListNotificationEndpoints) => { }, [isLoading, dispatch]); useEffect(() => { - setIsLoading(true); - }, []); + dispatch(setDestinationLoading(true)); + }, [dispatch]); const resetNotificationConfig = ( ep: TransformedEndpointItem | undefined | null @@ -142,6 +143,7 @@ const ListEventDestinations = ({ classes }: IListNotificationEndpoints) => { dispatch(setServerNeedsRestart(true)); setSelNotifyEndpoint(null); setIsDelConfirmOpen(false); + dispatch(setDestinationLoading(true)); }) .catch((err: ErrorResponseHandler) => { setIsDelConfirmOpen(false); @@ -188,142 +190,146 @@ const ListEventDestinations = ({ classes }: IListNotificationEndpoints) => { return ( - - -
- -
-
- {isLoading && } - {!isLoading && ( - - {records.length > 0 && ( - - - - + + +
+ +
+
+ {isLoading && } + {!isLoading && ( + + {records.length > 0 && ( + + + + + + + + } + help={ + + MinIO bucket notifications allow administrators to + send notifications to supported external services on + certain object or bucket events. MinIO supports bucket + and object-level S3 events similar to the Amazon S3 + Event Notifications. +
+
+ You can learn more at our{" "} + + documentation + + . +
+ } /> -
+
+
+ )} + {records.length === 0 && ( + + + } + help={ + + MinIO bucket notifications allow administrators to + send notifications to supported external services on + certain object or bucket events. MinIO supports bucket + and object-level S3 events similar to the Amazon S3 + Event Notifications. +
+
+ To get started,{" "} + { + navigate(IAM_PAGES.EVENT_DESTINATIONS_ADD); + }} + > + Add an Event Destination + + . +
+ } + /> +
- - } - help={ - - MinIO bucket notifications allow administrators to send - notifications to supported external services on certain - object or bucket events. MinIO supports bucket and - object-level S3 events similar to the Amazon S3 Event - Notifications. -
-
- You can learn more at our{" "} - - documentation - - . -
- } - /> -
-
- )} - {records.length === 0 && ( - - - } - help={ - - MinIO bucket notifications allow administrators to send - notifications to supported external services on certain - object or bucket events. MinIO supports bucket and - object-level S3 events similar to the Amazon S3 Event - Notifications. -
-
- To get started,{" "} - { - navigate(IAM_PAGES.EVENT_DESTINATIONS_ADD); - }} - > - Add an Event Destination - - . -
- } - /> -
-
- )} -
- )} + )} + + )} - {isDelConfirmOpen ? ( - { - resetNotificationConfig(selNotifyEndPoint); - }} - status={`${selNotifyEndPoint?.status}`} - serviceName={`${selNotifyEndPoint?.service_name}`} - onClose={() => { - setIsDelConfirmOpen(false); - }} - /> - ) : null} + {isDelConfirmOpen ? ( + { + resetNotificationConfig(selNotifyEndPoint); + }} + status={`${selNotifyEndPoint?.status}`} + serviceName={`${selNotifyEndPoint?.service_name}`} + onClose={() => { + setIsDelConfirmOpen(false); + }} + /> + ) : null} +
); diff --git a/portal-ui/src/screens/Console/EventDestinations/TargetTitle.tsx b/portal-ui/src/screens/Console/EventDestinations/TargetTitle.tsx new file mode 100644 index 000000000..38bb6ee0b --- /dev/null +++ b/portal-ui/src/screens/Console/EventDestinations/TargetTitle.tsx @@ -0,0 +1,78 @@ +// 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 from "react"; +import get from "lodash/get"; +import styled from "styled-components"; +import { Box } from "mds"; + +interface ITargetTitle { + logoSrc: string; + title: string; +} + +const TargetBase = styled.div(({ theme }) => ({ + background: get(theme, "boxBackground", "#fff"), + border: `${get(theme, "borderColor", "#E5E5E5")} 1px solid`, + borderRadius: 5, + height: 80, + display: "flex", + alignItems: "center", + justifyContent: "start", + marginBottom: 16, + cursor: "pointer", + padding: 0, + overflow: "hidden", + "& .logoButton": { + height: "80px", + }, + "& .imageContainer": { + backgroundColor: get(theme, "bgColor", "#fff"), + display: "flex", + alignItems: "center", + justifyContent: "center", + width: 80, + height: 80, + + "& img": { + maxWidth: 46, + maxHeight: 46, + filter: "drop-shadow(1px 1px 8px #fff)", + }, + }, + "& .titleBox": { + color: get(theme, "fontColor", "#000"), + fontSize: 16, + fontFamily: "Inter,sans-serif", + paddingLeft: 18, + }, +})); + +const TargetTitle = ({ logoSrc, title }: ITargetTitle) => { + return ( + + + {title} + + + + {title} Event Destination + + + ); +}; + +export default TargetTitle; diff --git a/portal-ui/src/screens/Console/EventDestinations/destinationsSlice.ts b/portal-ui/src/screens/Console/EventDestinations/destinationsSlice.ts new file mode 100644 index 000000000..2796d8fb6 --- /dev/null +++ b/portal-ui/src/screens/Console/EventDestinations/destinationsSlice.ts @@ -0,0 +1,40 @@ +// 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 { createSlice, PayloadAction } from "@reduxjs/toolkit"; + +export interface DestinationState { + loading: boolean; +} + +const initialState: DestinationState = { + loading: true, +}; + +export const destinationSlice = createSlice({ + name: "destination", + initialState, + reducers: { + setDestinationLoading: (state, action: PayloadAction) => { + state.loading = action.payload; + }, + }, +}); + +// Action creators are generated for each case reducer function +export const { setDestinationLoading } = destinationSlice.actions; + +export default destinationSlice.reducer; diff --git a/portal-ui/src/store.ts b/portal-ui/src/store.ts index 4c7189964..8f47121d8 100644 --- a/portal-ui/src/store.ts +++ b/portal-ui/src/store.ts @@ -30,6 +30,7 @@ import dashboardReducer from "./screens/Console/Dashboard/dashboardSlice"; import createUserReducer from "./screens/Console/Users/AddUsersSlice"; import licenseReducer from "./screens/Console/License/licenseSlice"; import registerReducer from "./screens/Console/Support/registerSlice"; +import destinationSlice from "./screens/Console/EventDestinations/destinationsSlice"; const rootReducer = combineReducers({ system: systemReducer, @@ -46,6 +47,7 @@ const rootReducer = combineReducers({ register: registerReducer, createUser: createUserReducer, license: licenseReducer, + destination: destinationSlice, }); export const store = configureStore({