github.com/minio/console@v1.4.1/web-app/src/screens/Console/Buckets/BucketDetails/AddEvent.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, { useCallback, useEffect, useState, Fragment } from "react"; 18 import { 19 Autocomplete, 20 Button, 21 DataTable, 22 EventSubscriptionIcon, 23 Grid, 24 InputBox, 25 } from "mds"; 26 import { ErrorResponseHandler } from "../../../../common/types"; 27 import { setModalErrorSnackMessage } from "../../../../systemSlice"; 28 import { useAppDispatch } from "../../../../store"; 29 import { api } from "api"; 30 import { NotificationEventType } from "api/consoleApi"; 31 import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper"; 32 import { 33 formFieldStyles, 34 modalBasic, 35 modalStyleUtils, 36 } from "../../Common/FormComponents/common/styleLibrary"; 37 38 interface IAddEventProps { 39 open: boolean; 40 selectedBucket: string; 41 closeModalAndRefresh: () => void; 42 } 43 44 const AddEvent = ({ 45 open, 46 selectedBucket, 47 closeModalAndRefresh, 48 }: IAddEventProps) => { 49 const dispatch = useAppDispatch(); 50 const [addLoading, setAddLoading] = useState<boolean>(false); 51 const [prefix, setPrefix] = useState<string>(""); 52 const [suffix, setSuffix] = useState<string>(""); 53 const [arn, setArn] = useState<string>(""); 54 const [selectedEvents, setSelectedEvents] = useState<NotificationEventType[]>( 55 [], 56 ); 57 const [arnList, setArnList] = useState<string[] | undefined>([]); 58 59 const addRecord = (event: React.FormEvent) => { 60 event.preventDefault(); 61 if (addLoading) { 62 return; 63 } 64 setAddLoading(true); 65 api.buckets 66 .createBucketEvent(selectedBucket, { 67 configuration: { 68 arn: arn, 69 events: selectedEvents, 70 prefix: prefix, 71 suffix: suffix, 72 }, 73 ignoreExisting: true, 74 }) 75 .then(() => { 76 setAddLoading(false); 77 closeModalAndRefresh(); 78 }) 79 .catch((err: ErrorResponseHandler) => { 80 setAddLoading(false); 81 dispatch(setModalErrorSnackMessage(err)); 82 }); 83 }; 84 85 const fetchArnList = useCallback(() => { 86 setAddLoading(true); 87 api.admin 88 .arnList() 89 .then((res) => { 90 if (res.data.arns !== null) { 91 setArnList(res.data.arns); 92 } 93 setAddLoading(false); 94 }) 95 .catch((err: ErrorResponseHandler) => { 96 setAddLoading(false); 97 dispatch(setModalErrorSnackMessage(err)); 98 }); 99 }, [dispatch]); 100 101 useEffect(() => { 102 fetchArnList(); 103 }, [fetchArnList]); 104 105 const events = [ 106 { label: "PUT - Object Uploaded", value: NotificationEventType.Put }, 107 { label: "GET - Object accessed", value: NotificationEventType.Get }, 108 { label: "DELETE - Object Deleted", value: NotificationEventType.Delete }, 109 { 110 label: "REPLICA - Object Replicated", 111 value: NotificationEventType.Replica, 112 }, 113 { label: "ILM - Object Transitioned", value: NotificationEventType.Ilm }, 114 { 115 label: 116 "SCANNER - Object has too many versions / Prefixes has too many sub-folders", 117 value: NotificationEventType.Scanner, 118 }, 119 ]; 120 121 const handleClick = (event: React.ChangeEvent<HTMLInputElement>) => { 122 const targetD = event.target; 123 const value = targetD.value; 124 const checked = targetD.checked; 125 126 let elements: NotificationEventType[] = [...selectedEvents]; 127 128 if (checked) { 129 elements.push(value as NotificationEventType); 130 } else { 131 elements = elements.filter((element) => element !== value); 132 } 133 134 setSelectedEvents(elements); 135 }; 136 137 const arnValues = arnList?.map((arnConstant) => ({ 138 label: arnConstant, 139 value: arnConstant, 140 })); 141 142 return ( 143 <ModalWrapper 144 modalOpen={open} 145 onClose={() => { 146 closeModalAndRefresh(); 147 }} 148 title="Subscribe To Bucket Events" 149 titleIcon={<EventSubscriptionIcon />} 150 > 151 <form 152 noValidate 153 autoComplete="off" 154 onSubmit={(e: React.FormEvent<HTMLFormElement>) => { 155 addRecord(e); 156 }} 157 > 158 <Grid container> 159 <Grid item xs={12} sx={modalBasic.formScrollable}> 160 <Grid 161 item 162 xs={12} 163 sx={{ 164 ...formFieldStyles.formFieldRow, 165 "& div div .MuiOutlinedInput-root": { 166 padding: 0, 167 }, 168 }} 169 > 170 <Autocomplete 171 onChange={(value: string) => { 172 setArn(value); 173 }} 174 id="select-access-policy" 175 name="select-access-policy" 176 label={"ARN"} 177 value={arn} 178 options={arnValues || []} 179 helpTip={ 180 <Fragment> 181 <a 182 target="blank" 183 href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html" 184 > 185 Amazon Resource Name 186 </a> 187 </Fragment> 188 } 189 /> 190 </Grid> 191 <Grid item xs={12} sx={formFieldStyles.formFieldRow}> 192 <InputBox 193 id="prefix-input" 194 name="prefix-input" 195 label="Prefix" 196 value={prefix} 197 onChange={(e: React.ChangeEvent<HTMLInputElement>) => { 198 setPrefix(e.target.value); 199 }} 200 /> 201 </Grid> 202 <Grid item xs={12} sx={formFieldStyles.formFieldRow}> 203 <InputBox 204 id="suffix-input" 205 name="suffix-input" 206 label="Suffix" 207 value={suffix} 208 onChange={(e: React.ChangeEvent<HTMLInputElement>) => { 209 setSuffix(e.target.value); 210 }} 211 /> 212 </Grid> 213 <Grid item xs={12} sx={formFieldStyles.formFieldRow}> 214 <DataTable 215 columns={[{ label: "Event", elementKey: "label" }]} 216 idField={"value"} 217 records={events} 218 onSelect={handleClick} 219 selectedItems={selectedEvents} 220 noBackground 221 customPaperHeight={"260px"} 222 /> 223 </Grid> 224 </Grid> 225 <Grid item xs={12} sx={modalStyleUtils.modalButtonBar}> 226 <Button 227 id={"cancel-add-event"} 228 type="button" 229 variant="regular" 230 disabled={addLoading} 231 onClick={() => { 232 closeModalAndRefresh(); 233 }} 234 label={"Cancel"} 235 /> 236 <Button 237 id={"save-event"} 238 type="submit" 239 variant="callAction" 240 disabled={addLoading || arn === "" || selectedEvents.length === 0} 241 label={"Save"} 242 /> 243 </Grid> 244 </Grid> 245 </form> 246 </ModalWrapper> 247 ); 248 }; 249 250 export default AddEvent;