Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/visualBuilder/__test__/click/fields/multi-line.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ describe("When an element is clicked in visual builder mode", () => {
},
},
});
case VisualBuilderPostMessageEvents.GET_RESOLVED_VARIANT_PERMISSIONS:
return Promise.resolve({
update: true,
});
default:
return Promise.resolve({});
}
Expand Down Expand Up @@ -216,6 +220,10 @@ describe("When an element is clicked in visual builder mode", () => {
},
});
}
case VisualBuilderPostMessageEvents.GET_RESOLVED_VARIANT_PERMISSIONS:
return Promise.resolve({
update: true,
});
default:
return Promise.resolve({});
}
Expand Down
5 changes: 5 additions & 0 deletions src/visualBuilder/__test__/click/fields/number.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ describe("When an element is clicked in visual builder mode", () => {
},
});
}
else if (eventName === VisualBuilderPostMessageEvents.GET_RESOLVED_VARIANT_PERMISSIONS) {
return Promise.resolve({
update: true,
});
}
return Promise.resolve({});
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ describe("When an element is clicked in visual builder mode", () => {
},
},
});
case VisualBuilderPostMessageEvents.GET_RESOLVED_VARIANT_PERMISSIONS:
return Promise.resolve({
update: true,
});
default:
return Promise.resolve({});
}
Expand Down Expand Up @@ -234,6 +238,10 @@ describe("When an element is clicked in visual builder mode", () => {
},
},
});
case VisualBuilderPostMessageEvents.GET_RESOLVED_VARIANT_PERMISSIONS:
return Promise.resolve({
update: true,
});
default:
return Promise.resolve({});
}
Expand Down
6 changes: 5 additions & 1 deletion src/visualBuilder/components/FieldToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { EntryPermissions } from "../utils/getEntryPermissions";
import { FieldLocationAppList } from "./FieldLocationAppList";
import { FieldLocationIcon } from "./FieldLocationIcon";
import { WorkflowStageDetails } from "../utils/getWorkflowStageDetails";
import { ResolvedVariantPermissions } from "../utils/getResolvedVariantPermissions";

export type FieldDetails = Pick<
VisualBuilderCslpEventDetails,
Expand All @@ -57,6 +58,7 @@ interface MultipleFieldToolbarProps {
isVariant?: boolean;
entryPermissions?: EntryPermissions | undefined;
entryWorkflowStageDetails?: WorkflowStageDetails | undefined;
resolvedVariantPermissions?: ResolvedVariantPermissions | undefined;
}

