@mui/material#Accordion TypeScript Examples

The following examples show how to use @mui/material#Accordion. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SidebarLink.tsx    From Cromwell with MIT License 6 votes vote down vote up
ExpansionPanel = withStyles({
    root: {
        padding: 0,
        boxShadow: 'none',
        '&:before': {
            display: 'none',
        },
        '&$expanded': {
            margin: 'auto',
        },
    },
    expanded: {},
})(Accordion)
Example #2
Source File: index.tsx    From genshin-optimizer with MIT License 6 votes vote down vote up
function FormulaCalc({ sectionKey, displayNs }: { displayNs: DisplaySub<NodeDisplay>, sectionKey: string }) {
  const { data } = useContext(DataContext)
  const header = usePromise(getDisplayHeader(data, sectionKey), [data, sectionKey])
  if (!header) return null
  if (Object.entries(displayNs).every(([_, node]) => node.isEmpty)) return null
  const { title, icon, action } = header
  return <CardDark sx={{ mb: 1 }}>
    <CardHeader avatar={icon && <ImgIcon size={2} sx={{ m: -1 }} src={icon} />} title={title} action={action} titleTypographyProps={{ variant: "subtitle1" }} />
    <Divider />
    <CardContent>
      {Object.entries(displayNs).map(([key, node]) =>
        !node.isEmpty && <Accordion sx={{ bgcolor: "contentLight.main" }} key={key}>
          <AccordionSummary expandIcon={<ExpandMore />}>
            <Typography><ColorText color={node.info.variant}>{KeyMap.get(node.info.key ?? "")}</ColorText> <strong>{valueString(node.value, node.unit)}</strong></Typography>
          </AccordionSummary>
          <AccordionDetails>
            {node.formulas.map((subform, i) => <Typography key={i}>{subform}</Typography>)}
          </AccordionDetails>
        </Accordion>)}
    </CardContent>
  </CardDark>
}
Example #3
Source File: itemAccordion.tsx    From Search-Next with GNU General Public License v3.0 5 votes vote down vote up
ItemAccordion: React.FC<ItemAccordionProps> = ({
  title,
  desc,
  action,
  expanded,
  onChange,
  children,
  disableDetailPadding = false,
}) => {
  return (
    <Accordion
      expanded={expanded}
      onChange={onChange}
      className={classNames(
        'rounded border shadow-none bg-white my-0',
        css`
          &::before {
            background-color: transparent !important;
          }
        `,
      )}
    >
      <AccordionSummary
        className=" transition hover:bg-gray-100"
        expandIcon={<ExpandMore />}
      >
        <div className="flex items-center justify-between w-full mr-2">
          <div>
            {title && <p className="mb-0 text-sm">{title}</p>}
            {desc && <p className="mb-0 text-xs text-gray-700">{desc}</p>}
          </div>
          <div className="flex items-center">{action}</div>
        </div>
      </AccordionSummary>
      <AccordionDetails className={classNames({ 'p-0': disableDetailPadding })}>
        {children}
      </AccordionDetails>
    </Accordion>
  );
}
Example #4
Source File: AddLifecycleModal.tsx    From console with GNU Affero General Public License v3.0 4 votes vote down vote up
AddLifecycleModal = ({
  open,
  closeModalAndRefresh,
  classes,
  bucketName,
}: IReplicationModal) => {
  const dispatch = useDispatch();
  const distributedSetup = useSelector(selDistSet);
  const [loadingTiers, setLoadingTiers] = useState<boolean>(true);
  const [tiersList, setTiersList] = useState<ITiersDropDown[]>([]);
  const [addLoading, setAddLoading] = useState(false);
  const [isVersioned, setIsVersioned] = useState<boolean>(false);
  const [prefix, setPrefix] = useState("");
  const [tags, setTags] = useState<string>("");
  const [storageClass, setStorageClass] = useState("");

  const [ilmType, setIlmType] = useState<string>("expiry");
  const [targetVersion, setTargetVersion] = useState<"current" | "noncurrent">(
    "current"
  );

  const [lifecycleDays, setLifecycleDays] = useState<string>("");
  const [isFormValid, setIsFormValid] = useState<boolean>(false);
  const [expiredObjectDM, setExpiredObjectDM] = useState<boolean>(false);
  const [loadingVersioning, setLoadingVersioning] = useState<boolean>(true);

  useEffect(() => {
    if (loadingTiers) {
      api
        .invoke("GET", `/api/v1/admin/tiers`)
        .then((res: ITierResponse) => {
          const tiersList: ITierElement[] | null = get(res, "items", []);

          if (tiersList !== null && tiersList.length >= 1) {
            const objList = tiersList.map((tier: ITierElement) => {
              const tierType = tier.type;
              const value = get(tier, `${tierType}.name`, "");

              return { label: value, value: value };
            });

            setTiersList(objList);
            if (objList.length > 0) {
              setStorageClass(objList[0].value);
            }
          }
          setLoadingTiers(false);
        })
        .catch((err: ErrorResponseHandler) => {
          setLoadingTiers(false);
        });
    }
  }, [loadingTiers]);

  useEffect(() => {
    let valid = true;

    if (ilmType !== "expiry") {
      if (storageClass === "") {
        valid = false;
      }
    }
    setIsFormValid(valid);
  }, [ilmType, lifecycleDays, storageClass]);

  useEffect(() => {
    if (loadingVersioning && distributedSetup) {
      api
        .invoke("GET", `/api/v1/buckets/${bucketName}/versioning`)
        .then((res: BucketVersioning) => {
          setIsVersioned(res.is_versioned);
          setLoadingVersioning(false);
        })
        .catch((err: ErrorResponseHandler) => {
          dispatch(setModalErrorSnackMessage(err));
          setLoadingVersioning(false);
        });
    }
  }, [loadingVersioning, dispatch, bucketName, distributedSetup]);

  const addRecord = () => {
    let rules = {};

    if (ilmType === "expiry") {
      let expiry: { [key: string]: number } = {};

      if (targetVersion === "current") {
        expiry["expiry_days"] = parseInt(lifecycleDays);
      } else {
        expiry["noncurrentversion_expiration_days"] = parseInt(lifecycleDays);
      }

      rules = {
        ...expiry,
      };
    } else {
      let transition: { [key: string]: number | string } = {};
      if (targetVersion === "current") {
        transition["transition_days"] = parseInt(lifecycleDays);
        transition["storage_class"] = storageClass;
      } else {
        transition["noncurrentversion_transition_days"] =
          parseInt(lifecycleDays);
        transition["noncurrentversion_transition_storage_class"] = storageClass;
      }

      rules = {
        ...transition,
      };
    }

    const lifecycleInsert = {
      type: ilmType,
      prefix,
      tags,
      expired_object_delete_marker: expiredObjectDM,
      ...rules,
    };

    api
      .invoke(
        "POST",
        `/api/v1/buckets/${bucketName}/lifecycle`,
        lifecycleInsert
      )
      .then(() => {
        setAddLoading(false);
        closeModalAndRefresh(true);
      })
      .catch((err: ErrorResponseHandler) => {
        setAddLoading(false);
        dispatch(setModalErrorSnackMessage(err));
      });
  };

  return (
    <ModalWrapper
      modalOpen={open}
      onClose={() => {
        closeModalAndRefresh(false);
      }}
      title="Add Lifecycle Rule"
      titleIcon={<LifecycleConfigIcon />}
    >
      {loadingTiers && (
        <Grid container className={classes.loadingBox}>
          <Grid item xs={12}>
            <LinearProgress />
          </Grid>
        </Grid>
      )}

      {!loadingTiers && (
        <form
          noValidate
          autoComplete="off"
          onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
            e.preventDefault();
            setAddLoading(true);
            addRecord();
          }}
        >
          <Grid container>
            <Grid item xs={12} className={classes.formScrollable}>
              <Grid item xs={12}>
                <Grid container spacing={1}>
                  <Grid item xs={12}>
                    <RadioGroupSelector
                      currentSelection={ilmType}
                      id="ilm_type"
                      name="ilm_type"
                      label="Type of lifecycle"
                      onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
                        setIlmType(e.target.value as string);
                      }}
                      selectorOptions={[
                        { value: "expiry", label: "Expiry" },
                        { value: "transition", label: "Transition" },
                      ]}
                    />
                  </Grid>
                  {isVersioned && (
                    <Grid item xs={12}>
                      <SelectWrapper
                        value={targetVersion}
                        id="object_version"
                        name="object_version"
                        label="Object Version"
                        onChange={(e) => {
                          setTargetVersion(
                            e.target.value as "current" | "noncurrent"
                          );
                        }}
                        options={[
                          { value: "current", label: "Current Version" },
                          { value: "noncurrent", label: "Non-Current Version" },
                        ]}
                      />
                    </Grid>
                  )}

                  <Grid item xs={12}>
                    <InputBoxWrapper
                      id="expiry_days"
                      name="expiry_days"
                      onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                        if (e.target.validity.valid) {
                          setLifecycleDays(e.target.value);
                        }
                      }}
                      pattern={"[0-9]*"}
                      label="After"
                      value={lifecycleDays}
                      overlayObject={
                        <InputUnitMenu
                          id={"expire-current-unit"}
                          unitSelected={"days"}
                          unitsList={[{ label: "Days", value: "days" }]}
                          disabled={true}
                        />
                      }
                    />
                  </Grid>

                  {ilmType === "expiry" ? (
                    <Fragment></Fragment>
                  ) : (
                    <Fragment>
                      <Grid item xs={12}>
                        <SelectWrapper
                          label="To Tier"
                          id="storage_class"
                          name="storage_class"
                          value={storageClass}
                          onChange={(e: SelectChangeEvent<string>) => {
                            setStorageClass(e.target.value as string);
                          }}
                          options={tiersList}
                        />
                      </Grid>
                    </Fragment>
                  )}
                  <Grid item xs={12} className={classes.formFieldRowFilter}>
                    <Accordion>
                      <AccordionSummary>
                        <Typography>Filters</Typography>
                      </AccordionSummary>
                      <AccordionDetails>
                        <Grid item xs={12}>
                          <InputBoxWrapper
                            id="prefix"
                            name="prefix"
                            onChange={(
                              e: React.ChangeEvent<HTMLInputElement>
                            ) => {
                              setPrefix(e.target.value);
                            }}
                            label="Prefix"
                            value={prefix}
                          />
                        </Grid>
                        <Grid item xs={12}>
                          <QueryMultiSelector
                            name="tags"
                            label="Tags"
                            elements={""}
                            onChange={(vl: string) => {
                              setTags(vl);
                            }}
                            keyPlaceholder="Tag Key"
                            valuePlaceholder="Tag Value"
                            withBorder
                          />
                        </Grid>
                      </AccordionDetails>
                    </Accordion>
                  </Grid>
                  {ilmType === "expiry" && targetVersion === "noncurrent" && (
                    <Grid item xs={12} className={classes.formFieldRowFilter}>
                      <Accordion>
                        <AccordionSummary>
                          <Typography>Advanced</Typography>
                        </AccordionSummary>
                        <AccordionDetails>
                          <Grid item xs={12}>
                            <FormSwitchWrapper
                              value="expired_delete_marker"
                              id="expired_delete_marker"
                              name="expired_delete_marker"
                              checked={expiredObjectDM}
                              onChange={(
                                event: React.ChangeEvent<HTMLInputElement>
                              ) => {
                                setExpiredObjectDM(event.target.checked);
                              }}
                              label={"Expire Delete Marker"}
                              description={
                                "Remove the reference to the object if no versions are left"
                              }
                            />
                          </Grid>
                        </AccordionDetails>
                      </Accordion>
                    </Grid>
                  )}
                </Grid>
              </Grid>
            </Grid>
            <Grid item xs={12} className={classes.modalButtonBar}>
              <Button
                type="button"
                variant="outlined"
                color="primary"
                disabled={addLoading}
                onClick={() => {
                  closeModalAndRefresh(false);
                }}
              >
                Cancel
              </Button>
              <Button
                type="submit"
                variant="contained"
                color="primary"
                disabled={addLoading || !isFormValid}
              >
                Save
              </Button>
            </Grid>
            {addLoading && (
              <Grid item xs={12}>
                <LinearProgress />
              </Grid>
            )}
          </Grid>
        </form>
      )}
    </ModalWrapper>
  );
}
Example #5
Source File: EditLifecycleConfiguration.tsx    From console with GNU Affero General Public License v3.0 4 votes vote down vote up
EditLifecycleConfiguration = ({
  classes,
  closeModalAndRefresh,
  selectedBucket,
  lifecycleRule,
  open,
}: IAddUserContentProps) => {
  const dispatch = useDispatch();
  const [loadingTiers, setLoadingTiers] = useState<boolean>(true);
  const [addLoading, setAddLoading] = useState<boolean>(false);
  const [tags, setTags] = useState<string>("");
  const [enabled, setEnabled] = useState<boolean>(false);
  const [tiersList, setTiersList] = useState<ITiersDropDown[]>([]);
  const [prefix, setPrefix] = useState("");
  const [storageClass, setStorageClass] = useState("");
  const [NCTransitionSC, setNCTransitionSC] = useState("");
  const [expiredObjectDM, setExpiredObjectDM] = useState<boolean>(false);
  const [NCExpirationDays, setNCExpirationDays] = useState<string>("0");
  const [NCTransitionDays, setNCTransitionDays] = useState<string>("0");
  const [ilmType, setIlmType] = useState<string>("expiry");
  const [expiryDays, setExpiryDays] = useState<string>("0");
  const [transitionDays, setTransitionDays] = useState<string>("0");
  const [isFormValid, setIsFormValid] = useState<boolean>(false);

  useEffect(() => {
    if (loadingTiers) {
      api
        .invoke("GET", `/api/v1/admin/tiers`)
        .then((res: ITierResponse) => {
          const tiersList: ITierElement[] | null = get(res, "items", []);

          if (tiersList !== null && tiersList.length >= 1) {
            const objList = tiersList.map((tier: ITierElement) => {
              const tierType = tier.type;
              const value = get(tier, `${tierType}.name`, "");

              return { label: value, value: value };
            });

            setTiersList(objList);
            if (objList.length > 0) {
              setStorageClass(objList[0].value);
            }
          }
          setLoadingTiers(false);
        })
        .catch((err: ErrorResponseHandler) => {
          setLoadingTiers(false);
        });
    }
  }, [loadingTiers]);

  useEffect(() => {
    let valid = true;

    if (ilmType !== "expiry") {
      if (storageClass === "") {
        valid = false;
      }
    }
    setIsFormValid(valid);
  }, [ilmType, expiryDays, transitionDays, storageClass]);

  useEffect(() => {
    if (lifecycleRule.status === "Enabled") {
      setEnabled(true);
    }

    let transitionMode = false;

    if (lifecycleRule.transition) {
      if (
        lifecycleRule.transition.days &&
        lifecycleRule.transition.days !== 0
      ) {
        setTransitionDays(lifecycleRule.transition.days.toString());
        setIlmType("transition");
        transitionMode = true;
      }
      if (
        lifecycleRule.transition.noncurrent_transition_days &&
        lifecycleRule.transition.noncurrent_transition_days !== 0
      ) {
        setNCTransitionDays(
          lifecycleRule.transition.noncurrent_transition_days.toString()
        );
        setIlmType("transition");
        transitionMode = true;
      }

      // Fallback to old rules by date
      if (
        lifecycleRule.transition.date &&
        lifecycleRule.transition.date !== "0001-01-01T00:00:00Z"
      ) {
        setIlmType("transition");
        transitionMode = true;
      }
    }

    if (lifecycleRule.expiration) {
      if (
        lifecycleRule.expiration.days &&
        lifecycleRule.expiration.days !== 0
      ) {
        setExpiryDays(lifecycleRule.expiration.days.toString());
        setIlmType("expiry");
        transitionMode = false;
      }
      if (
        lifecycleRule.expiration.noncurrent_expiration_days &&
        lifecycleRule.expiration.noncurrent_expiration_days !== 0
      ) {
        setNCExpirationDays(
          lifecycleRule.expiration.noncurrent_expiration_days.toString()
        );
        setIlmType("expiry");
        transitionMode = false;
      }

      // Fallback to old rules by date
      if (
        lifecycleRule.expiration.date &&
        lifecycleRule.expiration.date !== "0001-01-01T00:00:00Z"
      ) {
        setIlmType("expiry");
        transitionMode = false;
      }
    }

    // Transition fields
    if (transitionMode) {
      setStorageClass(lifecycleRule.transition?.storage_class || "");
      setNCTransitionDays(
        lifecycleRule.transition?.noncurrent_transition_days?.toString() || "0"
      );
      setNCTransitionSC(
        lifecycleRule.transition?.noncurrent_storage_class || ""
      );
    } else {
      // Expiry fields
      setNCExpirationDays(
        lifecycleRule.expiration?.noncurrent_expiration_days?.toString() || "0"
      );
    }

    setExpiredObjectDM(!!lifecycleRule.expiration?.delete_marker);
    setPrefix(lifecycleRule.prefix || "");

    if (lifecycleRule.tags) {
      const tgs = lifecycleRule.tags.reduce(
        (stringLab: string, currItem: any, index: number) => {
          return `${stringLab}${index !== 0 ? "&" : ""}${currItem.key}=${
            currItem.value
          }`;
        },
        ""
      );

      setTags(tgs);
    }
  }, [lifecycleRule]);

  const saveRecord = (event: React.FormEvent) => {
    event.preventDefault();

    if (addLoading) {
      return;
    }
    setAddLoading(true);
    if (selectedBucket !== null && lifecycleRule !== null) {
      let rules = {};

      if (ilmType === "expiry") {
        let expiry: { [key: string]: number } = {};

        if (
          lifecycleRule.expiration?.days &&
          lifecycleRule.expiration?.days > 0
        ) {
          expiry["expiry_days"] = parseInt(expiryDays);
        }
        if (lifecycleRule.expiration?.noncurrent_expiration_days) {
          expiry["noncurrentversion_expiration_days"] =
            parseInt(NCExpirationDays);
        }

        rules = {
          ...expiry,
        };
      } else {
        let transition: { [key: string]: number | string } = {};

        if (
          lifecycleRule.expiration?.days &&
          lifecycleRule.expiration?.days > 0
        ) {
          transition["transition_days"] = parseInt(expiryDays);
          transition["storage_class"] = storageClass;
        }
        if (lifecycleRule.expiration?.noncurrent_expiration_days) {
          transition["noncurrentversion_transition_days"] =
            parseInt(NCExpirationDays);
          transition["noncurrentversion_transition_storage_class"] =
            NCTransitionSC;
        }

        rules = {
          ...transition,
        };
      }

      const lifecycleUpdate = {
        type: ilmType,
        disable: !enabled,
        prefix,
        tags,
        expired_object_delete_marker: expiredObjectDM,
        ...rules,
      };

      api
        .invoke(
          "PUT",
          `/api/v1/buckets/${selectedBucket}/lifecycle/${lifecycleRule.id}`,
          lifecycleUpdate
        )
        .then((res) => {
          setAddLoading(false);
          closeModalAndRefresh(true);
        })
        .catch((err: ErrorResponseHandler) => {
          setAddLoading(false);
          dispatch(setModalErrorSnackMessage(err));
        });
    }
  };

  return (
    <ModalWrapper
      onClose={() => {
        closeModalAndRefresh(false);
      }}
      modalOpen={open}
      title={"Edit Lifecycle Configuration"}
      titleIcon={<LifecycleConfigIcon />}
    >
      <form
        noValidate
        autoComplete="off"
        onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
          saveRecord(e);
        }}
      >
        <Grid container>
          <Grid item xs={12} className={classes.formScrollable}>
            <Grid container spacing={1}>
              <Grid item xs={12}>
                <InputBoxWrapper
                  id="id"
                  name="id"
                  label="Id"
                  value={lifecycleRule.id}
                  onChange={() => {}}
                  disabled
                />
              </Grid>
              <Grid item xs={12}>
                <FormSwitchWrapper
                  label="Status"
                  indicatorLabels={["Enabled", "Disabled"]}
                  checked={enabled}
                  value={"user_enabled"}
                  id="rule_status"
                  name="rule_status"
                  onChange={(e) => {
                    setEnabled(e.target.checked);
                  }}
                />
              </Grid>
              <Grid item xs={12}>
                <RadioGroupSelector
                  currentSelection={ilmType}
                  id="rule_type"
                  name="rule_type"
                  label="Rule Type"
                  selectorOptions={[
                    { value: "expiry", label: "Expiry" },
                    { value: "transition", label: "Transition" },
                  ]}
                  onChange={() => {}}
                  disableOptions
                />
              </Grid>
              {ilmType === "expiry" && lifecycleRule.expiration?.days && (
                <Grid item xs={12}>
                  <InputBoxWrapper
                    type="number"
                    id="expiry_days"
                    name="expiry_days"
                    onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                      setExpiryDays(e.target.value);
                    }}
                    label="Expiry Days"
                    value={expiryDays}
                    min="0"
                  />
                </Grid>
              )}

              {ilmType === "expiry" &&
                lifecycleRule.expiration?.noncurrent_expiration_days && (
                  <Grid item xs={12}>
                    <InputBoxWrapper
                      type="number"
                      id="noncurrentversion_expiration_days"
                      name="noncurrentversion_expiration_days"
                      onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                        setNCExpirationDays(e.target.value);
                      }}
                      label="Non-current Expiration Days"
                      value={NCExpirationDays}
                      min="0"
                    />
                  </Grid>
                )}
              {ilmType === "transition" && lifecycleRule.transition?.days && (
                <Fragment>
                  <Grid item xs={12}>
                    <InputBoxWrapper
                      type="number"
                      id="transition_days"
                      name="transition_days"
                      onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                        setTransitionDays(e.target.value);
                      }}
                      label="Transition Days"
                      value={transitionDays}
                      min="0"
                    />
                  </Grid>

                  <Grid item xs={12}>
                    <SelectWrapper
                      label="Storage Class"
                      id="storage_class"
                      name="storage_class"
                      value={storageClass}
                      onChange={(e: SelectChangeEvent<string>) => {
                        setStorageClass(e.target.value as string);
                      }}
                      options={tiersList}
                    />
                  </Grid>
                </Fragment>
              )}

              {ilmType === "transition" &&
                lifecycleRule.transition?.noncurrent_transition_days && (
                  <Fragment>
                    <Grid item xs={12}>
                      <InputBoxWrapper
                        type="number"
                        id="noncurrentversion_transition_days"
                        name="noncurrentversion_transition_days"
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                          setNCTransitionDays(e.target.value);
                        }}
                        label="Non-current Transition Days"
                        value={NCTransitionDays}
                        min="0"
                      />
                    </Grid>

                    <Grid item xs={12}>
                      <InputBoxWrapper
                        id="noncurrentversion_t_SC"
                        name="noncurrentversion_t_SC"
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                          setNCTransitionSC(e.target.value);
                        }}
                        placeholder="Set Non-current Version Transition Storage Class"
                        label="Non-current Version Transition Storage Class"
                        value={NCTransitionSC}
                      />
                    </Grid>
                  </Fragment>
                )}
              <Grid item xs={12} className={classes.formFieldRowAccordion}>
                <Accordion>
                  <AccordionSummary>
                    <Typography>Filters</Typography>
                  </AccordionSummary>

                  <AccordionDetails>
                    <Grid item xs={12}>
                      <InputBoxWrapper
                        id="prefix"
                        name="prefix"
                        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                          setPrefix(e.target.value);
                        }}
                        label="Prefix"
                        value={prefix}
                      />
                    </Grid>
                    <Grid item xs={12}>
                      <QueryMultiSelector
                        name="tags"
                        label="Tags"
                        elements={tags}
                        onChange={(vl: string) => {
                          setTags(vl);
                        }}
                        keyPlaceholder="Tag Key"
                        valuePlaceholder="Tag Value"
                        withBorder
                      />
                    </Grid>
                  </AccordionDetails>
                </Accordion>
              </Grid>
              {ilmType === "expiry" &&
                lifecycleRule.expiration?.noncurrent_expiration_days && (
                  <Grid item xs={12} className={classes.formFieldRowAccordion}>
                    <Accordion>
                      <AccordionSummary>
                        <Typography>Advanced</Typography>
                      </AccordionSummary>

                      <AccordionDetails>
                        <Grid item xs={12}>
                          <FormSwitchWrapper
                            value="expired_delete_marker"
                            id="expired_delete_marker"
                            name="expired_delete_marker"
                            checked={expiredObjectDM}
                            onChange={(
                              event: React.ChangeEvent<HTMLInputElement>
                            ) => {
                              setExpiredObjectDM(event.target.checked);
                            }}
                            label={"Expired Object Delete Marker"}
                          />
                        </Grid>
                      </AccordionDetails>
                    </Accordion>
                  </Grid>
                )}
            </Grid>
          </Grid>
          <Grid item xs={12} className={classes.modalButtonBar}>
            <Button
              type="button"
              variant="outlined"
              color="primary"
              disabled={addLoading}
              onClick={() => {
                closeModalAndRefresh(false);
              }}
            >
              Cancel
            </Button>
            <Button
              type="submit"
              variant="contained"
              color="primary"
              disabled={addLoading || !isFormValid}
            >
              Save
            </Button>
          </Grid>
          {addLoading && (
            <Grid item xs={12}>
              <LinearProgress />
            </Grid>
          )}
        </Grid>
      </form>
    </ModalWrapper>
  );
}
Example #6
Source File: BlockEditor.tsx    From NekoMaid with MIT License 4 votes vote down vote up
BlockEditor: React.FC = () => {
  const theme = useTheme()
  const plugin = usePlugin()
  const his = useHistory()
  const loc = useLocation()
  const globalData = useGlobalData()
  const drawerWidth = useDrawerWidth()
  const [block, setBlock] = useState<Block>()
  const [types, setTypes] = useState<string[]>([])
  const [worlds, setWorlds] = useState<string[]>([])
  const params = { world: '', x: 0, y: 0, z: 0 }
  if (loc.pathname.startsWith('/NekoMaid/block/')) {
    const arr = loc.pathname.split('/')
    if (arr.length > 6) {
      params.world = arr[3]
      params.x = +arr[4]
      params.y = +arr[5]
      params.z = +arr[6]
    } else his.push('/NekoMaid/block')
  }
  useEffect(() => {
    const off = plugin.emit('item:blocks', (types: string[], worlds: string[]) => {
      setTypes(types)
      setWorlds(worlds)
    })
      .on('block:select', (world, x, y, z) => his.push(`/NekoMaid/block/${world}/${x}/${y}/${z}`))
    return () => void off()
  }, [])
  const update = () => {
    if (params.world) {
      plugin.emit('block:fetch', (block: Block) => {
        if (!block) {
          failed()
          his.push('/NekoMaid/block')
          return
        }
        if (globalData.hasNBTAPI && block.nbt) block.nbt = stringify(parse(block.nbt), { pretty: true })
        setBlock(block)
      }, params.world, params.x, params.y, params.z)
    }
  }
  const updateWithAction = (res: boolean) => {
    action(res)
    update()
  }
  useEffect(update, [params.world, params.x, params.y, params.z])
  return <Box sx={{ minHeight: '100%', py: 3 }}>
    <Toolbar />
    <Container maxWidth={false}>
      <Grid container spacing={3} sx={{ width: { sm: `calc(100vw - ${drawerWidth}px - ${theme.spacing(3)})` } }}>
        <Grid item lg={6} md={12} xl={6} xs={12}>
          <Card sx={{ '& .CodeMirror-dialog, .CodeMirror-scrollbar-filler': { backgroundColor: theme.palette.background.paper + '!important' } }}>
            <CardHeader
              title={lang.blockEditor.title}
              sx={{ position: 'relative' }}
              action={<Box sx={cardActionStyles}>
                <IconButton
                  size='small'
                  disabled={!block || (!block.data && !block.nbt)}
                  onClick={() => block && plugin.emit('block:save', (res: boolean) => {
                    action(res)
                    update()
                  }, params.world, params.x, params.y, params.z, block.nbt || null, block.data || null)}
                ><Save /></IconButton>
                <IconButton
                  size='small'
                  disabled={!block}
                  onClick={() => {
                    update()
                    success()
                  }}
                ><Refresh /></IconButton>
              </Box>}
            />
            <Divider />
            {block
              ? <>
                <CardContent sx={{ display: 'flex', width: '100%', justifyContent: 'center' }}>
                  <ItemViewer item={{ type: block.type }} />
                  <Autocomplete
                    options={types}
                    sx={{ maxWidth: 300, marginLeft: 1, flexGrow: 1 }}
                    value={block.type}
                    onChange={(_, it) => it && plugin.emit('block:type', (res: boolean) => {
                      action(res)
                      update()
                    }, params.world, params.x, params.y, params.z, (block.type = it))}
                    getOptionLabel={it => {
                      const locatedName = getName(it.toLowerCase())
                      return (locatedName ? locatedName + ' ' : '') + it
                    }}
                    renderInput={(params) => <TextField {...params} label={lang.itemEditor.itemType} size='small' variant='standard' />}
                  />
                </CardContent>
                {block.data != null && <Accordion sx={{ '&::before': { opacity: '1!important' } }} disableGutters>
                  <AccordionSummary expandIcon={<ExpandMore />}><Typography>{lang.data}</Typography></AccordionSummary>
                  <AccordionDetails sx={{ padding: 0, '& .CodeMirror': { width: '100%', height: 350 } }}>
                    <UnControlled
                      value={block.data}
                      options={{
                        mode: 'javascript',
                        phrases: lang.codeMirrorPhrases,
                        theme: theme.palette.mode === 'dark' ? 'material' : 'one-light'
                      }}
                      onChange={(_: any, __: any, data: string) => (block.data = data)}
                    />
                  </AccordionDetails>
                </Accordion>}
                {block.nbt != null && <Accordion sx={{ '&::before': { opacity: '1!important', display: '!important' } }} disableGutters>
                  <AccordionSummary expandIcon={<ExpandMore />}><Typography>NBT</Typography></AccordionSummary>
                  <AccordionDetails sx={{ padding: 0, '& .CodeMirror': { width: '100%', height: 350 } }}>
                    <UnControlled
                      value={block.nbt}
                      options={{
                        mode: 'javascript',
                        phrases: lang.codeMirrorPhrases,
                        theme: theme.palette.mode === 'dark' ? 'material' : 'one-light'
                      }}
                      onChange={(_: any, __: any, data: string) => (block.nbt = data)}
                    />
                  </AccordionDetails>
                </Accordion>}
              </>
              : <CardContent>{worlds.length ? <BlockSelector worlds={worlds} /> : <Empty />}</CardContent>}
          </Card>
        </Grid>
        {block?.inventory?.length
          ? <Grid item lg={6} md={12} xl={6} xs={12}>
            <Card>
              <CardHeader
                title={minecraft[('container.' + block.inventoryType || '').toLowerCase()] || lang.blockEditor.container}
                sx={{ position: 'relative' }}
              />
              <Divider />
              <CardContent sx={{ whiteSpace: 'nowrap', overflowX: 'auto', textAlign: 'center' }}>
                {block.inventory.map((it, i) => <React.Fragment key={i}><ItemViewer
                  item={it}
                  data={{ type: InvType.BLOCK, solt: i, ...params }}
                  onDrag={() => plugin.emit('block:setItem', update, params.world, params.x, params.y, params.z, i, null, -1)}
                  onDrop={(item, obj) => plugin.emit('block:setItem', update, params.world, params.x, params.y, params.z, i,
                    JSON.stringify(item), compare(obj, params) ? obj.solt : -1)}
                  onEdit={item => item !== false && plugin.emit('block:setItem', updateWithAction, params.world, params.x, params.y,
                    params.z, i, item && JSON.stringify(item), -1)}
                />{!((i + 1) % 9) && <br />}</React.Fragment>)}
              </CardContent>
            </Card>
          </Grid>
          : undefined}
      </Grid>
    </Container>
  </Box>
}
Example #7
Source File: Dashboard.tsx    From NekoMaid with MIT License 4 votes vote down vote up
Dashboard: React.FC = () => {
  const plugin = usePlugin()
  const { version, hasGeoIP } = useGlobalData()
  const [status, setStatus] = useState<Status[]>([])
  const [current, setCurrent] = useState<CurrentStatus | undefined>()

  useEffect(() => {
    const offSetStatus = plugin.once('dashboard:info', setStatus)
    const offCurrent = plugin.on('dashboard:current', (data: CurrentStatus) => setCurrent(old => {
      if (old && isEqual(old.players, data.players)) data.players = old.players
      return data
    }))
    plugin.switchPage('dashboard')
    return () => {
      offSetStatus()
      offCurrent()
    }
  }, [])

  const playerCount = current?.players?.length || 0
  const prev = status[status.length - 1]?.players || 0
  const percent = (prev ? playerCount / prev - 1 : playerCount) * 100
  const tpsColor = !current || current.tps >= 18 ? green : current.tps >= 15 ? yellow : red
  return <Box sx={{ minHeight: '100%', py: 3 }}>
    <Toolbar />
    <Container maxWidth={false}>
      <Grid container spacing={3}>
        <Grid item lg={3} sm={6} xl={3} xs={12}>
          <TopCard
            title={lang.dashboard.version}
            content={current ? version : <Skeleton animation='wave' width={150} />}
            icon={<Handyman />}
            color={orange[600]}
          >
            <Box sx={{ pt: 2, display: 'flex', alignItems: 'flex-end' }}>
              {!current || current.behinds < 0
                ? <Refresh htmlColor={blue[900]} />
                : current?.behinds === 0
                  ? <Check htmlColor={green[900]} />
                  : <Update htmlColor={yellow[900]} />}
              <Typography color='textSecondary' variant='caption'>&nbsp;{!current || current.behinds === -3
                ? lang.dashboard.updateChecking
                : current.behinds < 0
                  ? <Link underline='hover' color='inherit' sx={{ cursor: 'pointer' }} onClick={() => {
                    toast(lang.dashboard.updateChecking)
                    plugin.emit('dashboard:checkUpdate')
                  }}>{lang.dashboard.updateFailed}</Link>
                  : current.behinds === 0 ? lang.dashboard.updated : lang.dashboard.behinds(current.behinds)}</Typography>
            </Box>
          </TopCard>
        </Grid>
        <Grid item lg={3} sm={6} xl={3} xs={12}>
          <TopCard
            title={lang.dashboard.onlinePlayers}
            content={current ? playerCount : <Skeleton animation='wave' width={150} />}
            icon={<People />}
            color={deepPurple[600]}
          >
            <Box sx={{ pt: 2, display: 'flex', alignItems: 'flex-end' }}>
              {percent === 0 ? <Remove color='primary' /> : percent < 0 ? <ArrowDownward color='error' /> : <ArrowUpward color='success' />}
              <Typography
                sx={{ color: (percent === 0 ? blue : percent < 0 ? red : green)[900], mr: 1 }}
                variant='body2'
              >{Math.abs(percent).toFixed(0)}%</Typography>
              <Typography color='textSecondary' variant='caption'>{lang.dashboard.lastHour}</Typography>
            </Box>
          </TopCard>
        </Grid>
        <Grid item lg={3} sm={6} xl={3} xs={12}>
          <TopCard
            title='TPS'
            content={current ? (current.tps === -1 ? '?' : current.tps.toFixed(2)) : <Skeleton animation='wave' width={150} />}
            icon={!current || current.tps >= 18 || current.tps === -1
              ? <SentimentVerySatisfied />
              : current.tps >= 15 ? <SentimentSatisfied /> : <SentimentDissatisfied />}
            color={tpsColor[600]}
          >
            <Box sx={{ pt: 2.1, display: 'flex', alignItems: 'flex-end' }}>
              <Typography
                sx={{ color: tpsColor[900], mr: 1 }}
                variant='body2'
              >{!current || current.mspt === -1 ? '?' : current.mspt.toFixed(2) + 'ms'}</Typography>
              <Typography color='textSecondary' variant='caption'>{lang.dashboard.mspt}</Typography>
            </Box>
          </TopCard>
        </Grid>
        <Grid item lg={3} sm={6} xl={3} xs={12}>
          <TopCard
            title={lang.dashboard.uptime}
            content={current ? <Uptime time={current.time} /> : <Skeleton animation='wave' width={150} />}
            icon={<AccessTime />}
            color={blue[600]}
          >
            <Box sx={{ pt: 2.7, display: 'flex', alignItems: 'center' }}>
              <Typography color='textSecondary' variant='caption' sx={{ marginRight: 1 }}>{lang.dashboard.memory}</Typography>
              <Tooltip title={current?.totalMemory ? prettyBytes(current.memory) + ' / ' + prettyBytes(current.totalMemory) : ''}>
                <LinearProgress
                  variant='determinate'
                  value={current?.totalMemory ? current.memory / current.totalMemory * 100 : 0}
                  sx={{ flex: '1' }}
                />
              </Tooltip>
            </Box>
          </TopCard>
        </Grid>
        <Grid item lg={8} md={12} xl={9} xs={12}>{useMemo(() => <Charts data={status} />, [status])}</Grid>
        <Grid item lg={4} md={12} xl={3} xs={12}><Players players={current?.players} /></Grid>
        {hasGeoIP && current?.players && typeof current.players[0] !== 'string' && <Grid item xs={12}>
          <Accordion TransitionProps={{ unmountOnExit: true }} disableGutters>
            <AccordionSummary expandIcon={<ExpandMore />}>
              <Typography>{lang.dashboard.playersDistribution}</Typography>
            </AccordionSummary>
            <Divider />
            <WorldMap players={current.players as Player[]} />
          </Accordion>
        </Grid>}
      </Grid>
    </Container>
  </Box>
}
Example #8
Source File: EntityEditor.tsx    From NekoMaid with MIT License 4 votes vote down vote up
EntityEditor: React.FC = () => {
  const theme = useTheme()
  const plugin = usePlugin()
  const his = useHistory()
  const loc = useLocation()
  const globalData = useGlobalData()
  const drawerWidth = useDrawerWidth()
  const [customName, setCustomName] = useState('')
  const [entity, setEntity] = useState<Entity>()
  let id: string | null = null
  if (loc.pathname.startsWith('/NekoMaid/entity/')) {
    const arr = loc.pathname.split('/')
    if (arr.length > 3) id = arr[3]
  }
  useEffect(() => {
    const off = plugin.on('entity:select', id => his.push('/NekoMaid/entity/' + id))
    return () => void off()
  }, [])
  const update = () => {
    if (id) {
      plugin.emit('entity:fetch', (entity: Entity) => {
        if (!entity) {
          failed()
          his.push('/NekoMaid/entity')
          return
        }
        if (globalData.hasNBTAPI && entity.nbt) entity.nbt = stringify(parse(entity.nbt), { pretty: true })
        setCustomName(entity.customName || '')
        setEntity(entity)
      }, id)
    }
  }
  const updateWithAction = (res: boolean) => {
    action(res)
    update()
  }
  useEffect(update, [id])
  return <Box sx={{ minHeight: '100%', py: 3 }}>
    <Toolbar />
    <Container maxWidth={false}>
      <Grid container spacing={3} sx={{ width: { sm: `calc(100vw - ${drawerWidth}px - ${theme.spacing(3)})` } }}>
        <Grid item lg={6} md={12} xl={6} xs={12}>
          <Card>
            <CardHeader
              title={(entity && minecraft['entity.minecraft.' + entity.type.toLowerCase()]) || lang.entityEditor.title}
              sx={{ position: 'relative' }}
              action={<Box sx={cardActionStyles}>
                <IconButton
                  size='small'
                  disabled={!entity}
                  onClick={() => entity && plugin.emit('entity:save', (res: boolean) => {
                    action(res)
                    update()
                  }, id, entity.nbt || null, customName || null)}
                ><Save /></IconButton>
                <IconButton
                  size='small'
                  disabled={!entity}
                  onClick={() => {
                    update()
                    success()
                  }}
                ><Refresh /></IconButton>
              </Box>}
            />
            <Divider />
            {entity
              ? <>
                <CardContent>
                  <Grid container>
                    <Grid item lg={6} md={6} xl={6} xs={12}>
                      <TextField
                        size='small'
                        label={lang.entityEditor.customName}
                        value={customName}
                        sx={{ width: '90%' }}
                        onChange={e => setCustomName(e.target.value)}
                      />
                    </Grid>
                    {values.map(it => <Grid item lg={6} md={6} xl={6} xs={12} key={it}>
                      <FormControlLabel
                        control={<Switch checked={(entity as any)[it]} />}
                        label={(lang.entityEditor as any)[it]}
                        onChange={(e: any) => plugin.emit('entity:set', (res: boolean) => {
                          action(res)
                          update()
                        }, id, it, e.target.checked)}
                      />
                    </Grid>)}
                  </Grid>
                </CardContent>
                {entity.nbt != null && <Accordion sx={{ '&::before': { opacity: '1!important' } }} disableGutters>
                  <AccordionSummary expandIcon={<ExpandMore />}><Typography>NBT</Typography></AccordionSummary>
                  <AccordionDetails sx={{
                    padding: 0,
                    '& .CodeMirror': { width: '100%', height: 350 },
                    '& .CodeMirror-dialog, .CodeMirror-scrollbar-filler': { backgroundColor: theme.palette.background.paper + '!important' }
                  }}>
                    <UnControlled
                      value={entity.nbt}
                      options={{
                        mode: 'javascript',
                        phrases: lang.codeMirrorPhrases,
                        theme: theme.palette.mode === 'dark' ? 'material' : 'one-light'
                      }}
                      onChange={(_: any, __: any, data: string) => (entity.nbt = data)}
                    />
                  </AccordionDetails>
                </Accordion>}
              </>
              : <CardContent><EntitySelector /></CardContent>}
          </Card>
        </Grid>
        {entity?.inventory?.length
          ? <Grid item lg={6} md={12} xl={6} xs={12}>
            <Card>
              <CardHeader
                title={lang.entityEditor.container}
                sx={{ position: 'relative' }}
              />
              <Divider />
              <CardContent sx={{ whiteSpace: 'nowrap', overflowX: 'auto', textAlign: 'center' }}>
                {entity.inventory.map((it, i) => <React.Fragment key={i}><ItemViewer
                  item={it}
                  data={{ type: InvType.ENTITY, solt: i, id }}
                  onDrag={() => plugin.emit('entity:setItem', update, id, i, null, -1)}
                  onDrop={(item, obj) => plugin.emit('entity:setItem', update, id, i, JSON.stringify(item),
                    obj?.type === InvType.ENTITY && obj.id === id ? obj.solt : -1)}
                  onEdit={item => item !== false && plugin.emit('entity:setItem', updateWithAction, id, i, item && JSON.stringify(item), -1)}
                />{!((i + 1) % 9) && <br />}</React.Fragment>)}
              </CardContent>
            </Card>
          </Grid>
          : undefined}
      </Grid>
    </Container>
  </Box>
}