Skip to content

Commit

Permalink
[FIX] Edit form contains only relationship field of cardinality many …
Browse files Browse the repository at this point in the history
…if kind is Attribute or Parent (#4229)

* Added test on getRelationshipsForForm func when create form
* hide relationship field of cardinality many on edit form
  • Loading branch information
bilalabbad authored Aug 30, 2024
1 parent 1f32a2a commit 66a33e2
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 26 deletions.
3 changes: 3 additions & 0 deletions frontend/app/src/components/form/node-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type NodeFormProps = {
onSuccess?: (newObject: any) => void;
currentObject?: Record<string, AttributeType | RelationshipType>;
isFilterForm?: boolean;
isUpdate?: boolean;
onSubmit?: (data: NodeFormSubmitParams) => void;
};

Expand All @@ -49,6 +50,7 @@ export const NodeForm = ({
onSuccess,
isFilterForm,
onSubmit,
isUpdate,
...props
}: NodeFormProps) => {
const branch = useAtomValue(currentBranchAtom);
Expand Down Expand Up @@ -80,6 +82,7 @@ export const NodeForm = ({
isFilterForm,
filters,
pools: numberPools,
isUpdate,
});

async function onSubmitCreate(data: Record<string, FormFieldValue>) {
Expand Down
1 change: 1 addition & 0 deletions frontend/app/src/components/form/object-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface ObjectFormProps extends Omit<DynamicFormProps, "fields" | "onSu
currentObject?: Record<string, AttributeType | RelationshipType>;
currentProfiles?: ProfileData[];
isFilterForm?: boolean;
isUpdate?: boolean;
onSubmit?: (data: NodeFormSubmitParams) => void;
onUpdateComplete?: () => void;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ import {
FormFieldValue,
NumberPoolData,
} from "@/components/form/type";
import {
getObjectRelationshipsForForm,
getOptionsFromAttribute,
getRelationshipOptions,
} from "@/utils/getSchemaObjectColumns";
import { getOptionsFromAttribute, getRelationshipOptions } from "@/utils/getSchemaObjectColumns";
import { isGeneric, sortByOrderWeight } from "@/utils/common";
import { getFieldDefaultValue } from "@/components/form/utils/getFieldDefaultValue";
import { SchemaAttributeType } from "@/screens/edit-form-hook/dynamic-control-types";
Expand All @@ -33,6 +29,7 @@ import { getRelationshipDefaultValue } from "@/components/form/utils/getRelation
import { Filter } from "@/hooks/useFilters";
import { getRelationshipParent } from "@/components/form/utils/getRelationshipParent";
import { isRequired } from "@/components/form/utils/validation";
import { getRelationshipsForForm } from "@/components/form/utils/getRelationshipsForForm";

type GetFormFieldsFromSchema = {
schema: iNodeSchema | iGenericSchema;
Expand All @@ -42,6 +39,7 @@ type GetFormFieldsFromSchema = {
isFilterForm?: boolean;
filters?: Array<Filter>;
pools?: Array<NumberPoolData>;
isUpdate?: boolean;
};

export const getFormFieldsFromSchema = ({
Expand All @@ -52,10 +50,11 @@ export const getFormFieldsFromSchema = ({
isFilterForm,
filters,
pools = [],
isUpdate,
}: GetFormFieldsFromSchema): Array<DynamicFieldProps> => {
const unorderedFields = [
...(schema.attributes ?? []),
...getObjectRelationshipsForForm(schema),
...getRelationshipsForForm(schema.relationships ?? [], isUpdate),
].filter((attribute) => !attribute.read_only);
const orderedFields: typeof unorderedFields = sortByOrderWeight(unorderedFields);

Expand Down
19 changes: 19 additions & 0 deletions frontend/app/src/components/form/utils/getRelationshipsForForm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { components } from "@/infraops";
import { peersKindForForm } from "@/config/constants";

export const getRelationshipsForForm = (
relationships: components["schemas"]["RelationshipSchema-Output"][],
isUpdate?: boolean
) => {
// Filter relationships based on cardinality and kind for form inclusion
// For create forms, include relationships with cardinality 'one', eligible kinds, or mandatory cardinality 'many'
// For update forms, only include relationships with cardinality 'one' or those with eligible kinds (Attribute or Parent). Other should be display as tabs on details view
return relationships.filter((relationship) => {
if (relationship.cardinality === "one") return true;

const isPeerKindEligibleForForm = peersKindForForm.includes(relationship?.kind ?? "");
if (isUpdate) return isPeerKindEligibleForForm;

return isPeerKindEligibleForForm || !relationship.optional;
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export default function ObjectItemEditComponent(props: Props) {
currentObject={objectDetailsData}
currentProfiles={objectProfiles}
data-cy="object-item-edit"
isUpdate
/>
);
}
20 changes: 0 additions & 20 deletions frontend/app/src/utils/getSchemaObjectColumns.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
attributesKindForDetailsViewExclude,
attributesKindForListView,
peersKindForForm,
relationshipsForDetailsView,
relationshipsForListView,
relationshipsForTabs,
Expand Down Expand Up @@ -143,25 +142,6 @@ export const getObjectTabs = (tabs: any[], data: any) => {
}));
};

// Used by the form to display the fields
export const getObjectRelationshipsForForm = (
schema?: iNodeSchema | iGenericSchema,
isUpdate?: boolean
) => {
const relationships = (schema?.relationships || [])
// Create form includes cardinality many but only if required, edit form doesn't include it at all
.filter(
(relationship) =>
relationship.cardinality === "one" ||
(isUpdate
? peersKindForForm.includes(relationship?.kind ?? "")
: peersKindForForm.includes(relationship?.kind ?? "") || !relationship.optional)
)
.filter(Boolean);

return relationships;
};

// Include current value in the options to make it available in the select component
export const getRelationshipOptions = (row: any, field: any, schemas: any[], generics: any[]) => {
const value = row && (row[field.name]?.node ?? row[field.name]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { describe, expect, it } from "vitest";
import { getRelationshipsForForm } from "@/components/form/utils/getRelationshipsForForm";
import { buildRelationshipSchema } from "./getFormFieldsFromSchema.test";

describe("getRelationshipsForForm", () => {
it("returns an empty array if the provided relationships array is empty", () => {
// GIVEN
const relationships: never[] = [];

// WHEN
const result = getRelationshipsForForm(relationships);

// THEN
expect(result).toEqual([]);
});

it("returns a relationship if cardinality is one", () => {
// GIVEN
const relationships = [buildRelationshipSchema({ cardinality: "one" })];

// WHEN
const result = getRelationshipsForForm(relationships);

// THEN
expect(result).toEqual([relationships[0]]);
});

it("returns a relationship of cardinality many if kind is Attribute or Parent", () => {
// GIVEN
const relationships = [
buildRelationshipSchema({ cardinality: "many", kind: "Attribute" }),
buildRelationshipSchema({ cardinality: "many", kind: "Parent" }),
];

// WHEN
const result = getRelationshipsForForm(relationships);

// THEN
expect(result).toEqual(relationships);
});

it("should not return a relationship of cardinality many if kind is Generic/Component/Hierarchy", () => {
// GIVEN
const relationships = [
buildRelationshipSchema({ cardinality: "many", kind: "Generic" }),
buildRelationshipSchema({ cardinality: "many", kind: "Component" }),
buildRelationshipSchema({ cardinality: "many", kind: "Hierarchy" }),
buildRelationshipSchema({ cardinality: "many", kind: "Group" }),
buildRelationshipSchema({ cardinality: "many", kind: "Profile" }),
];

// WHEN
const result = getRelationshipsForForm(relationships);

// THEN
expect(result).toEqual([]);
});

it("returns a relationship of cardinality many if it's mandatory field", () => {
// GIVEN
const relationships = [
buildRelationshipSchema({ cardinality: "many", kind: "Attribute", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Parent", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Generic", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Component", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Hierarchy", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Group", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Profile", optional: false }),
];

// WHEN
const result = getRelationshipsForForm(relationships);

// THEN
expect(result).toEqual(relationships);
});

it("When update, returns a mandatory relationship of cardinality is many if kind is Attribute or Parent", () => {
// GIVEN
const relationships = [
buildRelationshipSchema({ cardinality: "many", kind: "Attribute", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Parent", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Generic", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Component", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Hierarchy", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Group", optional: false }),
buildRelationshipSchema({ cardinality: "many", kind: "Profile", optional: false }),
];
const isUpdate = true;

// WHEN
const result = getRelationshipsForForm(relationships, isUpdate);

// THEN
expect(result).toEqual([relationships[0], relationships[1]]);
});
});

0 comments on commit 66a33e2

Please sign in to comment.