diff --git a/src/components/FeatureAttributes/FeatureAttributesConfiguration/FeatureAttributesConfiguration.stories.tsx b/src/components/FeatureAttributes/FeatureAttributesConfiguration/FeatureAttributesConfiguration.stories.tsx index 5fb8b5f..b670cab 100644 --- a/src/components/FeatureAttributes/FeatureAttributesConfiguration/FeatureAttributesConfiguration.stories.tsx +++ b/src/components/FeatureAttributes/FeatureAttributesConfiguration/FeatureAttributesConfiguration.stories.tsx @@ -15,7 +15,7 @@ const meta: Meta = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core", "synthesis"] }), withPadding, ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes diff --git a/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.stories.tsx b/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.stories.tsx index f085f33..20ec03b 100644 --- a/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.stories.tsx +++ b/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.stories.tsx @@ -22,7 +22,9 @@ const meta: Meta = { decorators: [withPadding], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, - args: {}, + args: { + purposes: ["core"], + }, }; const sampleFeatureAttributesIndex: FeatureAttributesIndex = { @@ -166,6 +168,24 @@ Default.args!.timeFeatureAtom = getInferFeatureAttributesParamsTimeFeatureAtom({ runRequiredAtom: defaultRunRequiredAtom, }); +const synthesisRunRequiredAtom = getInferFeatureAttributesRunRequiredFields(); +export const Synthesis: Story = { + args: { + activeFeatureAtom: + getFeatureAttributesActiveFeatureAtom(defaultActiveFeature), + paramsAtom: getInferFeatureAttributesParamsAtom({ + features: sampleFeatureAttributesIndex, + }), + purposes: ["core", "synthesis"], + runRequiredAtom: synthesisRunRequiredAtom, + }, +}; +Synthesis.args!.timeFeatureAtom = + getInferFeatureAttributesParamsTimeFeatureAtom({ + paramsAtom: Synthesis.args!.paramsAtom!, + runRequiredAtom: synthesisRunRequiredAtom, + }); + const noFeaturesRunRequiredAtom = getInferFeatureAttributesRunRequiredFields(); export const NoFeatures: Story = { args: { diff --git a/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.test.tsx b/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.test.tsx index f04122b..cf9358c 100644 --- a/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.test.tsx +++ b/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.test.tsx @@ -71,6 +71,7 @@ describe("FeaturesAttributesCompact", () => { , @@ -100,6 +101,7 @@ describe("FeaturesAttributesCompact", () => { , @@ -143,6 +145,7 @@ describe("FeaturesAttributesCompact", () => { , @@ -195,6 +198,7 @@ describe("FeaturesAttributesCompact", () => { , diff --git a/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.tsx b/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.tsx index 0ee147b..ec8e0bb 100644 --- a/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.tsx +++ b/src/components/FeatureAttributes/FeaturesAttributesCompact/FeaturesAttributesCompact.tsx @@ -36,6 +36,7 @@ import { InferFeatureAttributesRunRequiredFieldsAtom, useFeatureAttributesForm, } from "../hooks"; +import { IFeatureAttributePurposes } from "../types"; import { getFeatureAttributeConfigurationIssues, getInferFeatureAttributeParamsFormValuesOnSubmit, @@ -44,7 +45,7 @@ import { } from "../utils"; import { FeaturesAttributesCompactI18nBundle as i18n } from "./FeaturesAttributesCompact.i18n"; -export type FeaturesAttributesCompactProps = { +export type FeaturesAttributesCompactProps = IFeatureAttributePurposes & { activeFeatureAtom: FeatureAttributesActiveFeatureAtom; paramsAtom: InferFeatureAttributesParamsAtom; runRequiredAtom: InferFeatureAttributesRunRequiredFieldsAtom; @@ -56,9 +57,10 @@ export type FeaturesAttributesCompactProps = { * * ⚠️ This component relies heavily on Modal components, and is unsuited to Jupyter Notebook integrations. **/ -export const FeaturesAttributesCompact: FC = ( - props, -) => { +export const FeaturesAttributesCompact: FC = ({ + purposes, + ...props +}) => { const { t } = useTranslation(i18n.namespace); const { activeFeatureAtom, paramsAtom, timeFeatureAtom } = props; const activeFeature = useAtomValue(activeFeatureAtom); @@ -70,7 +72,7 @@ export const FeaturesAttributesCompact: FC = ( const [isCompact, setIsCompact] = useState(true); return ( - +
= (props) => { const { t } = useTranslation(i18n.namespace); const theme = getTheme(); + const { purposes } = useContext(FeaturesAttributesContext); const activeFeature = useAtomValue(activeFeatureAtom); const params = useAtomValue(inferFeatureAttributesParamsAtom); const attributes = activeFeature @@ -233,7 +236,9 @@ const Configuration: FC = (props) => { if (!attributes) { throw new Error(`attributes are not defined for ${activeFeature}`); } - const issues = getFeatureAttributeConfigurationIssues(attributes); + const issues = getFeatureAttributeConfigurationIssues(attributes, { + purposes, + }); return (
diff --git a/src/components/FeatureAttributes/FeaturesAttributesContext/FeaturesAttributesContext.stories.decorators.tsx b/src/components/FeatureAttributes/FeaturesAttributesContext/FeaturesAttributesContext.stories.decorators.tsx index 09b4af7..5d15f46 100644 --- a/src/components/FeatureAttributes/FeaturesAttributesContext/FeaturesAttributesContext.stories.decorators.tsx +++ b/src/components/FeatureAttributes/FeaturesAttributesContext/FeaturesAttributesContext.stories.decorators.tsx @@ -5,10 +5,12 @@ import { } from "./FeaturesAttributesContext"; export const getFeaturesAttributesContextDecorator = - (props?: FeaturesAttributesContextProviderProps): Decorator => + ( + props?: Omit, + ): Decorator => (Story) => { return ( - + ); diff --git a/src/components/FeatureAttributes/FeaturesAttributesContext/FeaturesAttributesContext.tsx b/src/components/FeatureAttributes/FeaturesAttributesContext/FeaturesAttributesContext.tsx index 0f0090f..9f2cd73 100644 --- a/src/components/FeatureAttributes/FeaturesAttributesContext/FeaturesAttributesContext.tsx +++ b/src/components/FeatureAttributes/FeaturesAttributesContext/FeaturesAttributesContext.tsx @@ -1,11 +1,12 @@ import { ErrorBoundary, + FieldCheckboxProps, FieldRadiosProps, FieldSelectProps, FieldTextAreaProps, FieldTextProps, - FieldCheckboxProps, } from "@howso/react-tailwind-flowbite-components"; +import { ButtonProps } from "flowbite-react"; import { ComponentProps, Context, @@ -16,9 +17,9 @@ import { } from "react"; import { twMerge } from "tailwind-merge"; import { FeatureAttributesGroupBaseProps } from "../groups"; -import { ButtonProps } from "flowbite-react"; +import { IFeatureAttributePurposes } from "../types"; -export type IFeaturesAttributesContext = { +export type IFeaturesAttributesContext = IFeatureAttributePurposes & { buttonProps?: Partial; fieldCheckboxProps?: Partial; fieldRadiosProps?: Pick; @@ -34,16 +35,18 @@ export type IFeaturesAttributesContext = { >; }; +const defaultContext = { purposes: ["core"] } as IFeaturesAttributesContext; export const FeaturesAttributesContext: Context = - createContext({}); + createContext(defaultContext); -export type FeaturesAttributesContextProviderProps = { - children: ReactNode; - compact?: boolean; -}; +export type FeaturesAttributesContextProviderProps = + IFeatureAttributePurposes & { + children: ReactNode; + compact?: boolean; + }; export const FeaturesAttributesContextProvider: FC< FeaturesAttributesContextProviderProps -> = ({ children, compact }) => { +> = ({ children, compact, purposes }) => { const buttonProps: IFeaturesAttributesContext["buttonProps"] = useMemo( () => ({ size: compact ? "sm" : undefined }), [compact], @@ -138,6 +141,7 @@ export const FeaturesAttributesContextProvider: FC< fieldStackProps, fieldTextAreaProps, groupBaseProps, + purposes, }} > {children} diff --git a/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.stories.tsx b/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.stories.tsx index 90aa95e..a4e169f 100644 --- a/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.stories.tsx +++ b/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.stories.tsx @@ -23,7 +23,9 @@ const meta: Meta = { decorators: [withPadding], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, - args: {}, + args: { + purposes: ["core"], + }, }; const sampleFeatureAttributesIndex: FeatureAttributesIndex = { @@ -166,6 +168,24 @@ Default.args!.timeFeatureAtom = getInferFeatureAttributesParamsTimeFeatureAtom({ runRequiredAtom: defaultRunRequiredAtom, }); +const synthesisRunRequiredAtom = getInferFeatureAttributesRunRequiredFields(); +export const Synthesis: Story = { + args: { + activeFeatureAtom: getFeatureAttributesActiveFeatureAtom(), + optionsAtom: getFeatureAttributesOptionsAtom({}), + paramsAtom: getInferFeatureAttributesParamsAtom({ + features: sampleFeatureAttributesIndex, + }), + purposes: ["core", "synthesis"], + runRequiredAtom: synthesisRunRequiredAtom, + }, +}; +Synthesis.args!.timeFeatureAtom = + getInferFeatureAttributesParamsTimeFeatureAtom({ + paramsAtom: Synthesis.args!.paramsAtom!, + runRequiredAtom: synthesisRunRequiredAtom, + }); + const noFeaturesRunRequiredAtom = getInferFeatureAttributesRunRequiredFields(); export const NoFeatures: Story = { args: { diff --git a/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.test.tsx b/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.test.tsx index 6cbbbd7..a3c339f 100644 --- a/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.test.tsx +++ b/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.test.tsx @@ -69,6 +69,7 @@ describe("FeaturesAttributesRows", () => { activeFeatureAtom={getFeatureAttributesActiveFeatureAtom()} optionsAtom={getFeatureAttributesOptionsAtom({})} paramsAtom={inferFeatureAttributesParamsAtom} + purposes={["core", "synthesis"]} runRequiredAtom={runRequiredAtom} timeFeatureAtom={timeFeatureAtom} />, @@ -101,6 +102,7 @@ describe("FeaturesAttributesRows", () => { activeFeatureAtom={getFeatureAttributesActiveFeatureAtom()} optionsAtom={getFeatureAttributesOptionsAtom({})} paramsAtom={inferFeatureAttributesParamsAtom} + purposes={["core", "synthesis"]} runRequiredAtom={runRequiredAtom} timeFeatureAtom={timeFeatureAtom} />, diff --git a/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.tsx b/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.tsx index 38c9a2c..593d3ec 100644 --- a/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.tsx +++ b/src/components/FeatureAttributes/FeaturesAttributesRows/FeaturesAttributesRows.tsx @@ -10,7 +10,14 @@ import { } from "@howso/react-tailwind-flowbite-components"; import { Alert, Button, getTheme, Modal, Table, Tooltip } from "flowbite-react"; import { useAtom, useAtomValue, useSetAtom } from "jotai/react"; -import { ChangeEvent, FC, useCallback, useEffect, useState } from "react"; +import { + ChangeEvent, + FC, + useCallback, + useContext, + useEffect, + useState, +} from "react"; import { FormProvider, SubmitHandler, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { twMerge } from "tailwind-merge"; @@ -18,7 +25,10 @@ import { MapDependentFeatureAttributesIcon } from "../../Icons"; import { FeatureAttributeSample } from "../FeatureAttributeSample"; import { FeatureAttributesConfiguration } from "../FeatureAttributesConfiguration"; import { FeatureAttributesConfigurationIssues } from "../FeatureAttributesConfigurationIssues"; -import { FeaturesAttributesContextProvider } from "../FeaturesAttributesContext"; +import { + FeaturesAttributesContext, + FeaturesAttributesContextProvider, +} from "../FeaturesAttributesContext"; import { FeaturesAttributesDependencies } from "../FeaturesAttributesDependencies"; import { FeatureAttributeTypeField, @@ -33,6 +43,7 @@ import { InferFeatureAttributesRunRequiredFieldsAtom, useFeatureAttributesForm, } from "../hooks"; +import { IFeatureAttributePurposes } from "../types"; import { getFeatureAttributeConfigurationIssues, getInferFeatureAttributeParamsFormValuesOnSubmit, @@ -42,7 +53,7 @@ import { } from "../utils"; import { FeaturesAttributesRowsI18nBundle as i18n } from "./FeaturesAttributesRows.i18n"; -export type FeaturesAttributesRowsProps = { +export type FeaturesAttributesRowsProps = IFeatureAttributePurposes & { activeFeatureAtom: FeatureAttributesActiveFeatureAtom; runRequiredAtom: InferFeatureAttributesRunRequiredFieldsAtom; paramsAtom: InferFeatureAttributesParamsAtom; @@ -55,9 +66,10 @@ export type FeaturesAttributesRowsProps = { * * ⚠️ This component relies heavily on Modal components, and is unsuited to Jupyter Notebook integrations. **/ -export const FeaturesAttributesRows: FC = ( - props, -) => { +export const FeaturesAttributesRows: FC = ({ + purposes, + ...props +}) => { const { t } = useTranslation(i18n.namespace); const { activeFeatureAtom, paramsAtom, optionsAtom, timeFeatureAtom } = props; const activeFeature = useAtomValue(activeFeatureAtom); @@ -74,7 +86,7 @@ export const FeaturesAttributesRows: FC = ( }; return ( - +
@@ -144,6 +156,7 @@ const FeatureFields: FC = ({ }) => { const { t } = useTranslation(i18n.namespace); const theme = getTheme(); + const { purposes } = useContext(FeaturesAttributesContext); const setActiveFeature = useSetAtom(activeFeatureAtom); const setRunRequired = useSetAtom(runRequiredAtom); const [params, setParams] = useAtom(paramsAtom); @@ -162,7 +175,9 @@ const FeatureFields: FC = ({ }, [setRunRequired, setParams, params, feature], ); - const issues = getFeatureAttributeConfigurationIssues(attributes); + const issues = getFeatureAttributeConfigurationIssues(attributes, { + purposes, + }); return ( diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeAllowNullsField/FeatureAttributeAllowNullsField.test.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeAllowNullsField/FeatureAttributeAllowNullsField.test.tsx index e489903..143a3b1 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeAllowNullsField/FeatureAttributeAllowNullsField.test.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeAllowNullsField/FeatureAttributeAllowNullsField.test.tsx @@ -1,10 +1,10 @@ -import { render, screen, within } from "@testing-library/react"; import "@testing-library/jest-dom"; -import { FeatureAttributeAllowNullsField } from "./FeatureAttributeAllowNullsField"; -import { featureAttributeAllowNullsFieldName } from "./constants"; -import { useForm, FormProvider, UseFormProps } from "react-hook-form"; +import { render, screen, within } from "@testing-library/react"; import { FC, ReactNode } from "react"; +import { FormProvider, useForm, UseFormProps } from "react-hook-form"; import { FeaturesAttributesContextProvider } from "../../FeaturesAttributesContext"; +import { FeatureAttributeAllowNullsField } from "./FeatureAttributeAllowNullsField"; +import { featureAttributeAllowNullsFieldName } from "./constants"; describe("AllowNullsField", () => { it("should be rendered with a default value of true if not in form context", async () => { @@ -58,7 +58,7 @@ const Wrapper: FC<{ children: ReactNode; formProps?: UseFormProps }> = ({ }) => { const form = useForm(formProps); return ( - + {children} ); diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeAllowNullsField/FeatureAttributeAllowNullsField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeAllowNullsField/FeatureAttributeAllowNullsField.tsx index 78d3d56..a7e9828 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeAllowNullsField/FeatureAttributeAllowNullsField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeAllowNullsField/FeatureAttributeAllowNullsField.tsx @@ -1,12 +1,12 @@ +import { FieldCheckbox } from "@howso/react-tailwind-flowbite-components"; import { FC, useContext } from "react"; import { Controller, useFormContext } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { featureAttributeAllowNullsFieldLabel, featureAttributeAllowNullsFieldName, } from "./constants"; -import { FieldCheckbox } from "@howso/react-tailwind-flowbite-components"; -import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; -import { useTranslation } from "react-i18next"; import { FeatureAttributeAllowNullsFieldI18nBundle as i18n } from "./FeatureAttributeAllowNullsField.i18n"; export type FeatureAttributeAllowNullsFieldProps = Record; @@ -19,9 +19,15 @@ export const FeatureAttributeAllowNullsField: FC< FeatureAttributeAllowNullsFieldProps > = () => { const { t } = useTranslation(i18n.namespace); - const { fieldCheckboxProps } = useContext(FeaturesAttributesContext); + const { fieldCheckboxProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); + if (!purposes.includes("core")) { + return null; + } + return ( = ({ }) => { const form = useForm(formProps); return ( - + {children} ); diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeAllowedValuesField/FeatureAttributeAllowedValuesField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeAllowedValuesField/FeatureAttributeAllowedValuesField.tsx index 1a946dd..8ad183f 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeAllowedValuesField/FeatureAttributeAllowedValuesField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeAllowedValuesField/FeatureAttributeAllowedValuesField.tsx @@ -41,7 +41,10 @@ export const FeatureAttributeAllowedValuesField: FC< ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextAreaProps } = useContext(FeaturesAttributesContext); + const { fieldTextAreaProps, purposes } = useContext( + FeaturesAttributesContext, + ); + const allowedFeatureTypes: FeatureAttributes["type"][] = [ "nominal", "ordinal", @@ -54,7 +57,8 @@ export const FeatureAttributeAllowedValuesField: FC< if ( !featureType || !allowedFeatureTypes.includes(featureType) || - !allowedDataTypes.includes(dataType) + !allowedDataTypes.includes(dataType) || + !purposes.includes("core") ) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeCycleLengthField/FeatureAttributeCycleLengthField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeCycleLengthField/FeatureAttributeCycleLengthField.tsx index 1e09ccc..1d5b499 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeCycleLengthField/FeatureAttributeCycleLengthField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeCycleLengthField/FeatureAttributeCycleLengthField.tsx @@ -27,14 +27,15 @@ export const FeatureAttributeCycleLengthField: FC< FeatureAttributeCycleLengthProps > = ({ featureType, dataType, ...props }) => { const { t } = useTranslation(i18n.namespace); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); - const { fieldTextProps } = useContext(FeaturesAttributesContext); const allowedFeatureTypes: FeatureAttributes["type"][] = ["continuous"]; const allowedDataTypes: FeatureAttributes["data_type"][] = ["number"]; if ( !allowedFeatureTypes.includes(featureType) || - !allowedDataTypes.includes(dataType) + !allowedDataTypes.includes(dataType) || + !purposes.includes("core") ) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeDataTypeField/FeatureAttributeDataTypeField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeDataTypeField/FeatureAttributeDataTypeField.tsx index 4685c35..6969e31 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeDataTypeField/FeatureAttributeDataTypeField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeDataTypeField/FeatureAttributeDataTypeField.tsx @@ -24,8 +24,13 @@ export const FeatureAttributeDataTypeField: FC< FeatureAttributeDataTypeFieldProps > = ({ featureType, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldSelectProps } = useContext(FeaturesAttributesContext); + const { fieldSelectProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); + + if (!purposes.includes("core")) { + return null; + } + const dataType = form.getValues("data_type"); const required = true; diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeDateTimeFormatField/FeatureAttributeDateTimeFormatField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeDateTimeFormatField/FeatureAttributeDateTimeFormatField.tsx index dbb6eba..c60047e 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeDateTimeFormatField/FeatureAttributeDateTimeFormatField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeDateTimeFormatField/FeatureAttributeDateTimeFormatField.tsx @@ -26,13 +26,13 @@ export const FeatureAttributeDateTimeFormatField: FC< FeatureAttributeDateTimeFormatProps > = ({ dataType, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); const allowedDataTypes: FeatureAttributes["data_type"][] = [ "formatted_date_time", ]; - if (!allowedDataTypes.includes(dataType)) { + if (!allowedDataTypes.includes(dataType) || !purposes.includes("core")) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeDecimalPlacesField/FeatureAttributeDecimalPlacesField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeDecimalPlacesField/FeatureAttributeDecimalPlacesField.tsx index fc35136..901b319 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeDecimalPlacesField/FeatureAttributeDecimalPlacesField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeDecimalPlacesField/FeatureAttributeDecimalPlacesField.tsx @@ -29,14 +29,15 @@ export const FeatureAttributeDecimalPlacesField: FC< FeatureAttributeDecimalPlacesProps > = ({ featureType, dataType, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); const allowedFeatureTypes: FeatureAttributes["type"][] = ["continuous"]; const allowedDataTypes: FeatureAttributes["data_type"][] = ["number"]; if ( !allowedFeatureTypes.includes(featureType) || - !allowedDataTypes.includes(dataType) + !allowedDataTypes.includes(dataType) || + !purposes.includes("core") ) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeDerivedFeatureCodeField/FeatureAttributeDerivedFeatureCodeField.stories.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeDerivedFeatureCodeField/FeatureAttributeDerivedFeatureCodeField.stories.tsx index 6fcbe16..d50a7a9 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeDerivedFeatureCodeField/FeatureAttributeDerivedFeatureCodeField.stories.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeDerivedFeatureCodeField/FeatureAttributeDerivedFeatureCodeField.stories.tsx @@ -14,7 +14,7 @@ const meta: Meta = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeDerivedFeatureCodeField/FeatureAttributeDerivedFeatureCodeField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeDerivedFeatureCodeField/FeatureAttributeDerivedFeatureCodeField.tsx index d0478f1..7b9c600 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeDerivedFeatureCodeField/FeatureAttributeDerivedFeatureCodeField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeDerivedFeatureCodeField/FeatureAttributeDerivedFeatureCodeField.tsx @@ -1,11 +1,11 @@ -import { FC, useContext } from "react"; -import { useFormContext } from "react-hook-form"; -import { Trans, useTranslation } from "react-i18next"; import { FieldTextArea, FieldTextAreaProps, Link, } from "@howso/react-tailwind-flowbite-components"; +import { FC, useContext } from "react"; +import { useFormContext } from "react-hook-form"; +import { Trans, useTranslation } from "react-i18next"; import { twMerge } from "tailwind-merge"; import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { FeatureAttributeDerivedFeatureCodeFieldI18nBundle as i18n } from "./FeatureAttributeDerivedFeatureCodeField.i18n"; @@ -22,9 +22,15 @@ export const FeatureAttributeDerivedFeatureCodeField: FC< FeatureAttributeDerivedFeatureCodeProps > = (props) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextAreaProps } = useContext(FeaturesAttributesContext); + const { fieldTextAreaProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); + if (!purposes.includes("core")) { + return null; + } + return ( = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeIdFeatureField/FeatureAttributeIdFeatureField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeIdFeatureField/FeatureAttributeIdFeatureField.tsx index 6f417b7..58e62e1 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeIdFeatureField/FeatureAttributeIdFeatureField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeIdFeatureField/FeatureAttributeIdFeatureField.tsx @@ -21,7 +21,9 @@ export const FeatureAttributeIdFeatureField: FC< FeatureAttributeIdFeatureFieldProps > = ({ featureType, dataType }) => { const { t } = useTranslation(i18n.namespace); - const { fieldCheckboxProps } = useContext(FeaturesAttributesContext); + const { fieldCheckboxProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); const allowedFeatureTypes: FeatureAttributes["type"][] = ["nominal"]; @@ -32,7 +34,8 @@ export const FeatureAttributeIdFeatureField: FC< if ( !featureType || !allowedFeatureTypes.includes(featureType) || - !allowedDataTypes.includes(dataType) + !allowedDataTypes.includes(dataType) || + !purposes.includes("core") ) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.stories.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.stories.tsx index bbf1e43..8946b87 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.stories.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.stories.tsx @@ -14,7 +14,7 @@ const meta: Meta = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core", "synthesis"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.tsx index c5e6b07..afb0008 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.tsx @@ -29,14 +29,19 @@ export const FeatureAttributeIsSensitiveField: FC< FeatureAttributeIsSensitiveFieldProps > = ({ featureType, dataType }) => { const { t } = useTranslation(i18n.namespace); - const { fieldCheckboxProps } = useContext(FeaturesAttributesContext); + const { fieldCheckboxProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); if ( - !isFeatureAttributeSensitiveAttributeAvailable({ - type: featureType, - data_type: dataType, - }) + !isFeatureAttributeSensitiveAttributeAvailable( + { + type: featureType, + data_type: dataType, + }, + { purposes }, + ) ) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.utils.ts b/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.utils.ts index 3035687..2606cbc 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.utils.ts +++ b/src/components/FeatureAttributes/fields/FeatureAttributeIsSensitiveField/FeatureAttributeIsSensitiveField.utils.ts @@ -1,10 +1,16 @@ import { FeatureAttributes } from "@howso/engine"; +import { IFeatureAttributePurposes } from "../../types"; export const isFeatureAttributeSensitiveAttributeAvailable = ( attributes: | Partial> | undefined, + params: IFeatureAttributePurposes, ): boolean => { + if (!params.purposes.includes("synthesis")) { + return false; + } + if (!attributes) { return false; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeLocaleField/FeatureAttributeLocaleField.stories.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeLocaleField/FeatureAttributeLocaleField.stories.tsx index b4cc28a..4ffb9e3 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeLocaleField/FeatureAttributeLocaleField.stories.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeLocaleField/FeatureAttributeLocaleField.stories.tsx @@ -14,7 +14,7 @@ const meta: Meta = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeLocaleField/FeatureAttributeLocaleField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeLocaleField/FeatureAttributeLocaleField.tsx index a7c0af2..6916b24 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeLocaleField/FeatureAttributeLocaleField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeLocaleField/FeatureAttributeLocaleField.tsx @@ -27,14 +27,15 @@ export const FeatureAttributeLocaleField: FC< FeatureAttributeLocaleFieldProps > = ({ dataType, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); - const required = false; - if (dataType !== "formatted_date_time") { + if (dataType !== "formatted_date_time" || !purposes.includes("core")) { return null; } + const required = false; + return ( { const { t } = useTranslation(i18n.namespace); - const { fieldStackProps } = useContext(FeaturesAttributesContext); + const { fieldStackProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); - if (boundingMode !== "userDefined") { + if (!purposes.includes("core") || boundingMode !== "userDefined") { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeNullIsDependentField/FeatureAttributeNullIsDependentField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeNullIsDependentField/FeatureAttributeNullIsDependentField.tsx index 274522e..732febb 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeNullIsDependentField/FeatureAttributeNullIsDependentField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeNullIsDependentField/FeatureAttributeNullIsDependentField.tsx @@ -16,10 +16,12 @@ export const FeatureAttributeNullIsDependentField: FC< FeatureAttributeNullIsDependentFieldProps > = ({ dependentFeatures }) => { const { t } = useTranslation(i18n.namespace); - const { fieldCheckboxProps } = useContext(FeaturesAttributesContext); + const { fieldCheckboxProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); - if (!dependentFeatures?.length) { + if (!dependentFeatures?.length || !purposes.includes("core")) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeObservationalErrorField/FeatureAttributeObservationalErrorField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeObservationalErrorField/FeatureAttributeObservationalErrorField.tsx index 290f4be..ce50cb9 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeObservationalErrorField/FeatureAttributeObservationalErrorField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeObservationalErrorField/FeatureAttributeObservationalErrorField.tsx @@ -23,9 +23,13 @@ export const FeatureAttributeObservationalErrorField: FC< FeatureAttributeObservationalErrorFieldProps > = ({ featureType, dataType, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); + if (!purposes.includes("core")) { + return null; + } + const max = featureType === "nominal" ? 1 : undefined; return ( diff --git a/src/components/FeatureAttributes/fields/FeatureAttributePostProcessField/FeatureAttributePostProcessField.stories.tsx b/src/components/FeatureAttributes/fields/FeatureAttributePostProcessField/FeatureAttributePostProcessField.stories.tsx index 06cf0bd..43728a6 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributePostProcessField/FeatureAttributePostProcessField.stories.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributePostProcessField/FeatureAttributePostProcessField.stories.tsx @@ -14,7 +14,7 @@ const meta: Meta = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core", "synthesis"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, diff --git a/src/components/FeatureAttributes/fields/FeatureAttributePostProcessField/FeatureAttributePostProcessField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributePostProcessField/FeatureAttributePostProcessField.tsx index a1bbc63..8b5fa16 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributePostProcessField/FeatureAttributePostProcessField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributePostProcessField/FeatureAttributePostProcessField.tsx @@ -1,11 +1,11 @@ -import { FC, useContext } from "react"; -import { useFormContext } from "react-hook-form"; -import { Trans, useTranslation } from "react-i18next"; import { FieldTextArea, FieldTextAreaProps, Link, } from "@howso/react-tailwind-flowbite-components"; +import { FC, useContext } from "react"; +import { useFormContext } from "react-hook-form"; +import { Trans, useTranslation } from "react-i18next"; import { twMerge } from "tailwind-merge"; import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { FeatureAttributePostProcessFieldI18nBundle as i18n } from "./FeatureAttributePostProcessField.i18n"; @@ -20,9 +20,15 @@ export const FeatureAttributePostProcessField: FC< FeatureAttributePostProcessProps > = (props) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextAreaProps } = useContext(FeaturesAttributesContext); + const { fieldTextAreaProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); + if (!purposes.includes("core")) { + return null; + } + return ( = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeReservedBoundingModeField/FeatureAttributeReservedBoundingModeField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeReservedBoundingModeField/FeatureAttributeReservedBoundingModeField.tsx index 9dd2ed5..59f6d2c 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeReservedBoundingModeField/FeatureAttributeReservedBoundingModeField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeReservedBoundingModeField/FeatureAttributeReservedBoundingModeField.tsx @@ -20,7 +20,7 @@ export const FeatureAttributeReservedBoundingModeField: FC< FeatureAttributeReservedBoundingModeFieldProps > = ({ featureType, dataType, required = true, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldRadiosProps } = useContext(FeaturesAttributesContext); + const { fieldRadiosProps, purposes } = useContext(FeaturesAttributesContext); const registerOptions: RegisterOptions = useMemo( () => ({ @@ -37,7 +37,8 @@ export const FeatureAttributeReservedBoundingModeField: FC< if ( !featureType || !allowedFeatureTypes.includes(featureType) || - !allowedDataTypes.includes(dataType) + !allowedDataTypes.includes(dataType) || + !purposes.includes("core") ) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeReservedTightTimeBoundField/FeatureAttributeReservedTightTimeBoundField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeReservedTightTimeBoundField/FeatureAttributeReservedTightTimeBoundField.tsx index 62a15ec..2d9f53d 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeReservedTightTimeBoundField/FeatureAttributeReservedTightTimeBoundField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeReservedTightTimeBoundField/FeatureAttributeReservedTightTimeBoundField.tsx @@ -19,11 +19,17 @@ export const FeatureAttributeReservedTightTimeBoundField: FC< FeatureAttributeReservedTightTimeBoundFieldProps > = ({ featureType, isTimeFeature }) => { const { t } = useTranslation(i18n.namespace); - const { fieldCheckboxProps } = useContext(FeaturesAttributesContext); - + const { fieldCheckboxProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); - if (!featureType || featureType !== "continuous" || !isTimeFeature) { + if ( + !featureType || + featureType !== "continuous" || + !isTimeFeature || + !purposes.includes("core") + ) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeSignificantDigitsField/FeatureAttributeSignificantDigitsField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeSignificantDigitsField/FeatureAttributeSignificantDigitsField.tsx index e63d11a..f92e2cf 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeSignificantDigitsField/FeatureAttributeSignificantDigitsField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeSignificantDigitsField/FeatureAttributeSignificantDigitsField.tsx @@ -30,14 +30,15 @@ export const FeatureAttributeSignificantDigitsField: FC< FeatureAttributeSignificantDigitsFieldProps > = ({ featureType, dataType, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); const allowedFeatureTypes: FeatureAttributes["type"][] = ["continuous"]; const allowedDataTypes: FeatureAttributes["data_type"][] = ["number"]; if ( !allowedFeatureTypes.includes(featureType) || - !allowedDataTypes.includes(dataType) + !allowedDataTypes.includes(dataType) || + !purposes.includes("core") ) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeSubtypeField/FeatureAttributeSubtypeField.stories.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeSubtypeField/FeatureAttributeSubtypeField.stories.tsx index 4a37e70..712777b 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeSubtypeField/FeatureAttributeSubtypeField.stories.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeSubtypeField/FeatureAttributeSubtypeField.stories.tsx @@ -15,7 +15,7 @@ const meta: Meta = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core", "synthesis"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, @@ -47,7 +47,7 @@ export const CustomSubtype: Story = { getFormProviderDecorator({ defaultValues: { subtype: "My custom subtype " }, }), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core", "synthesis"] }), ], args: { dataType: "string", diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeSubtypeField/FeatureAttributeSubtypeField.test.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeSubtypeField/FeatureAttributeSubtypeField.test.tsx index 492a509..ba42736 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeSubtypeField/FeatureAttributeSubtypeField.test.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeSubtypeField/FeatureAttributeSubtypeField.test.tsx @@ -1,11 +1,11 @@ -import { render, screen } from "@testing-library/react"; import "@testing-library/jest-dom"; +import { render, screen } from "@testing-library/react"; +import { FC, ReactNode } from "react"; +import { FormProvider, useForm, UseFormProps } from "react-hook-form"; import { FeatureAttributeSubtypeField, featureAttributeSubtypeFieldLabel, } from ".."; -import { useForm, FormProvider, UseFormProps } from "react-hook-form"; -import { FC, ReactNode } from "react"; import { FeaturesAttributesContextProvider } from "../../FeaturesAttributesContext"; import { InferFeatureAttributeFormValues } from "../../utils"; @@ -172,7 +172,7 @@ const Wrapper: FC<{ }> = ({ children, formProps }) => { const form = useForm(formProps); return ( - + {children} = ({ ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); - const subtype = form.getValues("subtype"); - if (featureType === "continuous" || nonSensitive) { + if ( + featureType === "continuous" || + nonSensitive || + !purposes.includes("synthesis") + ) { return null; } + const subtype = form.getValues("subtype"); + const required = true; const isSubtypeValueInOptions = !!dataType && subtypes[dataType] && subtypes[dataType].includes(subtype); diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesDeltaMinMaxFields/FeatureAttributeTimeSeriesDeltaMinMaxFields.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesDeltaMinMaxFields/FeatureAttributeTimeSeriesDeltaMinMaxFields.tsx index 9404d3c..2d022a5 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesDeltaMinMaxFields/FeatureAttributeTimeSeriesDeltaMinMaxFields.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesDeltaMinMaxFields/FeatureAttributeTimeSeriesDeltaMinMaxFields.tsx @@ -21,9 +21,9 @@ export const FeatureAttributeTimeSeriesDeltaMinMaxFields: FC< FeatureAttributeTimeSeriesDeltaMinMaxFieldsProps > = ({ timeSeriesType, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); - if (timeSeriesType !== "delta") { + if (timeSeriesType !== "delta" || !purposes.includes("core")) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesDerivedOrdersField/FeatureAttributeTimeSeriesDerivedOrdersField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesDerivedOrdersField/FeatureAttributeTimeSeriesDerivedOrdersField.tsx index 6bcc1b4..355a21d 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesDerivedOrdersField/FeatureAttributeTimeSeriesDerivedOrdersField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesDerivedOrdersField/FeatureAttributeTimeSeriesDerivedOrdersField.tsx @@ -4,9 +4,9 @@ import { } from "@howso/react-tailwind-flowbite-components"; import { FC, useContext } from "react"; import { useFormContext } from "react-hook-form"; +import { useTranslation } from "react-i18next"; import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { FeatureAttributeTimeSeriesDerivedOrdersFieldI18nBundle as i18n } from "./FeatureAttributeTimeSeriesDerivedOrdersField.i18n"; -import { useTranslation } from "react-i18next"; export type FeatureAttributeTimeSeriesDerivedOrdersFieldProps = Partial & { @@ -19,9 +19,13 @@ export const FeatureAttributeTimeSeriesDerivedOrdersField: FC< FeatureAttributeTimeSeriesDerivedOrdersFieldProps > = ({ timeSeriesOrder, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); + if (!purposes.includes("core")) { + return null; + } + return ( = ({ isIdFeature }) => { const { t } = useTranslation(i18n.namespace); - const { fieldCheckboxProps } = useContext(FeaturesAttributesContext); + const { fieldCheckboxProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); - if (!isIdFeature) { + if (!isIdFeature || !purposes.includes("core")) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesLagsField/FeatureAttributeTimeSeriesLagsField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesLagsField/FeatureAttributeTimeSeriesLagsField.tsx index e4a9a71..cdec480 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesLagsField/FeatureAttributeTimeSeriesLagsField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesLagsField/FeatureAttributeTimeSeriesLagsField.tsx @@ -3,9 +3,9 @@ import { FieldTextProps, } from "@howso/react-tailwind-flowbite-components"; import { FC, useContext } from "react"; +import { useTranslation } from "react-i18next"; import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { FeatureAttributeTimeSeriesLagsFieldI18nBundle as i18n } from "./FeatureAttributeTimeSeriesLagsField.i18n"; -import { useTranslation } from "react-i18next"; export type FeatureAttributeTimeSeriesLagsFieldProps = Partial; /** @@ -15,7 +15,11 @@ export const FeatureAttributeTimeSeriesLagsField: FC< FeatureAttributeTimeSeriesLagsFieldProps > = (props) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); + + if (!purposes.includes("core")) { + return null; + } return ( & { @@ -19,9 +19,13 @@ export const FeatureAttributeTimeSeriesNumLagsField: FC< FeatureAttributeTimeSeriesNumLagsFieldProps > = ({ timeSeriesLags, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); + if (!purposes.includes("core")) { + return null; + } + return ( ; /** @@ -16,9 +16,13 @@ export const FeatureAttributeTimeSeriesOrderField: FC< FeatureAttributeTimeSeriesOrderFieldProps > = (props) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); + if (!purposes.includes("core")) { + return null; + } + return ( & { @@ -20,9 +20,9 @@ export const FeatureAttributeTimeSeriesRateMinMaxFields: FC< FeatureAttributeTimeSeriesRateMinMaxFieldsProps > = ({ timeSeriesType, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldTextProps } = useContext(FeaturesAttributesContext); + const { fieldTextProps, purposes } = useContext(FeaturesAttributesContext); - if (timeSeriesType !== "rate") { + if (timeSeriesType !== "rate" || !purposes.includes("core")) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesStopOnTerminatorsField/FeatureAttributeTimeSeriesStopOnTerminatorsField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesStopOnTerminatorsField/FeatureAttributeTimeSeriesStopOnTerminatorsField.tsx index db05257..0f645ef 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesStopOnTerminatorsField/FeatureAttributeTimeSeriesStopOnTerminatorsField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesStopOnTerminatorsField/FeatureAttributeTimeSeriesStopOnTerminatorsField.tsx @@ -1,9 +1,9 @@ import { FieldCheckbox } from "@howso/react-tailwind-flowbite-components"; import { FC, useContext } from "react"; import { useFormContext } from "react-hook-form"; +import { useTranslation } from "react-i18next"; import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { FeatureAttributeTimeSeriesStopOnTerminatorsFieldI18nBundle as i18n } from "./FeatureAttributeTimeSeriesStopOnTerminatorsField.i18n"; -import { useTranslation } from "react-i18next"; export type FeatureAttributeTimeSeriesStopOnTerminatorsFieldProps = { isIdFeature: boolean | undefined; @@ -15,10 +15,12 @@ export const FeatureAttributeTimeSeriesStopOnTerminatorsField: FC< FeatureAttributeTimeSeriesStopOnTerminatorsFieldProps > = ({ isIdFeature }) => { const { t } = useTranslation(i18n.namespace); - const { fieldCheckboxProps } = useContext(FeaturesAttributesContext); + const { fieldCheckboxProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); - if (!isIdFeature) { + if (!isIdFeature || !purposes.includes("core")) { return null; } diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesTypeField/FeatureAttributeTimeSeriesTypeField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesTypeField/FeatureAttributeTimeSeriesTypeField.tsx index d748868..96ca319 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesTypeField/FeatureAttributeTimeSeriesTypeField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeTimeSeriesTypeField/FeatureAttributeTimeSeriesTypeField.tsx @@ -22,8 +22,12 @@ export const FeatureAttributeTimeSeriesTypeField: FC< FeatureAttributeTimeSeriesTypeFieldProps > = ({ featureType, isTimeFeature, ...props }) => { const { t } = useTranslation(i18n.namespace); - const { fieldSelectProps } = useContext(FeaturesAttributesContext); + const { fieldSelectProps, purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); + if (!purposes.includes("core")) { + return null; + } + const required = false; const rateTypes: FeatureAttributes["type"][] = ["continuous", "ordinal"]; diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeTypeField/FeatureAttributeTypeField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeTypeField/FeatureAttributeTypeField.tsx index be9a27e..be3cc13 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeTypeField/FeatureAttributeTypeField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeTypeField/FeatureAttributeTypeField.tsx @@ -35,6 +35,7 @@ export const FeatureAttributeTypeField: FC = ({ required, ...props }) => { + const { purposes } = useContext(FeaturesAttributesContext); const form = useFormContext(); const registerOptions: RegisterOptions = useMemo( () => ({ @@ -57,6 +58,10 @@ export const FeatureAttributeTypeField: FC = ({ [form, required, onChange], ); + if (!purposes.includes("core")) { + return null; + } + switch (fieldType) { case "radios": return ( diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeUniqueField/FeatureAttributeUniqueField.stories.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeUniqueField/FeatureAttributeUniqueField.stories.tsx index 20a253d..c64af5d 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeUniqueField/FeatureAttributeUniqueField.stories.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeUniqueField/FeatureAttributeUniqueField.stories.tsx @@ -14,7 +14,7 @@ const meta: Meta = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core", "synthesis"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, diff --git a/src/components/FeatureAttributes/fields/FeatureAttributeUniqueField/FeatureAttributeUniqueField.tsx b/src/components/FeatureAttributes/fields/FeatureAttributeUniqueField/FeatureAttributeUniqueField.tsx index 3168a9f..cecbc0d 100644 --- a/src/components/FeatureAttributes/fields/FeatureAttributeUniqueField/FeatureAttributeUniqueField.tsx +++ b/src/components/FeatureAttributes/fields/FeatureAttributeUniqueField/FeatureAttributeUniqueField.tsx @@ -23,8 +23,9 @@ export const FeatureAttributeUniqueField: FC< FeatureAttributeUniqueFieldProps > = ({ featureType, dataType }) => { const { t } = useTranslation(i18n.namespace); - const { fieldCheckboxProps } = useContext(FeaturesAttributesContext); - + const { fieldCheckboxProps, purposes } = useContext( + FeaturesAttributesContext, + ); const form = useFormContext(); const allowedFeatureTypes: FeatureAttributes["type"][] = ["nominal"]; @@ -32,7 +33,8 @@ export const FeatureAttributeUniqueField: FC< if ( !featureType || !allowedFeatureTypes.includes(featureType) || - unAllowedDataTypes.includes(dataType) + unAllowedDataTypes.includes(dataType) || + !purposes.includes("synthesis") ) { return null; } diff --git a/src/components/FeatureAttributes/groups/FeatureAttributesBoundsGroup/FeatureAttributesBoundsGroup.tsx b/src/components/FeatureAttributes/groups/FeatureAttributesBoundsGroup/FeatureAttributesBoundsGroup.tsx index 3a6542c..e5b0d31 100644 --- a/src/components/FeatureAttributes/groups/FeatureAttributesBoundsGroup/FeatureAttributesBoundsGroup.tsx +++ b/src/components/FeatureAttributes/groups/FeatureAttributesBoundsGroup/FeatureAttributesBoundsGroup.tsx @@ -1,7 +1,8 @@ import { FeatureAttributes } from "@howso/engine"; import { formSpacingYDefault } from "@howso/react-tailwind-flowbite-components"; -import { FC } from "react"; +import { FC, useContext } from "react"; import { useTranslation } from "react-i18next"; +import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { FeatureAttributeAllowNullsField, FeatureAttributeAllowedValuesField, @@ -40,6 +41,11 @@ export const FeatureAttributesBoundsGroup: FC< ...props }) => { const { t } = useTranslation(i18n.namespace); + const { purposes } = useContext(FeaturesAttributesContext); + + if (!purposes.includes("core")) { + return null; + } return ( = ({ featureType, dataType, ...props }) => { const { t } = useTranslation(i18n.namespace); + const { purposes } = useContext(FeaturesAttributesContext); const allowedFeatureTypes: FeatureAttributes["type"][] = ["continuous"]; const allowedDataTypes: FeatureAttributes["data_type"][] = ["number"]; if ( !featureType || !allowedFeatureTypes.includes(featureType) || - !allowedDataTypes.includes(dataType) + !allowedDataTypes.includes(dataType) || + !purposes.includes("core") ) { return null; } diff --git a/src/components/FeatureAttributes/groups/FeatureAttributesProgrammableGroup/FeatureAttributesProgrammableGroup.stories.tsx b/src/components/FeatureAttributes/groups/FeatureAttributesProgrammableGroup/FeatureAttributesProgrammableGroup.stories.tsx index 7e820f4..c71baa3 100644 --- a/src/components/FeatureAttributes/groups/FeatureAttributesProgrammableGroup/FeatureAttributesProgrammableGroup.stories.tsx +++ b/src/components/FeatureAttributes/groups/FeatureAttributesProgrammableGroup/FeatureAttributesProgrammableGroup.stories.tsx @@ -14,7 +14,7 @@ const meta: Meta = { }, decorators: [ getFormProviderDecorator(), - getFeaturesAttributesContextDecorator(), + getFeaturesAttributesContextDecorator({ purposes: ["core"] }), ], // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, diff --git a/src/components/FeatureAttributes/groups/FeatureAttributesProgrammableGroup/FeatureAttributesProgrammableGroup.tsx b/src/components/FeatureAttributes/groups/FeatureAttributesProgrammableGroup/FeatureAttributesProgrammableGroup.tsx index 7dbfcb2..f709baa 100644 --- a/src/components/FeatureAttributes/groups/FeatureAttributesProgrammableGroup/FeatureAttributesProgrammableGroup.tsx +++ b/src/components/FeatureAttributes/groups/FeatureAttributesProgrammableGroup/FeatureAttributesProgrammableGroup.tsx @@ -1,15 +1,16 @@ -import { FC } from "react"; -import { - FeatureAttributesGroupBase, - FeatureAttributesGroupBaseProps, -} from "../FeatureAttributesGroupBase"; +import { formSpacingYDefault } from "@howso/react-tailwind-flowbite-components"; +import { FC, useContext } from "react"; +import { useTranslation } from "react-i18next"; +import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { FeatureAttributeDerivedFeatureCodeField, FeatureAttributePostProcessField, } from "../../fields"; -import { formSpacingYDefault } from "@howso/react-tailwind-flowbite-components"; +import { + FeatureAttributesGroupBase, + FeatureAttributesGroupBaseProps, +} from "../FeatureAttributesGroupBase"; import { FeatureAttributesProgrammableGroupI18nBundle as i18n } from "./FeatureAttributesProgrammableGroup.i18n"; -import { useTranslation } from "react-i18next"; export type FeatureAttributesProgrammableGroupProps = Omit< FeatureAttributesGroupBaseProps, @@ -19,6 +20,11 @@ export const FeatureAttributesProgrammableGroup: FC< FeatureAttributesProgrammableGroupProps > = ({ ...props }) => { const { t } = useTranslation(i18n.namespace); + const { purposes } = useContext(FeaturesAttributesContext); + + if (!purposes.includes("core")) { + return null; + } return ( { it("should include the temporality group", async () => { @@ -35,7 +35,7 @@ const Wrapper: FC<{ children: ReactNode; formProps?: UseFormProps }> = ({ }) => { const form = useForm(formProps); return ( - + {children} ); diff --git a/src/components/FeatureAttributes/groups/FeatureAttributesTemporalityGroup/FeatureAttributesTemporalityGroup.tsx b/src/components/FeatureAttributes/groups/FeatureAttributesTemporalityGroup/FeatureAttributesTemporalityGroup.tsx index 491eb7d..b46f9da 100644 --- a/src/components/FeatureAttributes/groups/FeatureAttributesTemporalityGroup/FeatureAttributesTemporalityGroup.tsx +++ b/src/components/FeatureAttributes/groups/FeatureAttributesTemporalityGroup/FeatureAttributesTemporalityGroup.tsx @@ -1,7 +1,8 @@ import { FeatureAttributes, FeatureTimeSeriesTypeEnum } from "@howso/engine"; import { formSpacingYDefault } from "@howso/react-tailwind-flowbite-components"; -import { FC } from "react"; +import { FC, useContext } from "react"; import { useTranslation } from "react-i18next"; +import { FeaturesAttributesContext } from "../../FeaturesAttributesContext"; import { FeatureAttributeTimeSeriesDeltaMinMaxFields, FeatureAttributeTimeSeriesDerivedOrdersField, @@ -47,8 +48,9 @@ export const FeatureAttributesTemporalityGroup: FC< ...props }) => { const { t } = useTranslation(i18n.namespace); + const { purposes } = useContext(FeaturesAttributesContext); - if (!featuresHaveTimeFeature) { + if (!featuresHaveTimeFeature || !purposes.includes("core")) { return null; } diff --git a/src/components/FeatureAttributes/types/api.ts b/src/components/FeatureAttributes/types/api.ts index 7279748..e0c8afd 100644 --- a/src/components/FeatureAttributes/types/api.ts +++ b/src/components/FeatureAttributes/types/api.ts @@ -1,5 +1,10 @@ import type { FeatureAttributes } from "@howso/engine"; +export type FeatureAttributePurposes = "core" | "synthesis"; +export interface IFeatureAttributePurposes { + purposes: FeatureAttributePurposes[]; +} + export type FeatureAttributesIndex = Record; /** Options available to the InferFeatureAttributes call in the platform API */ diff --git a/src/components/FeatureAttributes/utils/state.test.ts b/src/components/FeatureAttributes/utils/state.test.ts new file mode 100644 index 0000000..0c63e9f --- /dev/null +++ b/src/components/FeatureAttributes/utils/state.test.ts @@ -0,0 +1,30 @@ +import { FeatureAttributesIndex } from "../types"; +import { getAllFeatureAttributeConfigurationIssues } from "./state"; + +describe("getAllFeatureAttributeConfigurationIssues", () => { + describe("sensitivity", () => { + const featureName = "testFeature"; + const features: FeatureAttributesIndex = { + [featureName]: { type: "nominal", data_type: "string" }, + }; + it("should not require a subtype for nominal values when purposes does not include synthesis", () => { + const issues = getAllFeatureAttributeConfigurationIssues(features, { + purposes: ["core"], + }); + expect(issues).toBeUndefined(); + }); + + it("should require a subtype for nominal values when purposes include synthesis", () => { + const issues = getAllFeatureAttributeConfigurationIssues(features, { + purposes: ["core", "synthesis"], + }); + if (!issues) { + throw new Error("issues is undefined"); + } + + expect(issues[featureName]).toStrictEqual([ + { translationKey: "sensitiveSubtypeUndefined" }, + ]); + }); + }); +}); diff --git a/src/components/FeatureAttributes/utils/state.ts b/src/components/FeatureAttributes/utils/state.ts index 6b9e8ff..2dd018f 100644 --- a/src/components/FeatureAttributes/utils/state.ts +++ b/src/components/FeatureAttributes/utils/state.ts @@ -4,6 +4,7 @@ import { isFeatureAttributeSensitiveAttributeAvailable } from "../fields/Feature import { type InferFeatureAttributesRunRequiredFields } from "../hooks"; import type { FeatureAttributesIndex, + IFeatureAttributePurposes, InferFeatureAttributesParams, } from "../types"; import { InferFeatureAttributesBoundingMode } from "./forms"; @@ -14,10 +15,11 @@ export type FeatureAttributesConfigurationIssuesIndex = Record< >; export const getAllFeatureAttributeConfigurationIssues = ( featuresAttributesIndex: FeatureAttributesIndex, + params: IFeatureAttributePurposes, ): FeatureAttributesConfigurationIssuesIndex | undefined => { const issuesIndex = Object.entries(featuresAttributesIndex).reduce( (issuesIndex, [feature, attributes]) => { - const issues = getFeatureAttributeConfigurationIssues(attributes); + const issues = getFeatureAttributeConfigurationIssues(attributes, params); if (issues) { issuesIndex[feature] = issues; } @@ -32,10 +34,11 @@ export const getAllFeatureAttributeConfigurationIssues = ( export const areAllFeatureAttributesValid = ( featuresAttributesIndex: FeatureAttributesIndex, + params: IFeatureAttributePurposes, ): boolean => { const hasInvalid = Object.values(featuresAttributesIndex).some( (attributes) => { - const issues = getFeatureAttributeConfigurationIssues(attributes); + const issues = getFeatureAttributeConfigurationIssues(attributes, params); return issues !== undefined; }, ); @@ -72,6 +75,7 @@ const featureAttributeIssues: Record< export const getFeatureAttributeConfigurationIssues = ( featureAttributes: FeatureAttributes | undefined, + params: IFeatureAttributePurposes, ): FeatureAttributesConfigurationIssue[] | undefined => { const issues: FeatureAttributesConfigurationIssue[] = []; @@ -83,7 +87,9 @@ export const getFeatureAttributeConfigurationIssues = ( issues.push(featureAttributeIssues.dataTypeUndefined); } - if (isFeatureAttributeSensitiveAttributeAvailable(featureAttributes)) { + if ( + isFeatureAttributeSensitiveAttributeAvailable(featureAttributes, params) + ) { const isSensitive = !featureAttributes?.non_sensitive; if (isSensitive && !featureAttributes?.subtype) { issues.push(featureAttributeIssues.sensitiveSubtypeUndefined);