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
2 changes: 1 addition & 1 deletion src/visualBuilder/components/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const Tooltip = ({ children, content, placement = 'top-start' }: TooltipProps) =

if (side === 'top' || side === 'bottom') {
// For top/bottom placements, center the arrow horizontally
arrowElement.style.left = `${tooltipRect.width / 2 - 4}px`; // 4px = half arrow width
arrowElement.style.left = `${14}px`; // 4px = half arrow width
if (arrowY != null) {
arrowElement.style.top = `${arrowY}px`;
}
Expand Down
100 changes: 77 additions & 23 deletions src/visualBuilder/components/fieldLabelWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ import { getEntryPermissionsCached } from "../utils/getEntryPermissionsCached";
import { ContentTypeIcon } from "./icons";
import { ToolbarTooltip } from "./Tooltip";

interface ReferenceParentMap {
[entryUid: string]: {
contentTypeUid: string;
contentTypeTitle: string;
referenceFieldName: string;
}[]
}

async function getFieldDisplayNames(fieldMetadata: CslpData[]) {
const result = await visualBuilderPostMessage?.send<{
[k: string]: string;
Expand All @@ -26,13 +34,30 @@ async function getFieldDisplayNames(fieldMetadata: CslpData[]) {
}

async function getContentTypeName(contentTypeUid: string) {
const result = await visualBuilderPostMessage?.send<{
[k: string]: string;
}>(VisualBuilderPostMessageEvents.GET_CONTENT_TYPE_NAME, {
content_type_uid: contentTypeUid,
});
return result;
try {
const result = await visualBuilderPostMessage?.send<{
contentTypeName: string;
}>(VisualBuilderPostMessageEvents.GET_CONTENT_TYPE_NAME, {
content_type_uid: contentTypeUid,
});
return result?.contentTypeName;
} catch(e) {
console.warn("[getFieldLabelWrapper] Error getting content type name", e);
return "";
}
}

async function getReferenceParentMap() {
try {
const result = await visualBuilderPostMessage?.send<ReferenceParentMap>(VisualBuilderPostMessageEvents.REFERENCE_MAP, {}) ?? {};
return result;
} catch(e) {
console.warn("[getFieldLabelWrapper] Error getting reference parent map", e);
return {};
}

}

interface FieldLabelWrapperProps {
fieldMetadata: CslpData;
eventDetails: VisualBuilderCslpEventDetails;
Expand All @@ -49,6 +74,7 @@ interface ICurrentField {
isVariant: boolean;
isReference: boolean;
referenceFieldName: string;
parentContentTypeName: string;
isEmbedded: boolean;
}

Expand All @@ -65,12 +91,13 @@ function FieldLabelWrapperComponent(
isVariant: false,
isReference: false,
referenceFieldName: "",
parentContentTypeName: "",
isEmbedded: false,
});
const [displayNames, setDisplayNames] = useState<Record<string, string>>(
{}
);
const [displayNamesLoading, setDisplayNamesLoading] = useState(true);
const [dataLoading, setDataLoading] = useState(true);
const [error, setError] = useState(false);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);

Expand All @@ -82,7 +109,7 @@ function FieldLabelWrapperComponent(

useEffect(() => {
const fetchData = async () => {
setDisplayNamesLoading(true);
setDataLoading(true);
const allPaths = uniqBy(
[
props.fieldMetadata,
Expand All @@ -99,12 +126,34 @@ function FieldLabelWrapperComponent(
props.fieldMetadata.fieldPath
)
]);
// const contentTypeName = await getContentTypeName(
// props.fieldMetadata.content_type_uid
// );
const contentTypeName = await getContentTypeName(
props.fieldMetadata.content_type_uid
);
const referenceParentMap = await getReferenceParentMap();
const entryUid = props.fieldMetadata.entry_uid;

const referenceData = referenceParentMap[entryUid];
const isReference = !!referenceData;

let referenceFieldName = referenceData ? referenceData[0].referenceFieldName : "";
let parentContentTypeName = referenceData ? referenceData[0].contentTypeTitle : "";

if(isReference) {
const domAncestor = eventDetails.editableElement.closest(`[data-cslp]:not([data-cslp^="${props.fieldMetadata.content_type_uid}"])`);
if(domAncestor) {
const domAncestorCslp = domAncestor.getAttribute("data-cslp");
const domAncestorDetails = extractDetailsFromCslp(domAncestorCslp!);
const domAncestorContentTypeUid = domAncestorDetails.content_type_uid;
const domAncestorContentParent = referenceData?.find(data => data.contentTypeUid === domAncestorContentTypeUid);
if(domAncestorContentParent) {
referenceFieldName = domAncestorContentParent.referenceFieldName;
parentContentTypeName = domAncestorContentParent.contentTypeTitle;
}
}
}

if (hasPostMessageError(displayNames) || !fieldSchema) {
setDisplayNamesLoading(false);
setDataLoading(false);
setError(true);

return;
Expand All @@ -130,7 +179,7 @@ function FieldLabelWrapperComponent(

setCurrentField({
text: currentFieldDisplayName,
contentTypeName: 'Page CT',
contentTypeName: contentTypeName ?? "",
icon: fieldDisabled ? (
<div
className={classNames(
Expand All @@ -147,23 +196,28 @@ function FieldLabelWrapperComponent(
) : (
<></>
),
isReference: false,
isReference,
isEmbedded: false,
prefixIcon: getFieldIcon(fieldSchema),
disabled: fieldDisabled,
referenceFieldName: "Reference Field",
referenceFieldName,
parentContentTypeName,
isVariant: isVariant,
});

if (displayNames) {
setDisplayNames(displayNames);
}
if (Object.keys(displayNames || {})?.length === allPaths.length) {
setDisplayNamesLoading(false);
setDataLoading(false);
}
};

fetchData();
try {
fetchData();
} catch(e) {
console.warn("[getFieldLabelWrapper] Error fetching field label data", e);
}
}, [props]);

const onParentPathClick = (cslp: string) => {
Expand All @@ -177,7 +231,7 @@ function FieldLabelWrapperComponent(
function getCurrentFieldIcon() {
if (error) {
return null;
} else if (displayNamesLoading) {
} else if (dataLoading) {
return <LoadingIcon />;
} else {
return currentField.icon;
Expand All @@ -193,7 +247,7 @@ function FieldLabelWrapperComponent(
]
)}
>
<ToolbarTooltip data={{contentTypeName: currentField.contentTypeName, referenceFieldName: currentField.referenceFieldName}} disabled={!currentField.isReference}>
<ToolbarTooltip data={{contentTypeName: currentField.parentContentTypeName, referenceFieldName: currentField.referenceFieldName}} disabled={!currentField.isReference || isDropdownOpen}>
<div
className={classNames(
"visual-builder__focused-toolbar__field-label-wrapper",
Expand Down Expand Up @@ -235,10 +289,10 @@ function FieldLabelWrapperComponent(
"visual-builder__button-error"
]
)}
disabled={displayNamesLoading}
disabled={dataLoading}
>
{
currentField.isReference && !displayNamesLoading && !error ?
currentField.isReference && !dataLoading && !error ?
<div
className={classNames(
"visual-builder__reference-icon-container",
Expand All @@ -260,8 +314,8 @@ function FieldLabelWrapperComponent(
<CaretRightIcon />
</div> : null
}
{!displayNamesLoading && !error && <ContentTypeIcon />}
{currentField.contentTypeName && !displayNamesLoading && !error ? (
{!dataLoading && !error && <ContentTypeIcon />}
{currentField.contentTypeName && !dataLoading && !error ? (
<div
className={classNames(
"visual-builder__focused-toolbar__text",
Expand Down
11 changes: 1 addition & 10 deletions src/visualBuilder/listeners/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { throttle } from "lodash-es";
import { VisualBuilder } from "..";
import handleBuilderInteraction from "./mouseClick";
import handleMouseHover, {
Expand Down Expand Up @@ -37,16 +36,8 @@ const eventHandlers = {
overlayWrapper: params.overlayWrapper,
visualBuilderContainer: params.visualBuilderContainer,
customCursor: params.customCursor,
});
showHoverToolbar({
event: event,
overlayWrapper: params.overlayWrapper,
visualBuilderContainer: params.visualBuilderContainer,
previousSelectedEditableDOM:
VisualBuilder.VisualBuilderGlobalState.value
.previousSelectedEditableDOM,
focusedToolbar: params.focusedToolbar,
resizeObserver: params.resizeObserver,
focusedToolbar: params.focusedToolbar,
});
},
mouseleave: (params: AddEventListenersParams) => () => {
Expand Down
31 changes: 21 additions & 10 deletions src/visualBuilder/listeners/mouseHover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const config = Config.get();
export interface HandleMouseHoverParams
extends Pick<
EventListenerHandlerParams,
"event" | "overlayWrapper" | "visualBuilderContainer"
"event" | "overlayWrapper" | "visualBuilderContainer" | "focusedToolbar" | "resizeObserver"
> {
customCursor: HTMLDivElement | null;
}
Expand Down Expand Up @@ -200,15 +200,6 @@ function isFieldPathDropdown(target: HTMLElement): boolean {
return target.classList.contains("visual-builder__focused-toolbar__field-label-wrapper") || target.classList.contains("visual-builder__focused-toolbar__field-label-wrapper__current-field");
}

export function syncReferenceMap() {
const referenceParentMap = VisualBuilder.VisualBuilderGlobalState.value.referenceParentMap;
// Only sync on first hover
if(!referenceParentMap) {
return;
}
visualBuilderPostMessage?.send(VisualBuilderPostMessageEvents.SYNC_REFERENCE_MAP);
}

const throttledMouseHover = throttle(async (params: HandleMouseHoverParams) => {
const eventDetails = getCsDataOfElement(params.event);
const eventTarget = params.event.target as HTMLElement | null;
Expand All @@ -233,6 +224,16 @@ const throttledMouseHover = throttle(async (params: HandleMouseHoverParams) => {
isFieldPathDropdown(eventTarget)
) {
showOutline();
showHoverToolbar({
event: params.event,
overlayWrapper: params.overlayWrapper,
visualBuilderContainer: params.visualBuilderContainer,
previousSelectedEditableDOM:
VisualBuilder.VisualBuilderGlobalState.value
.previousSelectedEditableDOM,
focusedToolbar: params.focusedToolbar,
resizeObserver: params.resizeObserver,
});
}
if (!config?.collab.enable) {
resetCustomCursor(params.customCursor);
Expand Down Expand Up @@ -370,6 +371,16 @@ const throttledMouseHover = throttle(async (params: HandleMouseHoverParams) => {
fieldPath,
fieldMetadata,
});
showHoverToolbar({
event: params.event,
overlayWrapper: params.overlayWrapper,
visualBuilderContainer: params.visualBuilderContainer,
previousSelectedEditableDOM:
VisualBuilder.VisualBuilderGlobalState.value
.previousSelectedEditableDOM,
focusedToolbar: params.focusedToolbar,
resizeObserver: params.resizeObserver,
});
}

if (
Expand Down
1 change: 0 additions & 1 deletion src/visualBuilder/utils/types/postMessage.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export enum VisualBuilderPostMessageEvents {
SEND_VARIANT_AND_LOCALE = "send-variant-and-locale",
GET_CONTENT_TYPE_NAME = "get-content-type-name",
REFERENCE_MAP = "get-reference-map",
SYNC_REFERENCE_MAP = "sync-reference-map",
COLLAB_ENABLE = "collab-enable",
COLLAB_DATA_UPDATE = "collab-data-update",
COLLAB_DISABLE = "collab-disable",
Expand Down
Loading