github.com/minio/console@v1.4.1/web-app/src/screens/Console/Buckets/BucketDetails/EnableQuota.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, { useEffect, useState } from "react";
    18  import {
    19    BucketQuotaIcon,
    20    Button,
    21    FormLayout,
    22    InputBox,
    23    Switch,
    24    Grid,
    25    ProgressBar,
    26  } from "mds";
    27  import {
    28    calculateBytes,
    29    getBytes,
    30    k8sScalarUnitsExcluding,
    31  } from "../../../../common/utils";
    32  
    33  import { modalStyleUtils } from "../../Common/FormComponents/common/styleLibrary";
    34  import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
    35  import InputUnitMenu from "../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
    36  
    37  import { setModalErrorSnackMessage } from "../../../../systemSlice";
    38  import { useAppDispatch } from "../../../../store";
    39  import { BucketQuota } from "api/consoleApi";
    40  import { api } from "api";
    41  import { errorToHandler } from "api/errors";
    42  
    43  interface IEnableQuotaProps {
    44    open: boolean;
    45    enabled: boolean;
    46    cfg: BucketQuota | null;
    47    selectedBucket: string;
    48    closeModalAndRefresh: () => void;
    49  }
    50  
    51  const EnableQuota = ({
    52    open,
    53    enabled,
    54    cfg,
    55    selectedBucket,
    56    closeModalAndRefresh,
    57  }: IEnableQuotaProps) => {
    58    const dispatch = useAppDispatch();
    59    const [loading, setLoading] = useState<boolean>(false);
    60    const [quotaEnabled, setQuotaEnabled] = useState<boolean>(false);
    61    const [quotaSize, setQuotaSize] = useState<string>("1");
    62    const [quotaUnit, setQuotaUnit] = useState<string>("Ti");
    63    const [validInput, setValidInput] = useState<boolean>(false);
    64  
    65    useEffect(() => {
    66      if (enabled) {
    67        setQuotaEnabled(true);
    68        if (cfg) {
    69          const unitCalc = calculateBytes(cfg.quota || 0, true, false, true);
    70  
    71          setQuotaSize(unitCalc.total.toString());
    72          setQuotaUnit(unitCalc.unit);
    73          setValidInput(true);
    74        }
    75      }
    76    }, [enabled, cfg]);
    77  
    78    useEffect(() => {
    79      const valRegExp = /^\d*(?:\.\d{1,2})?$/;
    80  
    81      if (!quotaEnabled) {
    82        setValidInput(true);
    83        return;
    84      }
    85  
    86      setValidInput(valRegExp.test(quotaSize));
    87    }, [quotaEnabled, quotaSize]);
    88  
    89    const enableBucketEncryption = () => {
    90      if (loading || !validInput) {
    91        return;
    92      }
    93  
    94      api.buckets
    95        .setBucketQuota(selectedBucket, {
    96          enabled: quotaEnabled,
    97          amount: parseInt(getBytes(quotaSize, quotaUnit, true)),
    98          quota_type: "hard",
    99        })
   100        .then(() => {
   101          setLoading(false);
   102          closeModalAndRefresh();
   103        })
   104        .catch((err) => {
   105          setLoading(false);
   106          dispatch(setModalErrorSnackMessage(errorToHandler(err.error)));
   107        });
   108    };
   109  
   110    return (
   111      <ModalWrapper
   112        modalOpen={open}
   113        onClose={() => {
   114          closeModalAndRefresh();
   115        }}
   116        title="Enable Bucket Quota"
   117        titleIcon={<BucketQuotaIcon />}
   118      >
   119        <form
   120          noValidate
   121          autoComplete="off"
   122          onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
   123            e.preventDefault();
   124            enableBucketEncryption();
   125          }}
   126        >
   127          <FormLayout withBorders={false} containerPadding={false}>
   128            <Switch
   129              value="bucket_quota"
   130              id="bucket_quota"
   131              name="bucket_quota"
   132              checked={quotaEnabled}
   133              onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
   134                setQuotaEnabled(event.target.checked);
   135              }}
   136              label={"Enabled"}
   137            />
   138            {quotaEnabled && (
   139              <InputBox
   140                id="quota_size"
   141                name="quota_size"
   142                onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
   143                  setQuotaSize(e.target.value);
   144                  if (!e.target.validity.valid) {
   145                    setValidInput(false);
   146                  } else {
   147                    setValidInput(true);
   148                  }
   149                }}
   150                label="Quota"
   151                value={quotaSize}
   152                required
   153                min="1"
   154                overlayObject={
   155                  <InputUnitMenu
   156                    id={"quota_unit"}
   157                    onUnitChange={(newValue) => {
   158                      setQuotaUnit(newValue);
   159                    }}
   160                    unitSelected={quotaUnit}
   161                    unitsList={k8sScalarUnitsExcluding(["Ki"])}
   162                    disabled={false}
   163                  />
   164                }
   165                error={!validInput ? "Please enter a valid quota" : ""}
   166              />
   167            )}
   168            <Grid item xs={12} sx={modalStyleUtils.modalButtonBar}>
   169              <Button
   170                id={"cancel"}
   171                type="button"
   172                variant="regular"
   173                disabled={loading}
   174                onClick={() => {
   175                  closeModalAndRefresh();
   176                }}
   177                label={"Cancel"}
   178              />
   179  
   180              <Button
   181                id={"save"}
   182                type="submit"
   183                variant="callAction"
   184                disabled={loading || !validInput}
   185                label={"Save"}
   186              />
   187            </Grid>
   188            {loading && (
   189              <Grid item xs={12}>
   190                <ProgressBar />
   191              </Grid>
   192            )}
   193          </FormLayout>
   194        </form>
   195      </ModalWrapper>
   196    );
   197  };
   198  
   199  export default EnableQuota;