Skip to content

Commit

Permalink
20656: MAJOR FeatureAttributes refactor to support InferFeatureAttrib…
Browse files Browse the repository at this point in the history
…uteParams (#5)

Highlights:
- Removed SetFeatureAtom. Conflicted with synchronous SetParamsAtom
- Introduced merged InferFeatureAttributesParams atom replacing both and
extracted shared functionality to utilities
- Renamed some component and functions based on "Infer". Should we
renamed all?
- Introduced FieldLabel tooltips for FieldRadio to simplify user
discovery
- Various style and bug fixes
- FeatureAttributeSubtypeField changed to FieldSelect due to VSCode
layout issues
- Renamed the 'areDirty' atom related to inference requirement to
"RunRequired" to avoid overlapping meaning with form's dirty handling.

Known issues:
- FieldLabel sizing does not match for FieldTextArea, because Flowbite
does not support it. ☠️
- [Light mode tooltips use dark mode theme
#1438](themesberg/flowbite-react#1438)
  • Loading branch information
lancegliser authored Jul 1, 2024
1 parent 23266bf commit e9389e8
Show file tree
Hide file tree
Showing 71 changed files with 1,581 additions and 792 deletions.
2 changes: 1 addition & 1 deletion .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const preview: Preview = {
},
},
i18n,
viewport: { defaultViewport: "responsive" },
viewport: { defaultViewport: undefined },
},
decorators: [
(Story: StoryFn, context) => {
Expand Down
81 changes: 80 additions & 1 deletion MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,82 @@
# Migration guide

## 1.x Initial version
## 1.x Feature Attributes updated to include Infer params

This breaking change modifies the data structures for FeatureAttributes.
All storage is now part of `InferFeatureAttributesParams` with attributes in `.features`.
Integration with `.strict_bounds` is complete.

Updates are based on the following signatures:

### FeaturesAttributesRows

```tsx
const params: InferFeatureAttributesParams = {
features: featuresAttributes,
};
const features = Object.keys(featuresAttributes);

const featuresDirtyAtom = getFeatureAttributesAreDirtyAtom();
const inferFeatureAttributesParamsAtom =
getInferFeatureAttributesParamsAtom(params);
const setFeatureAttributesAtom =
getInferFeatureAttributesParamsSetFeatureAttributesAtom({
inferFeatureAttributesParamsAtom,
featuresDirtyAtom,
});
const setParamsAtom = getInferFeatureAttributesParamsSetParamAtom({
inferFeatureAttributesParamsAtom,
});

const timeFeatureAtom = getInferFeatureAttributesParamsTimeFeatureAtom({
inferFeatureAttributesParamsAtom,
featuresDirtyAtom,
});

render(
<FeaturesAttributesRows
activeFeatureAtom={getFeatureAttributesActiveFeatureAtom()}
inferFeatureAttributesParamsAtom={inferFeatureAttributesParamsAtom}
optionsAtom={getFeatureAttributesOptionsAtom({})}
setFeatureAttributesAtom={setFeatureAttributesAtom}
setParamsAtom={setParamsAtom}
timeFeatureAtom={timeFeatureAtom}
/>
);
```

### FeaturesAttributesCompact

```tsx
const featuresDirtyAtom = getFeatureAttributesAreDirtyAtom();
const params: InferFeatureAttributesParams = {
features: featuresAttributes,
};
const inferFeatureAttributesParamsAtom =
getInferFeatureAttributesParamsAtom(params);
const setFeatureAttributesAtom =
getInferFeatureAttributesParamsSetFeatureAttributesAtom({
inferFeatureAttributesParamsAtom,
featuresDirtyAtom,
});
const setParamsAtom = getInferFeatureAttributesParamsSetParamAtom({
inferFeatureAttributesParamsAtom,
});
const timeFeatureAtom = getInferFeatureAttributesParamsTimeFeatureAtom({
inferFeatureAttributesParamsAtom,
featuresDirtyAtom,
});

render(
<FeaturesAttributesCompact
activeFeatureAtom={getFeatureAttributesActiveFeatureAtom()}
inferFeatureAttributesParamsAtom={inferFeatureAttributesParamsAtom}
optionsAtom={getFeatureAttributesOptionsAtom({})}
setFeatureAttributesAtom={setFeatureAttributesAtom}
setParamsAtom={setParamsAtom}
timeFeatureAtom={timeFeatureAtom}
/>
);
```

## 0.x Initial version
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"peerDependencies": {
"@hookform/error-message": "^2.0.1",
"@howso/openapi-client": "^1.0.0",
"@howso/react-tailwind-flowbite-components": "^3.0.1",
"@howso/react-tailwind-flowbite-components": "^3.1.0",
"flowbite": "^2.3.0",
"flowbite-react": "^0.7.2",
"jotai": "^2.8.3",
Expand All @@ -58,7 +58,7 @@
"@fontsource/inter": "^5.0.5",
"@hookform/error-message": "^2.0.1",
"@howso/openapi-client": "^1.0.0",
"@howso/react-tailwind-flowbite-components": "^3.0.1",
"@howso/react-tailwind-flowbite-components": "^3.1.0",
"@rollup/plugin-typescript": "^11.1.6",
"@storybook/addon-a11y": "^8.1.10",
"@storybook/addon-actions": "^8.1.10",
Expand Down
36 changes: 31 additions & 5 deletions public/locales/howso-engine-react-display-components/en.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"FeatureAttributes": {
"ConfigurationIssue": {
"typeUndefined": "Type is required",
"dataTypeUndefined": "Data type is required",
"dateTimeFormatUndefined": "Formatted date times require Date Time Format",
"sensitiveSubtypeUndefined": "Sensitive attributes require a Subtype for substitution",
"dateTimeFormatUndefined": "Formatted date times require Date Time Format"
"typeUndefined": "Type is required"
},
"FeatureAttributeAllowedValuesField": {
"help": {
Expand Down Expand Up @@ -93,6 +93,22 @@
"help": "<0>Amalgam</0> code that is called on resulting values of this feature during `react` operations.",
"label": "Post Process Code"
},
"FeatureAttributeReservedBoundingModeField": {
"help": {
"auto": "Extend the bounds of the feature for synthesis. Best for Privacy.",
"tightBounds": "Use the exact min and max found in the data. Best for Utility.",
"userDefined": "Specify min and max manually (not recommended)."
},
"label": "Bounding mode",
"options": {
"auto": "Auto",
"tightBounds": "Tight bounds",
"userDefined": "User defined"
}
},
"FeatureAttributeReservedTightTimeBoundField": {
"label": "Tight time bounds"
},
"FeatureAttributeSample": {
"modal": {
"title": "Sample"
Expand All @@ -118,7 +134,7 @@
"title": "Temporality"
},
"FeatureAttributeSubtypeField": {
"help": "Your platform supports a default list of options. You may create your own, supplying the name here instead.",
"help": "Your platform supports a default list of options. Refer to documentation for creation of a custom subtype.",
"label": "Subtype"
},
"FeatureAttributeTimeSeriesDeltaMinMaxFields": {
Expand Down Expand Up @@ -206,10 +222,20 @@
"form": {
"label": "Configure feature"
},
"header": {
"fields": {
"feature": {
"label": "Feature"
},
"timeFeature": {
"label": "Time Feature"
}
}
},
"labels": {
"density": {
"compact": "Compact",
"comfortable": "Comfortable"
"comfortable": "Comfortable",
"compact": "Compact"
},
"sample": "Sample"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import { FC, useState } from "react";
import { twMerge } from "tailwind-merge";

export type FeatureAttributeSampleProps = {
attributes: Pick<FeatureAttributes, "data_type" | "sample">;
attributes: Pick<FeatureAttributes, "data_type" | "sample"> | undefined;
disableModal?: boolean;
};
export const FeatureAttributeSample: FC<FeatureAttributeSampleProps> = ({
attributes,
disableModal,
}) => {
const [isOpen, setIsOpen] = useState(false);
if (!attributes) {
return null;
}

const openModal = () => {
if (disableModal) {
return;
Expand Down Expand Up @@ -73,6 +77,10 @@ const FeatureAttributeSampleModal: FC<
FeatureAttributeSampleProps & { onClose: () => void }
> = ({ attributes, onClose }) => {
const { t } = useDefaultTranslation();
if (!attributes) {
return null;
}

return (
<Modal show onClose={onClose} dismissible>
<Modal.Header>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { getFormProviderDecorator, withPadding } from "@/storybook";
import { FeatureAttributesConfiguration } from "./FeatureAttributesConfiguration";
import { type FeatureAttributesFieldsValues } from "./constants";
import { getFeaturesAttributesContextDecorator } from "../FeaturesAttributesContext/FeaturesAttributesContext.stories.decorators";
import { InferFeatureAttributeFormValues } from "../utils";

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta: Meta<typeof FeatureAttributesConfiguration> = {
Expand All @@ -14,7 +14,7 @@ const meta: Meta<typeof FeatureAttributesConfiguration> = {
layout: "fullscreen",
},
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>(),
getFormProviderDecorator<InferFeatureAttributeFormValues>(),
getFeaturesAttributesContextDecorator(),
withPadding,
],
Expand All @@ -30,7 +30,7 @@ type Story = StoryObj<typeof FeatureAttributesConfiguration>;

export const Default: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {},
}),
],
Expand All @@ -39,7 +39,7 @@ export const Default: Story = {

export const ContinuousNumber: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "continuous",
data_type: "number",
Expand All @@ -52,7 +52,7 @@ export const ContinuousNumber: Story = {

export const ContinuousString: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "continuous",
data_type: "string",
Expand All @@ -64,7 +64,7 @@ export const ContinuousString: Story = {

export const ContinuousFormattedDateTime: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "continuous",
data_type: "formatted_date_time",
Expand All @@ -79,7 +79,7 @@ export const ContinuousFormattedDateTime: Story = {

export const ContinuousComplex: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "continuous",
data_type: "json",
Expand All @@ -91,7 +91,7 @@ export const ContinuousComplex: Story = {

export const NominalNumber: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "nominal",
data_type: "number",
Expand All @@ -103,7 +103,7 @@ export const NominalNumber: Story = {

export const NominalString: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "nominal",
data_type: "string",
Expand All @@ -118,7 +118,7 @@ export const NominalString: Story = {

export const NominalFormattedDateTime: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "nominal",
data_type: "formatted_date_time",
Expand All @@ -136,7 +136,7 @@ export const NominalFormattedDateTime: Story = {

export const NominalComplex: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "nominal",
data_type: "json",
Expand All @@ -148,7 +148,7 @@ export const NominalComplex: Story = {

export const OrdinalNumber: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "ordinal",
data_type: "number",
Expand All @@ -163,7 +163,7 @@ export const OrdinalNumber: Story = {

export const OrdinalString: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "ordinal",
data_type: "string",
Expand All @@ -178,7 +178,7 @@ export const OrdinalString: Story = {

export const OrdinalFormattedDateTime: Story = {
decorators: [
getFormProviderDecorator<FeatureAttributesFieldsValues>({
getFormProviderDecorator<InferFeatureAttributeFormValues>({
defaultValues: {
type: "ordinal",
data_type: "formatted_date_time",
Expand Down
Loading

0 comments on commit e9389e8

Please sign in to comment.