Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic selector fixes to correctly reset values when changing kind or object #3837

Merged
merged 16 commits into from
Jul 18, 2024
Merged
25 changes: 21 additions & 4 deletions docs/docs/release-notes/release-0_15.1_DRAFT.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,36 @@ title: Release 0.15

# Release 0.15.1

We are thrilled to announce the latest release of Infrahub (0.15).
This release focuses on enhancing the user experience and laying the groundwork for future features.
We are thrilled to announce the latest release of Infrahub (0.15.1).

## Main changes

### Multi profiles
### Unified storage

#### Frontend update
### Schema

### Frontend

#### Multi profiles

We can now select multiple profiles when creating and editing an object.

The `profile_priority` value from the profile schema is used to understand which value is used for the fields (the lower the number is, the higher the priority is).

#### Generic relationship select fixes

The select for a generic relationship has been fixed to properly reset the value when changing the kind or the parent.

The parent is also not showing "Unknown" after choosing an object.

### Helm Chart

### Infrahub Sync

### Other

### Demo Environment

## Migration Guide

To migrate your instance of Infrahub to the latest version, please run the following commands and restart all instances of Infrahub.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ const RelationshipField = ({
<RelationshipInput
{...field}
{...props}
value={undefined}
peer={parentRelationship?.peer}
disabled={props.disabled || !parentRelationship || !selectedKind?.id}
onChange={setSelectedParent}
Expand Down Expand Up @@ -281,15 +282,13 @@ interface RelationshipInputProps extends FormFieldProps, RelationshipFieldProps

// Select parent if needed
const RelationshipInput = forwardRef<ElementRef<typeof Select>, RelationshipInputProps>(
({ schema, value, options, relationship, ...props }, ref) => {
({ options, relationship, ...props }, ref) => {
return (
<Select
ref={ref}
{...props}
value={value}
options={options ?? []}
field={relationship}
schema={schema}
className="w-full"
/>
);
Expand Down
33 changes: 27 additions & 6 deletions frontend/app/src/components/inputs/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { comparedOptions } from "@/utils/array";
import { getOptionsFromRelationship } from "@/utils/getSchemaObjectColumns";
import DynamicForm from "@/components/form/dynamic-form";
import { Badge } from "../ui/badge";
import usePrevious from "@/hooks/usePrevious";

export type Parent = {
name?: string;
Expand Down Expand Up @@ -124,6 +125,8 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
const [hasBeenOpened, setHasBeenOpened] = useState(false);
const [optionToDelete, setOptionToDelete] = useState<null | number | string>(null);
const [localOptions, setLocalOptions] = useState(options);
const previousKind = usePrevious(kind);
const previousParent = usePrevious(parent?.value);

const findSelectedOption = () => {
return multiple
Expand Down Expand Up @@ -217,14 +220,20 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
handleFocus();
}

if (!newValue) {
setSelectedOption(undefined);
if (onChange) onChange(null);
return;
}

if (newValue.id === addOption.id) {
setOpen(true);
return;
}

if (newValue.id === emptyOption.id) {
setSelectedOption(emptyOption);
onChange(null);
if (onChange) onChange(null);
return;
}

Expand All @@ -240,11 +249,11 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
setSelectedOption(newValue);

if (hasPoolsBeenOpened) {
onChange(newValue.map((item) => ({ from_pool: { id: item.id } })));
if (onChange) onChange(newValue.map((item) => ({ from_pool: { id: item.id } })));
return;
}

onChange(newValue.map((item) => ({ id: item.id })));
if (onChange) onChange(newValue.map((item) => ({ id: item.id })));
return;
}

Expand All @@ -253,16 +262,17 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
setOpen(false);

if (hasPoolsBeenOpened) {
onChange(hasPoolsBeenOpened ? { from_pool: { id: newValue.id } } : { id: newValue.id });
if (onChange)
onChange(hasPoolsBeenOpened ? { from_pool: { id: newValue.id } } : { id: newValue.id });
return;
}

if (dropdown || enumBoolean) {
onChange(newValue.id);
if (onChange) onChange(newValue.id);
return;
}

onChange({ id: newValue.id });
if (onChange) onChange({ id: newValue.id });
};

const handleCreate = (response: any) => {
Expand Down Expand Up @@ -861,6 +871,17 @@ export const Select = forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
setLocalOptions(options);
}, [options?.length]);

// If kind or parent has changed, remove the current value
useEffect(() => {
if (peer && previousKind && peer !== previousKind) {
handleChange(undefined);
}

if (parent?.value && previousParent && parent?.value !== previousParent) {
handleChange(undefined);
}
}, [peer, parent?.value]);

return (
<div
className={classNames("relative", dropdown && disabled && "opacity-60", className)}
Expand Down
2 changes: 2 additions & 0 deletions frontend/app/tests/e2e/objects/artifact.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { expect, test } from "@playwright/test";
import { ACCOUNT_STATE_PATH } from "../../constants";

test.describe("/objects/CoreArtifact - Artifact page", () => {
test.describe.configure({ mode: "serial" });

test.beforeEach(async function ({ page }) {
page.on("response", async (response) => {
if (response.status() === 500) {
Expand Down
6 changes: 3 additions & 3 deletions frontend/app/tests/e2e/objects/object-update.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,13 @@ test.describe("Object update", () => {
await page.getByTestId("edit-button").click();

await page.getByTestId("side-panel-container").getByLabel("Status").click();
await page.getByText("Empty").click();
await page.getByRole("option", { name: "Empty", exact: true }).click();

await page.getByTestId("side-panel-container").getByLabel("Role").click();
await page.getByText("Empty").click();
await page.getByRole("option", { name: "Empty", exact: true }).click();

await page.getByTestId("side-panel-container").getByLabel("Asn").click();
await page.getByText("Empty").click();
await page.getByRole("option", { name: "Empty", exact: true }).click();

await page.getByRole("button", { name: "Save" }).click();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test.describe("/objects/CoreProfile - Profiles page", () => {
// L2 profile v1
await page.getByTestId("create-object-button").click();
await page.getByLabel("Select an object type").click();
await page.getByRole("option", { name: "ProfileInfraInterfaceL2" }).click();
await page.getByRole("option", { name: "ProfileInfraInterfaceL2 Profile" }).click();
await page.getByLabel("Profile Name *").fill("L2 profile v1");
await page.getByLabel("Description").fill("Desc from L2 profile v1");
await page.getByRole("button", { name: "Save" }).click();
Expand All @@ -44,7 +44,7 @@ test.describe("/objects/CoreProfile - Profiles page", () => {
// L2 profile v2
await page.getByTestId("create-object-button").click();
await page.getByLabel("Select an object type").click();
await page.getByRole("option", { name: "ProfileInfraInterfaceL2" }).click();
await page.getByRole("option", { name: "ProfileInfraInterfaceL2 Profile" }).click();
await page.getByLabel("Profile Name *").fill("L2 profile v2");
await page.getByLabel("Description").fill("Desc from L2 profile v2");
await page.getByLabel("Profile Priority").fill("10");
Expand Down
Loading