function handleReplaceAsset(fieldMetadata: CslpData) {
Expand Down Expand Up @@ -117,6 +119,7 @@ function FieldToolbarComponent(
isVariant: isVariantOrParentOfVariant,
entryPermissions,
entryWorkflowStageDetails,
resolvedVariantPermissions,
} = props;
const { fieldMetadata, editableElement: targetElement } = eventDetails;
const [isFormLoading, setIsFormLoading] = useState(false);
Expand Down Expand Up @@ -157,8 +160,9 @@ function FieldToolbarComponent(
editableElement: targetElement,
fieldMetadata,
},
resolvedVariantPermissions,
entryPermissions,
entryWorkflowStageDetails
entryWorkflowStageDetails,
);
disableFieldActions = isDisabled;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ describe("FieldLabelWrapperComponent", () => {
expect(isFieldDisabled).toHaveBeenCalledWith(
mockFieldSchema,
mockEventDetails,
undefined,
{
update: {
create: true,
Expand Down
6 changes: 4 additions & 2 deletions src/visualBuilder/components/fieldLabelWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,20 @@ function FieldLabelWrapperComponent(
return;
}

const { acl: entryAcl, workflowStage: entryWorkflowStageDetails } =
const { acl: entryAcl, workflowStage: entryWorkflowStageDetails, resolvedVariantPermissions } =
await fetchEntryPermissionsAndStageDetails({
entryUid: props.fieldMetadata.entry_uid,
contentTypeUid: props.fieldMetadata.content_type_uid,
locale: props.fieldMetadata.locale,
variantUid: props.fieldMetadata.variant,
fieldPathWithIndex: props.fieldMetadata.fieldPathWithIndex,
});
const { isDisabled: fieldDisabled, reason } = isFieldDisabled(
fieldSchema,
eventDetails,
resolvedVariantPermissions,
entryAcl,
entryWorkflowStageDetails
entryWorkflowStageDetails,
);

const currentFieldDisplayName =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { FieldSchemaMap } from "../../../visualBuilder/utils/fieldSchemaMap";
import { visualBuilderStyles } from "../../../visualBuilder/visualBuilder.style";
import visualBuilderPostMessage from "../../../visualBuilder/utils/visualBuilderPostMessage";
import { EventManager } from "@contentstack/advanced-post-message";
import * as cslpdata from "../../../cslp/cslpdata";

const mockVisualBuilderPostMessage =
visualBuilderPostMessage as MockedObject<EventManager>;
Expand Down Expand Up @@ -101,7 +102,7 @@ const mockQuerySelectorAll = vi.fn().mockImplementation((selector) => {
return mockElements; // For onlyHighlighted=true case
} else if (
selector ===
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field"
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field, .visual-builder__lower-order-variant-field"
) {
return mockElements; // For onlyHighlighted=false case
}
Expand Down Expand Up @@ -303,7 +304,7 @@ describe("useVariantFieldsPostMessageEvent", () => {

// Verify querySelectorAll was called with the correct selector
expect(mockQuerySelectorAll).toHaveBeenCalledWith(
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field"
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field, .visual-builder__lower-order-variant-field"
);

// Verify that classes were removed from elements correctly
Expand All @@ -312,7 +313,8 @@ describe("useVariantFieldsPostMessageEvent", () => {
"visual-builder__disabled-variant-field",
"visual-builder__variant-field",
visualBuilderStyles()["visual-builder__variant-field"],
"visual-builder__base-field"
"visual-builder__base-field",
"visual-builder__lower-order-variant-field"
);
});
});
Expand All @@ -339,7 +341,7 @@ describe("addVariantFieldClass", () => {
const variantUid = "variant-123";
const highlightVariantFields = true;

addVariantFieldClass(variantUid, highlightVariantFields);
addVariantFieldClass(variantUid, highlightVariantFields, []);

// Verify querySelectorAll was called with the correct selector
expect(mockQuerySelectorAll).toHaveBeenCalledWith("[data-cslp]");
Expand Down Expand Up @@ -370,7 +372,7 @@ describe("addVariantFieldClass", () => {
const variantUid = "variant-123";
const highlightVariantFields = false;

addVariantFieldClass(variantUid, highlightVariantFields);
addVariantFieldClass(variantUid, highlightVariantFields, []);

// First element has the variant ID but should not get highlight class
expect(mockElements[0].getAttribute).toHaveBeenCalledWith("data-cslp");
Expand All @@ -381,6 +383,23 @@ describe("addVariantFieldClass", () => {
"visual-builder__variant-field"
);
});

it("should handle lower order variant fields correctly", () => {
// @ts-expect-error mocking only required properties
vi.spyOn(cslpdata, "extractDetailsFromCslp").mockImplementation((cslpValue) => {
return {
variant: cslpValue.split(":")[1]
}
});
const variantUid = "variant-456";
const highlightVariantFields = false;
const variantOrder = ["variant-123", "variant-456"];

addVariantFieldClass(variantUid, highlightVariantFields, variantOrder);

// Verify that classes were added to elements correctly
expect(mockElements[0].classList.add).toHaveBeenCalledWith("visual-builder__variant-field", "visual-builder__lower-order-variant-field");
});
});

describe("removeVariantFieldClass", () => {
Expand Down Expand Up @@ -421,7 +440,7 @@ describe("removeVariantFieldClass", () => {

// Verify querySelectorAll was called with the correct selector
expect(mockQuerySelectorAll).toHaveBeenCalledWith(
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field"
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field, .visual-builder__lower-order-variant-field"
);

// Verify classes were removed
Expand All @@ -430,7 +449,8 @@ describe("removeVariantFieldClass", () => {
"visual-builder__disabled-variant-field",
"visual-builder__variant-field",
visualBuilderStyles()["visual-builder__variant-field"],
"visual-builder__base-field"
"visual-builder__base-field",
"visual-builder__lower-order-variant-field"
);
});
});
Expand All @@ -440,7 +460,7 @@ describe("removeVariantFieldClass", () => {

// Verify querySelectorAll was called with the correct selector
expect(mockQuerySelectorAll).toHaveBeenCalledWith(
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field"
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field, .visual-builder__lower-order-variant-field"
);
});
});
Expand Down
33 changes: 28 additions & 5 deletions src/visualBuilder/eventManager/useVariantsPostMessageEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { visualBuilderStyles } from "../visualBuilder.style";
import visualBuilderPostMessage from "../utils/visualBuilderPostMessage";
import { VisualBuilderPostMessageEvents } from "../utils/types/postMessage.types";
import { FieldSchemaMap } from "../utils/fieldSchemaMap";
import { extractDetailsFromCslp } from "../../cslp/cslpdata";

interface VariantFieldsEvent {
data: {
variant_data: {
variant: string;
highlightVariantFields: boolean;
variantOrder: string[];
};
};
}
Expand All @@ -34,9 +36,24 @@ interface LocaleEvent {
locale: string;
};
}

function isLowerOrderVariant(variant_uid: string, dataCslp: string, variantOrder: string[]): boolean {
if(!variantOrder || variantOrder.length === 0) {
return false;
}
const {variant: cslpVariant} = extractDetailsFromCslp(dataCslp);
const indexOfCmsVariant = variantOrder.lastIndexOf(variant_uid);
const indexOfCslpVariant = variantOrder.lastIndexOf(cslpVariant || "");
if(indexOfCslpVariant < 0) {
return false;
}
return indexOfCslpVariant < indexOfCmsVariant;
}

export function addVariantFieldClass(
variant_uid: string,
highlightVariantFields: boolean
highlightVariantFields: boolean,
variantOrder: string[]
): void {
const elements = document.querySelectorAll(`[data-cslp]`);
elements.forEach((element) => {
Expand All @@ -51,7 +68,11 @@ export function addVariantFieldClass(
element.classList.add("visual-builder__variant-field");
} else if (!dataCslp.startsWith("v2:")) {
element.classList.add("visual-builder__base-field");
} else {
}
else if (isLowerOrderVariant(variant_uid, dataCslp, variantOrder)) {
element.classList.add("visual-builder__variant-field", "visual-builder__lower-order-variant-field");
}
else {
element.classList.add("visual-builder__disabled-variant-field");
}
});
Expand All @@ -71,14 +92,15 @@ export function removeVariantFieldClass(
});
} else {
const variantAndBaseFieldElements = document.querySelectorAll(
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field"
".visual-builder__disabled-variant-field, .visual-builder__variant-field, .visual-builder__base-field, .visual-builder__lower-order-variant-field"
);
variantAndBaseFieldElements.forEach((element) => {
element.classList.remove(
"visual-builder__disabled-variant-field",
"visual-builder__variant-field",
visualBuilderStyles()["visual-builder__variant-field"],
"visual-builder__base-field"
"visual-builder__base-field",
"visual-builder__lower-order-variant-field"
);
});
}
Expand Down Expand Up @@ -125,7 +147,8 @@ export function useVariantFieldsPostMessageEvent(): void {
removeVariantFieldClass();
addVariantFieldClass(
event.data.variant_data.variant,
event.data.variant_data.highlightVariantFields
event.data.variant_data.highlightVariantFields,
event.data.variant_data.variantOrder
);
}
);
Expand Down
4 changes: 3 additions & 1 deletion src/visualBuilder/generators/generateToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,13 @@ export async function appendFieldToolbar(
) && !isHover
)
return;
const { acl: entryPermissions, workflowStage: entryWorkflowStageDetails } =
const { acl: entryPermissions, workflowStage: entryWorkflowStageDetails, resolvedVariantPermissions } =
await fetchEntryPermissionsAndStageDetails({
entryUid: eventDetails.fieldMetadata.entry_uid,
contentTypeUid: eventDetails.fieldMetadata.content_type_uid,
locale: eventDetails.fieldMetadata.locale,
variantUid: eventDetails.fieldMetadata.variant,
fieldPathWithIndex: eventDetails.fieldMetadata.fieldPathWithIndex,
});
const wrapper = document.createDocumentFragment();
render(
Expand All @@ -66,6 +67,7 @@ export async function appendFieldToolbar(
isVariant={isVariant}
entryPermissions={entryPermissions}
entryWorkflowStageDetails={entryWorkflowStageDetails}
resolvedVariantPermissions={resolvedVariantPermissions}
/>,
wrapper
);
Expand Down
5 changes: 4 additions & 1 deletion src/visualBuilder/listeners/mouseClick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,23 +310,26 @@ async function handleFieldSchemaAndIndividualFields(
fieldPath,
locale,
variant: variantUid,
fieldPathWithIndex,
} = fieldMetadata;
const fieldSchema = await FieldSchemaMap.getFieldSchema(
content_type_uid,
fieldPath
);
const { acl: entryAcl, workflowStage: entryWorkflowStageDetails } =
const { acl: entryAcl, workflowStage: entryWorkflowStageDetails, resolvedVariantPermissions } =
await fetchEntryPermissionsAndStageDetails({
entryUid: entry_uid,
contentTypeUid: content_type_uid,
locale,
variantUid,
fieldPathWithIndex,
});

if (fieldSchema) {
const { isDisabled } = isFieldDisabled(
fieldSchema,
eventDetails,
resolvedVariantPermissions,
entryAcl,
entryWorkflowStageDetails
);
Expand Down
Loading
Loading