All files / src/views/Search CDKFilter.tsx

0% Statements 0/32
0% Branches 0/24
0% Functions 0/8
0% Lines 0/30

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                                                                                                                                                                                                                         
import { FunctionComponent, useMemo } from "react";
import { RadioFilter } from "./RadioFilter";
import testIds from "./testIds";
import { useCdkMajor, useCdkType } from "./useSearchParam";
import { useUpdateSearchParam } from "./useUpdateSearchParam";
import { CatalogConstructFrameworkMeta } from "../../api/catalog-search";
import { CDKType, CDKTYPE_NAME_MAP } from "../../constants/constructs";
import { useSearchContext } from "../../contexts/Search";
 
type CDKOptions = Partial<{
  [key in CDKType]: CatalogConstructFrameworkMeta & {
    display: string;
    value: key;
  };
}>;
 
export const CDKFilter: FunctionComponent = () => {
  const cdkType = useCdkType();
  const cdkMajor = useCdkMajor();
 
  const updateSearch = useUpdateSearchParam();
 
  const searchAPI = useSearchContext()!;
 
  // Options with less than one package will be omitted
  const cdkOptions = useMemo(() => {
    const cdkTypes = searchAPI.constructFrameworks;
    const options = Object.entries(cdkTypes).reduce((opts, [name, meta]) => {
      if (meta.pkgCount < 1) {
        return opts;
      }
 
      return {
        ...opts,
        [name]: {
          display: CDKTYPE_NAME_MAP[name as CDKType],
          value: name,
          ...meta,
        },
      };
    }, {});
 
    return Object.keys(options).length ? (options as CDKOptions) : undefined;
  }, [searchAPI]);
 
  const majorsOptions = useMemo(() => {
    if (!cdkOptions || !cdkType) return undefined;
    const majorVersions = cdkOptions[cdkType]?.majorVersions;
 
    if (!majorVersions) return undefined;
 
    return [...majorVersions]
      .sort((a, b) => a - b)
      .map((value) => ({
        value: value.toString(),
        display: `${CDKTYPE_NAME_MAP[cdkType]} v${value}`,
      }));
  }, [cdkOptions, cdkType]);
 
  if (!cdkOptions) {
    return null;
  }
 
  const onCdkTypeChange = (type: string) => {
    const cdk = type as CDKType;
    updateSearch({ cdkType: type ? cdk : undefined, cdkMajor: undefined });
  };
 
  const onCdkMajorChange = (major: string) => {
    let majorNum: number | undefined = undefined;
 
    if (major) {
      majorNum = parseInt(major, 10);
    }
 
    updateSearch({ cdkMajor: majorNum });
  };
 
  return (
    <>
      <RadioFilter
        data-testid={testIds.cdkTypeFilter}
        hint="Choose the right CDK for your IaC technology: AWS CDK for AWS CloudFormation, CDKTF for Terraform, or CDK8s for Kubernetes."
        name="CDK Type"
        onValueChange={onCdkTypeChange}
        options={[
          { display: "Any CDK Type", value: "" },
          ...Object.values(cdkOptions),
        ]}
        value={cdkType ?? ""}
      />
      {/* No point in showing major versions if only a single one is available */}
      {!!(majorsOptions && majorsOptions.length > 1) && (
        <RadioFilter
          data-testid={testIds.cdkVersionFilter}
          hint="Choose the major version of the CDK you're using to see only constructs that will work with that version."
          name="CDK Major Version"
          onValueChange={onCdkMajorChange}
          options={[
            { display: "Any Major Version", value: "" },
            ...majorsOptions,
          ]}
          value={cdkMajor?.toString() ?? ""}
        />
      )}
    </>
  );
};