function EditImage()

in frontend/src/containers/EditImage.tsx [37:356]


function EditImage() {
  const history = useHistory();
  const { t } = useTranslation();
  const { dashboardId, widgetId } = useParams<PathParams>();
  const { dashboard, loading } = useDashboard(dashboardId);
  const { setWidget, widget } = useWidget(dashboardId, widgetId);
  const { register, errors, handleSubmit } = useForm<FormValues>();
  const { file, loadingFile } = useImage(widget?.content.s3Key.raw);

  const [newImageFile, setNewImageFile] = useState<File | undefined>(undefined);
  const [imageUploading, setImageUploading] = useState(false);

  const supportedImageFileTypes = Object.values(StorageService.imageFileTypes);

  const { fullPreview, fullPreviewButton } = useFullPreview();

  const onSubmit = async (values: FormValues) => {
    if (!widget) {
      return;
    }
    try {
      setImageUploading(true);

      const s3Key = newImageFile
        ? await StorageService.uploadImage(newImageFile)
        : widget.content.s3Key.raw;

      const fileName = newImageFile
        ? newImageFile.name
        : widget.content.fileName;

      await BackendService.editWidget(
        dashboardId,
        widgetId,
        values.title,
        values.showTitle,
        {
          title: values.title,
          s3Key: {
            raw: s3Key,
          },
          fileName: fileName,
          imageAltText: values.altText,
          summary: values.summary,
          summaryBelow: values.summaryBelow,
        },
        widget.updatedAt
      );
      setImageUploading(false);

      history.push(`/admin/dashboard/edit/${dashboardId}`, {
        alert: {
          type: "success",
          message: t("EditImageScreen.ImageEditedSuccessfully", {
            title: values.title,
          }),
        },
      });
    } catch (err) {
      console.log(t("AddContentFailure"), err);
      setImageUploading(false);
    }
  };

  const onCancel = () => {
    history.push(`/admin/dashboard/edit/${dashboardId}`);
  };

  const handleChangeTitle = (event: React.FormEvent<HTMLInputElement>) => {
    if (widget) {
      setWidget({
        ...widget,
        content: {
          ...widget.content,
          title: (event.target as HTMLInputElement).value,
        },
      });
    }
  };

  const handleSummaryChange = (event: React.FormEvent<HTMLTextAreaElement>) => {
    if (widget) {
      setWidget({
        ...widget,
        content: {
          ...widget.content,
          summary: (event.target as HTMLTextAreaElement).value,
        },
      });
    }
  };

  const handleSummaryBelowChange = (
    event: React.FormEvent<HTMLInputElement>
  ) => {
    if (widget) {
      setWidget({
        ...widget,
        content: {
          ...widget.content,
          summaryBelow: (event.target as HTMLInputElement).checked,
        },
      });
    }
  };

  const handleShowTitleChange = (event: React.FormEvent<HTMLInputElement>) => {
    if (widget) {
      setWidget({
        ...widget,
        showTitle: (event.target as HTMLInputElement).checked,
        content: {
          ...widget.content,
        },
      });
    }
  };

  const onFileProcessed = (data: File) => {
    if (data) {
      setNewImageFile(data);
    }
  };

  const crumbs = [
    {
      label: t("Dashboards"),
      url: "/admin/dashboards",
    },
    {
      label: dashboard?.name,
      url: `/admin/dashboard/edit/${dashboardId}`,
    },
  ];

  useChangeBackgroundColor();

  if (!loading) {
    crumbs.push({
      label: t("EditImageScreen.EditImage"),
      url: "",
    });
  }

  return (
    <>
      <Breadcrumbs crumbs={crumbs} />

      {!widget || loading || loadingFile ? (
        <Spinner
          className="text-center margin-top-6"
          label={t("LoadingSpinnerLabel")}
        />
      ) : (
        <>
          <div className="grid-row width-desktop grid-gap">
            <div className="grid-col-6" hidden={fullPreview}>
              <PrimaryActionBar>
                <h1 className="margin-top-0">
                  {t("EditImageScreen.EditImage")}
                </h1>
                <form
                  className="usa-form usa-form--large"
                  onSubmit={handleSubmit(onSubmit)}
                >
                  <fieldset className="usa-fieldset">
                    {errors.title || errors.altText ? (
                      <Alert
                        type="error"
                        message={t("EditImageScreen.ResolveError")}
                        slim
                      ></Alert>
                    ) : (
                      ""
                    )}
                    <TextField
                      id="title"
                      name="title"
                      label={t("EditImageScreen.Title")}
                      hint={t("EditImageScreen.Hint")}
                      error={errors.title && t("EditImageScreen.TitleError")}
                      onChange={handleChangeTitle}
                      defaultValue={widget.content.title}
                      required
                      register={register}
                    />

                    <div className="usa-checkbox">
                      <input
                        className="usa-checkbox__input"
                        id="display-title"
                        type="checkbox"
                        name="showTitle"
                        defaultChecked={widget.showTitle}
                        onChange={handleShowTitleChange}
                        ref={register()}
                      />
                      <label
                        className="usa-checkbox__label"
                        htmlFor="display-title"
                      >
                        {t("EditImageScreen.ShowTitle")}
                      </label>
                    </div>

                    <div>
                      <FileInput
                        id="dataset"
                        name="image"
                        label={t("EditImageScreen.FileUpload")}
                        accept={supportedImageFileTypes.toString()}
                        loading={imageUploading}
                        register={register}
                        required
                        hint={<span>{t("EditImageScreen.FileHint")}</span>}
                        fileName={
                          newImageFile?.name
                            ? newImageFile.name
                            : widget.content.fileName
                        }
                        onFileProcessed={onFileProcessed}
                      />
                    </div>

                    <div>
                      <TextField
                        id="altText"
                        name="altText"
                        label={t("EditImageScreen.AltText")}
                        hint={t("EditImageScreen.TextHint")}
                        register={register}
                        error={errors.altText && t("EditImageScreen.TextError")}
                        required
                        defaultValue={widget.content.imageAltText}
                        multiline
                        rows={1}
                      />

                      <TextField
                        id="summary"
                        name="summary"
                        label={t("EditImageScreen.SummaryLabel")}
                        hint={
                          <>
                            {t("EditImageScreen.SummaryHint")}{" "}
                            <Link
                              target="_blank"
                              to={"/admin/markdown"}
                              external
                            >
                              {t("EditImageScreen.MarkdownLink")}
                            </Link>
                          </>
                        }
                        register={register}
                        onChange={handleSummaryChange}
                        multiline
                        defaultValue={widget.content.summary}
                        rows={5}
                      />
                      <div className="usa-checkbox">
                        <input
                          className="usa-checkbox__input"
                          id="summary-below"
                          type="checkbox"
                          name="summaryBelow"
                          defaultChecked={widget.content.summaryBelow}
                          onChange={handleSummaryBelowChange}
                          ref={register()}
                        />
                        <label
                          className="usa-checkbox__label"
                          htmlFor="summary-below"
                        >
                          {t("EditImageScreen.ToggleSummary")}
                        </label>
                      </div>
                    </div>
                  </fieldset>
                  <br />
                  <hr />
                  <Button disabled={imageUploading} type="submit">
                    {t("Save")}
                  </Button>
                  <Button
                    variant="unstyled"
                    className="text-base-dark hover:text-base-darker active:text-base-darkest"
                    type="button"
                    onClick={onCancel}
                  >
                    {t("Cancel")}
                  </Button>
                </form>
              </PrimaryActionBar>
            </div>
            <div className={fullPreview ? "grid-col-12" : "grid-col-6"}>
              <div hidden={false} className="sticky-preview">
                {fullPreviewButton}
                {loadingFile ? (
                  <Spinner
                    className="text-center margin-top-6"
                    label={t("LoadingSpinnerLabel")}
                  />
                ) : (
                  <ImageWidget
                    title={widget.showTitle ? widget.content.title : ""}
                    summary={widget.content.summary}
                    file={newImageFile ? newImageFile : file}
                    summaryBelow={widget.content.summaryBelow}
                    altText={widget.content.imageAltText}
                  />
                )}
              </div>
            </div>
          </div>
        </>
      )}
    </>
  );
}