github.com/minio/console@v1.4.1/web-app/src/screens/Console/EventDestinations/AddEventDestination.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 import React, { Fragment, useCallback, useEffect, useState } from "react"; 18 import get from "lodash/get"; 19 import { BackLink, Button, FormLayout, Grid, InputBox, PageLayout } from "mds"; 20 import { useNavigate, useParams } from "react-router-dom"; 21 import { api } from "api"; 22 import { errorToHandler } from "api/errors"; 23 import { 24 destinationList, 25 notificationEndpointsFields, 26 notifyMysql, 27 notifyPostgres, 28 removeEmptyFields, 29 } from "./utils"; 30 import { IElementValue } from "../Configurations/types"; 31 import { IAM_PAGES } from "../../../common/SecureComponent/permissions"; 32 import { 33 setErrorSnackMessage, 34 setHelpName, 35 setServerNeedsRestart, 36 } from "../../../systemSlice"; 37 import { useAppDispatch } from "../../../store"; 38 import { setDestinationLoading } from "./destinationsSlice"; 39 import withSuspense from "../Common/Components/withSuspense"; 40 import PageHeaderWrapper from "../Common/PageHeaderWrapper/PageHeaderWrapper"; 41 import TargetTitle from "./TargetTitle"; 42 import HelpMenu from "../HelpMenu"; 43 44 const ConfMySql = withSuspense( 45 React.lazy(() => import("./CustomForms/ConfMySql")), 46 ); 47 48 const ConfTargetGeneric = withSuspense( 49 React.lazy(() => import("./ConfTargetGeneric")), 50 ); 51 52 const ConfPostgres = withSuspense( 53 React.lazy(() => import("./CustomForms/ConfPostgres")), 54 ); 55 56 interface IAddNotificationEndpointProps { 57 saveAndRefresh: any; 58 } 59 60 const AddEventDestination = ({ 61 saveAndRefresh, 62 }: IAddNotificationEndpointProps) => { 63 const dispatch = useAppDispatch(); 64 const navigate = useNavigate(); 65 const params = useParams(); 66 67 //Local States 68 const [valuesArr, setValueArr] = useState<IElementValue[]>([]); 69 const [identifier, setIdentifier] = useState<string>(""); 70 const [saving, setSaving] = useState<boolean>(false); 71 const service = params.service || ""; 72 73 //Effects 74 useEffect(() => { 75 if (saving) { 76 const payload = { 77 key_values: removeEmptyFields(valuesArr), 78 }; 79 api.configs 80 .setConfig(`${service}:${identifier}`, payload) 81 .then(() => { 82 setSaving(false); 83 dispatch(setServerNeedsRestart(true)); 84 dispatch(setDestinationLoading(true)); 85 navigate(IAM_PAGES.EVENT_DESTINATIONS); 86 }) 87 .catch((err) => { 88 setSaving(false); 89 dispatch(setErrorSnackMessage(errorToHandler(err.error))); 90 }); 91 } 92 }, [ 93 saving, 94 service, 95 valuesArr, 96 saveAndRefresh, 97 dispatch, 98 navigate, 99 identifier, 100 ]); 101 102 //Fetch Actions 103 const submitForm = (event: React.FormEvent) => { 104 event.preventDefault(); 105 setSaving(true); 106 }; 107 108 const onValueChange = useCallback( 109 (newValue: IElementValue[]) => { 110 setValueArr(newValue); 111 }, 112 [setValueArr], 113 ); 114 115 let srvComponent; 116 switch (service) { 117 case notifyPostgres: { 118 srvComponent = <ConfPostgres onChange={onValueChange} />; 119 break; 120 } 121 case notifyMysql: { 122 srvComponent = <ConfMySql onChange={onValueChange} />; 123 break; 124 } 125 default: { 126 const fields = get(notificationEndpointsFields, service, []); 127 128 srvComponent = ( 129 <ConfTargetGeneric fields={fields} onChange={onValueChange} /> 130 ); 131 } 132 } 133 134 const targetElement = destinationList.find( 135 (element) => element.actionTrigger === service, 136 ); 137 138 useEffect(() => { 139 dispatch(setHelpName("add_notification_endpoint")); 140 // eslint-disable-next-line react-hooks/exhaustive-deps 141 }, []); 142 143 return ( 144 <Fragment> 145 <PageHeaderWrapper 146 label={ 147 <Fragment> 148 <BackLink 149 label="Event Destinations" 150 onClick={() => navigate(IAM_PAGES.EVENT_DESTINATIONS_ADD)} 151 /> 152 </Fragment> 153 } 154 actions={<HelpMenu />} 155 /> 156 157 <PageLayout> 158 <form noValidate onSubmit={submitForm}> 159 {service !== "" && ( 160 <Fragment> 161 <Grid item xs={12}> 162 {targetElement && ( 163 <TargetTitle 164 logoSrc={targetElement.logo} 165 title={targetElement ? targetElement.targetTitle : ""} 166 /> 167 )} 168 </Grid> 169 <FormLayout> 170 <InputBox 171 id={"identifier-field"} 172 name={"identifier-field"} 173 label={"Identifier"} 174 value={identifier} 175 onChange={(e) => setIdentifier(e.target.value)} 176 tooltip={"Unique descriptive string for this destination"} 177 placeholder="Enter Destination Identifier" 178 required 179 /> 180 <Grid item xs={12}> 181 {srvComponent} 182 </Grid> 183 <Grid 184 item 185 xs={12} 186 sx={{ 187 display: "flex", 188 justifyContent: "flex-end", 189 marginTop: 15, 190 }} 191 > 192 <Button 193 id={"save-notification-target"} 194 type="submit" 195 variant="callAction" 196 disabled={saving || identifier.trim() === ""} 197 label={"Save Event Destination"} 198 /> 199 </Grid> 200 </FormLayout> 201 </Fragment> 202 )} 203 </form> 204 </PageLayout> 205 </Fragment> 206 ); 207 }; 208 209 export default AddEventDestination;