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;