All files / src/components/forms WebTemplateSelect.tsx

0% Statements 0/38
0% Branches 0/28
0% Functions 0/13
0% Lines 0/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                                                                                                                                                                                                                                   
import React, { memo, useMemo } from "react";
import { SingleValue } from "react-select";
import {
  OptGroup,
  Option,
  Select,
  SelectCommonProps,
  OptionLabelWithInfo,
} from "ui/form/Select";
import type { WebTemplateInfo } from "shared/lib/webTemplates/types";
import { useAppSelector } from "store/hooks";
import l10n from "shared/lib/lang/l10n";
 
interface WebTemplateSelectProps extends SelectCommonProps {
  value?: string;
  onChange?: (newValue: string) => void;
}
 
const webTemplateFolderName = (template: string) =>
  template.split(/[\\/]/).pop() || template;
 
const webTemplateLabel = (template: WebTemplateInfo) =>
  template.name.trim() || webTemplateFolderName(template.id);
 
const webTemplatePlugin = (template: string) => {
  Iif (!template.startsWith("plugins/")) {
    return "";
  }
  return template.split(/[\\/]/).slice(0, -1).join("/");
};
 
const WebTemplateSelectComponent = ({
  value = "",
  onChange,
  ...selectProps
}: WebTemplateSelectProps) => {
  const webTemplates = useAppSelector((state) => state.webTemplates.templates);
  const defaultWebTemplateLabel = l10n("FIELD_DEFAULT_WEB_TEMPLATE_BINJGB");
 
  const options = useMemo<(Option | OptGroup)[]>(() => {
    const localOptions: Option[] = [
      { value: "", label: defaultWebTemplateLabel },
    ];
    const pluginOptions: Record<string, Option[]> = {};
 
    webTemplates.forEach((template) => {
      const option = {
        value: template.id,
        label: webTemplateLabel(template),
      };
      const plugin = webTemplatePlugin(template.id);
 
      if (plugin) {
        pluginOptions[plugin] = pluginOptions[plugin] || [];
        pluginOptions[plugin].push(option);
      } else {
        localOptions.push(option);
      }
    });
 
    return [
      ...localOptions,
      ...Object.entries(pluginOptions).map(([plugin, options]) => ({
        label: plugin,
        options,
      })),
    ];
  }, [defaultWebTemplateLabel, webTemplates]);
 
  const flatOptions = useMemo(
    () =>
      options.flatMap((option) =>
        "options" in option ? option.options : option,
      ),
    [options],
  );
 
  const currentValue =
    flatOptions.find((option) => option.value === value) ||
    (value
      ? {
          value,
          label: webTemplateFolderName(value),
        }
      : { value: "", label: defaultWebTemplateLabel });
 
  const onSelectChange = (newValue: SingleValue<Option>) => {
    onChange?.(newValue?.value || "");
  };
 
  return (
    <Select
      value={currentValue}
      options={options}
      onChange={onSelectChange}
      formatOptionLabel={(
        option: Option,
        { context }: { context: "menu" | "value" },
      ) => {
        return (
          <OptionLabelWithInfo info={context === "menu" ? option.value : ""}>
            {option.label}
          </OptionLabelWithInfo>
        );
      }}
      {...selectProps}
    />
  );
};
 
export const WebTemplateSelect = memo<WebTemplateSelectProps>(
  WebTemplateSelectComponent,
);