slice-machine-ui 2.17.0 → 2.17.1-alpha.jp-cr-ui-nested-ct-remove-section.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/404.html +1 -1
- package/out/_next/static/{9gEJI2zCChbd-ZM5eAZcP → 0SPBnBOIdcPusg2ceVdAq}/_buildManifest.js +1 -1
- package/out/_next/static/chunks/630-4a8f19a6a113700f.js +1 -0
- package/out/_next/static/chunks/pages/{_app-e3fa2a0a57c571ce.js → _app-15912b10c760cd68.js} +1 -1
- package/out/changelog.html +1 -1
- package/out/changes.html +1 -1
- package/out/custom-types/[customTypeId].html +1 -1
- package/out/custom-types.html +1 -1
- package/out/index.html +1 -1
- package/out/labs.html +1 -1
- package/out/page-types/[pageTypeId].html +1 -1
- package/out/settings.html +1 -1
- package/out/slices/[lib]/[sliceName]/[variation]/simulator.html +1 -1
- package/out/slices/[lib]/[sliceName]/[variation].html +1 -1
- package/out/slices.html +1 -1
- package/package.json +5 -4
- package/src/features/builder/fields/contentRelationship/ContentRelationshipFieldPicker.tsx +424 -205
- package/src/features/builder/fields/contentRelationship/__tests__/ContentRelationshipFieldPicker.test.ts +1225 -167
- package/src/utils/tracking/getLinkTrackingProperties.ts +3 -1
- package/out/_next/static/chunks/630-a8b2c2d022cc9450.js +0 -1
- /package/out/_next/static/{9gEJI2zCChbd-ZM5eAZcP → 0SPBnBOIdcPusg2ceVdAq}/_ssgManifest.js +0 -0
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from "@prismicio/editor-ui";
|
|
23
23
|
import {
|
|
24
24
|
CustomType,
|
|
25
|
+
DynamicWidget,
|
|
25
26
|
Group,
|
|
26
27
|
Link,
|
|
27
28
|
LinkConfig,
|
|
@@ -260,11 +261,11 @@ export function ContentRelationshipFieldPicker(
|
|
|
260
261
|
function ContentRelationshipFieldPickerContent(
|
|
261
262
|
props: ContentRelationshipFieldPickerProps,
|
|
262
263
|
) {
|
|
263
|
-
const { value, onChange } = props;
|
|
264
|
-
const { allCustomTypes, pickedCustomTypes } = useCustomTypes(
|
|
264
|
+
const { value: linkCustomtypes, onChange } = props;
|
|
265
|
+
const { allCustomTypes, pickedCustomTypes } = useCustomTypes(linkCustomtypes);
|
|
265
266
|
|
|
266
|
-
const fieldCheckMap =
|
|
267
|
-
? convertLinkCustomtypesToFieldCheckMap(
|
|
267
|
+
const fieldCheckMap = linkCustomtypes
|
|
268
|
+
? convertLinkCustomtypesToFieldCheckMap({ linkCustomtypes, allCustomTypes })
|
|
268
269
|
: {};
|
|
269
270
|
|
|
270
271
|
function onCustomTypesChange(id: string, newCustomType: PickerCustomType) {
|
|
@@ -274,22 +275,24 @@ function ContentRelationshipFieldPickerContent(
|
|
|
274
275
|
// represent new types added without any picked fields.
|
|
275
276
|
onChange(
|
|
276
277
|
mergeAndConvertCheckMapToLinkCustomtypes({
|
|
277
|
-
|
|
278
|
-
previousPickerCustomtypes: fieldCheckMap,
|
|
279
|
-
customTypeId: id,
|
|
278
|
+
fieldCheckMap,
|
|
280
279
|
newCustomType,
|
|
280
|
+
linkCustomtypes,
|
|
281
|
+
customTypeId: id,
|
|
281
282
|
}),
|
|
282
283
|
);
|
|
283
284
|
}
|
|
284
285
|
|
|
285
286
|
function addCustomType(id: string) {
|
|
286
|
-
const newFields =
|
|
287
|
+
const newFields = linkCustomtypes ? [...linkCustomtypes, id] : [id];
|
|
287
288
|
onChange(newFields);
|
|
288
289
|
}
|
|
289
290
|
|
|
290
291
|
function removeCustomType(id: string) {
|
|
291
|
-
if (
|
|
292
|
-
onChange(
|
|
292
|
+
if (linkCustomtypes) {
|
|
293
|
+
onChange(
|
|
294
|
+
linkCustomtypes.filter((existingCt) => getId(existingCt) !== id),
|
|
295
|
+
);
|
|
293
296
|
}
|
|
294
297
|
}
|
|
295
298
|
|
|
@@ -409,8 +412,9 @@ function ContentRelationshipFieldPickerContent(
|
|
|
409
412
|
rel="noopener noreferrer"
|
|
410
413
|
style={{ color: "inherit", textDecoration: "underline" }}
|
|
411
414
|
>
|
|
412
|
-
Please provide your feedback here
|
|
415
|
+
Please provide your feedback here
|
|
413
416
|
</a>
|
|
417
|
+
.
|
|
414
418
|
</Text>
|
|
415
419
|
</Box>
|
|
416
420
|
</Box>
|
|
@@ -463,20 +467,20 @@ function AddTypeButton(props: AddTypeButtonProps) {
|
|
|
463
467
|
</Button>
|
|
464
468
|
);
|
|
465
469
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
<
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
470
|
+
if (allCustomTypes.length === 0) {
|
|
471
|
+
return (
|
|
472
|
+
<Box>
|
|
473
|
+
<Tooltip
|
|
474
|
+
content="No type available"
|
|
475
|
+
side="bottom"
|
|
476
|
+
align="start"
|
|
477
|
+
disableHoverableContent
|
|
478
|
+
>
|
|
479
|
+
{triggerButton}
|
|
480
|
+
</Tooltip>
|
|
481
|
+
</Box>
|
|
482
|
+
);
|
|
483
|
+
}
|
|
480
484
|
|
|
481
485
|
return (
|
|
482
486
|
<Box>
|
|
@@ -529,7 +533,7 @@ function TreeViewCustomType(props: TreeViewCustomTypeProps) {
|
|
|
529
533
|
} = props;
|
|
530
534
|
|
|
531
535
|
const renderedFields = getCustomTypeStaticFields(customType).map(
|
|
532
|
-
(
|
|
536
|
+
([fieldId, field]) => {
|
|
533
537
|
// Group field
|
|
534
538
|
|
|
535
539
|
if (field.type === "Group") {
|
|
@@ -661,93 +665,89 @@ function TreeViewContentRelationshipField(
|
|
|
661
665
|
allCustomTypes,
|
|
662
666
|
);
|
|
663
667
|
|
|
664
|
-
if (resolvedCustomTypes.length
|
|
668
|
+
if (resolvedCustomTypes.length !== 1) return null;
|
|
665
669
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
670
|
+
const [customType] = resolvedCustomTypes;
|
|
671
|
+
|
|
672
|
+
if (typeof customType === "string") return null;
|
|
673
|
+
|
|
674
|
+
const onNestedCustomTypeChange = (
|
|
675
|
+
newNestedCustomTypeFields: PickerNestedCustomTypeValue,
|
|
676
|
+
) => {
|
|
677
|
+
onCrFieldChange({
|
|
678
|
+
...crFieldsCheckMap,
|
|
679
|
+
[customType.id]: newNestedCustomTypeFields,
|
|
680
|
+
});
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
const nestedCtFieldsCheckMap = crFieldsCheckMap[customType.id] ?? {};
|
|
675
684
|
|
|
676
|
-
|
|
677
|
-
|
|
685
|
+
const renderedFields = getCustomTypeStaticFields(customType).map(
|
|
686
|
+
([fieldId, field]) => {
|
|
687
|
+
// Group field
|
|
688
|
+
|
|
689
|
+
if (field.type === "Group") {
|
|
690
|
+
const onGroupFieldsChange = (
|
|
691
|
+
newGroupFields: PickerLeafGroupFieldValue,
|
|
678
692
|
) => {
|
|
679
|
-
|
|
680
|
-
...
|
|
681
|
-
[
|
|
693
|
+
onNestedCustomTypeChange({
|
|
694
|
+
...nestedCtFieldsCheckMap,
|
|
695
|
+
[fieldId]: { type: "group", value: newGroupFields },
|
|
682
696
|
});
|
|
683
697
|
};
|
|
684
698
|
|
|
685
|
-
const
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
[fieldId]: { type: "group", value: newGroupFields },
|
|
698
|
-
});
|
|
699
|
-
};
|
|
700
|
-
|
|
701
|
-
const groupFieldCheckMap = nestedCtFieldsCheckMap[fieldId] ?? {};
|
|
702
|
-
|
|
703
|
-
return (
|
|
704
|
-
<TreeViewLeafGroupField
|
|
705
|
-
key={fieldId}
|
|
706
|
-
group={field}
|
|
707
|
-
groupId={fieldId}
|
|
708
|
-
onChange={onGroupFieldsChange}
|
|
709
|
-
fieldCheckMap={
|
|
710
|
-
groupFieldCheckMap.type === "group"
|
|
711
|
-
? groupFieldCheckMap.value
|
|
712
|
-
: {}
|
|
713
|
-
}
|
|
714
|
-
/>
|
|
715
|
-
);
|
|
699
|
+
const groupFieldCheckMap = nestedCtFieldsCheckMap[fieldId] ?? {};
|
|
700
|
+
|
|
701
|
+
return (
|
|
702
|
+
<TreeViewLeafGroupField
|
|
703
|
+
key={fieldId}
|
|
704
|
+
group={field}
|
|
705
|
+
groupId={fieldId}
|
|
706
|
+
onChange={onGroupFieldsChange}
|
|
707
|
+
fieldCheckMap={
|
|
708
|
+
groupFieldCheckMap.type === "group"
|
|
709
|
+
? groupFieldCheckMap.value
|
|
710
|
+
: {}
|
|
716
711
|
}
|
|
712
|
+
/>
|
|
713
|
+
);
|
|
714
|
+
}
|
|
717
715
|
|
|
718
|
-
|
|
716
|
+
// Regular field
|
|
719
717
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
return (
|
|
728
|
-
<TreeViewCheckbox
|
|
729
|
-
key={fieldId}
|
|
730
|
-
title={fieldId}
|
|
731
|
-
checked={nestedCtFieldsCheckMap[fieldId]?.value === true}
|
|
732
|
-
onCheckedChange={onCheckedChange}
|
|
733
|
-
/>
|
|
734
|
-
);
|
|
735
|
-
},
|
|
736
|
-
);
|
|
718
|
+
const onCheckedChange = (newChecked: boolean) => {
|
|
719
|
+
onNestedCustomTypeChange({
|
|
720
|
+
...nestedCtFieldsCheckMap,
|
|
721
|
+
[fieldId]: { type: "checkbox", value: newChecked },
|
|
722
|
+
});
|
|
723
|
+
};
|
|
737
724
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
725
|
+
return (
|
|
726
|
+
<TreeViewCheckbox
|
|
727
|
+
key={fieldId}
|
|
728
|
+
title={fieldId}
|
|
729
|
+
checked={nestedCtFieldsCheckMap[fieldId]?.value === true}
|
|
730
|
+
onCheckedChange={onCheckedChange}
|
|
731
|
+
/>
|
|
732
|
+
);
|
|
733
|
+
},
|
|
734
|
+
);
|
|
735
|
+
|
|
736
|
+
return (
|
|
737
|
+
<TreeViewSection
|
|
738
|
+
key={customType.id}
|
|
739
|
+
// @ts-expect-error - TODO: Fix this when we are able to release editor packages
|
|
740
|
+
title={
|
|
741
|
+
<Text>
|
|
742
|
+
{fieldId} <Text color="grey11">→ {customType.id}</Text>
|
|
743
|
+
</Text>
|
|
744
|
+
}
|
|
745
|
+
subtitle={getPickedFieldsLabel(
|
|
746
|
+
countPickedFields(nestedCtFieldsCheckMap).pickedFields,
|
|
747
|
+
)}
|
|
748
|
+
badge={getTypeFormatLabel(customType.format)}
|
|
749
|
+
>
|
|
750
|
+
{renderedFields.length > 0 ? renderedFields : <NoFieldsAvailable />}
|
|
751
751
|
</TreeViewSection>
|
|
752
752
|
);
|
|
753
753
|
}
|
|
@@ -901,7 +901,7 @@ function getTypeFormatLabel(format: CustomType["format"]) {
|
|
|
901
901
|
}
|
|
902
902
|
|
|
903
903
|
/** Retrieves all existing page & custom types. */
|
|
904
|
-
function useCustomTypes(
|
|
904
|
+
function useCustomTypes(linkCustomtypes: LinkCustomtypes | undefined): {
|
|
905
905
|
/** Every existing custom type, used to discover nested custom types down the tree and the add type dropdown. */
|
|
906
906
|
allCustomTypes: CustomType[];
|
|
907
907
|
/** The custom types that are already picked. */
|
|
@@ -913,14 +913,14 @@ function useCustomTypes(value: LinkCustomtypes | undefined): {
|
|
|
913
913
|
void revalidateGetCustomTypes();
|
|
914
914
|
}, []);
|
|
915
915
|
|
|
916
|
-
if (!
|
|
916
|
+
if (!linkCustomtypes) {
|
|
917
917
|
return {
|
|
918
918
|
allCustomTypes,
|
|
919
919
|
pickedCustomTypes: [],
|
|
920
920
|
};
|
|
921
921
|
}
|
|
922
922
|
|
|
923
|
-
const pickedCustomTypes =
|
|
923
|
+
const pickedCustomTypes = linkCustomtypes.flatMap(
|
|
924
924
|
(pickedCt) => allCustomTypes.find((ct) => ct.id === getId(pickedCt)) ?? [],
|
|
925
925
|
);
|
|
926
926
|
|
|
@@ -932,10 +932,10 @@ function useCustomTypes(value: LinkCustomtypes | undefined): {
|
|
|
932
932
|
|
|
933
933
|
function resolveContentRelationshipCustomTypes(
|
|
934
934
|
linkCustomtypes: LinkCustomtypes,
|
|
935
|
-
|
|
935
|
+
allCustomTypes: CustomType[],
|
|
936
936
|
): CustomType[] {
|
|
937
937
|
return linkCustomtypes.flatMap((linkCustomtype) => {
|
|
938
|
-
return
|
|
938
|
+
return allCustomTypes.find((ct) => ct.id === getId(linkCustomtype)) ?? [];
|
|
939
939
|
});
|
|
940
940
|
}
|
|
941
941
|
|
|
@@ -943,92 +943,281 @@ function resolveContentRelationshipCustomTypes(
|
|
|
943
943
|
* Converts a Link config `customtypes` ({@link LinkCustomtypes}) structure into
|
|
944
944
|
* picker fields check map ({@link PickerCustomTypes}).
|
|
945
945
|
*/
|
|
946
|
-
export function convertLinkCustomtypesToFieldCheckMap(
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
946
|
+
export function convertLinkCustomtypesToFieldCheckMap(args: {
|
|
947
|
+
linkCustomtypes: LinkCustomtypes;
|
|
948
|
+
allCustomTypes?: CustomType[];
|
|
949
|
+
}): PickerCustomTypes {
|
|
950
|
+
const { linkCustomtypes, allCustomTypes } = args;
|
|
951
|
+
|
|
952
|
+
// If allCustomTypes is undefined, avoid checking if the fields exist.
|
|
953
|
+
const shouldValidate = allCustomTypes !== undefined;
|
|
954
|
+
|
|
955
|
+
const checkMap = linkCustomtypes.reduce<PickerCustomTypes>(
|
|
956
|
+
(customTypes, customType) => {
|
|
957
|
+
if (typeof customType === "string") return customTypes;
|
|
958
|
+
|
|
959
|
+
let ctFlatFieldMap: Record<string, NestableWidget | Group> = {};
|
|
960
|
+
|
|
961
|
+
if (shouldValidate) {
|
|
962
|
+
const existingCt = allCustomTypes.find((c) => c.id === customType.id);
|
|
963
|
+
// Exit early if the custom type doesn't exist
|
|
964
|
+
if (!existingCt) return customTypes;
|
|
965
|
+
|
|
966
|
+
ctFlatFieldMap = getCustomTypeStaticFieldsMap(existingCt);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
const customTypeFields = customType.fields.reduce<PickerCustomType>(
|
|
970
|
+
(fields, field) => {
|
|
971
|
+
// Check if the field exists (only if validating)
|
|
972
|
+
const existingField = ctFlatFieldMap[getId(field)];
|
|
973
|
+
if (shouldValidate && existingField === undefined) return fields;
|
|
974
|
+
|
|
955
975
|
// Regular field
|
|
956
|
-
|
|
957
|
-
|
|
976
|
+
if (typeof field === "string") {
|
|
977
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
978
|
+
if (
|
|
979
|
+
shouldValidate &&
|
|
980
|
+
existingField !== undefined &&
|
|
981
|
+
existingField.type === "Group"
|
|
982
|
+
) {
|
|
983
|
+
return fields;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
fields[field] = { type: "checkbox", value: true };
|
|
987
|
+
return fields;
|
|
988
|
+
}
|
|
989
|
+
|
|
958
990
|
// Group field
|
|
959
|
-
|
|
960
|
-
|
|
991
|
+
if ("fields" in field && field.fields !== undefined) {
|
|
992
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
993
|
+
if (
|
|
994
|
+
shouldValidate &&
|
|
995
|
+
existingField !== undefined &&
|
|
996
|
+
existingField.type !== "Group"
|
|
997
|
+
) {
|
|
998
|
+
return fields;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
const groupFieldCheckMap = createGroupFieldCheckMap({
|
|
1002
|
+
group: field,
|
|
1003
|
+
allCustomTypes,
|
|
1004
|
+
ctFlatFieldMap,
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
if (groupFieldCheckMap) {
|
|
1008
|
+
fields[field.id] = groupFieldCheckMap;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
return fields;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
961
1014
|
// Content relationship field
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1015
|
+
if ("customtypes" in field && field.customtypes !== undefined) {
|
|
1016
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1017
|
+
if (
|
|
1018
|
+
shouldValidate &&
|
|
1019
|
+
existingField !== undefined &&
|
|
1020
|
+
!isContentRelationshipField(existingField)
|
|
1021
|
+
) {
|
|
1022
|
+
return fields;
|
|
1023
|
+
}
|
|
965
1024
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1025
|
+
const crFieldCheckMap = createContentRelationshipFieldCheckMap({
|
|
1026
|
+
field,
|
|
1027
|
+
allCustomTypes,
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
if (crFieldCheckMap) {
|
|
1031
|
+
fields[field.id] = crFieldCheckMap;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
return fields;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
return fields;
|
|
1038
|
+
},
|
|
1039
|
+
{},
|
|
1040
|
+
);
|
|
1041
|
+
|
|
1042
|
+
if (Object.keys(customTypeFields).length > 0) {
|
|
1043
|
+
customTypes[customType.id] = customTypeFields;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
return customTypes;
|
|
1047
|
+
},
|
|
1048
|
+
{},
|
|
1049
|
+
);
|
|
1050
|
+
|
|
1051
|
+
return checkMap;
|
|
972
1052
|
}
|
|
973
1053
|
|
|
974
|
-
function createGroupFieldCheckMap(
|
|
975
|
-
group: LinkCustomtypesGroupFieldValue
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1054
|
+
function createGroupFieldCheckMap(args: {
|
|
1055
|
+
group: LinkCustomtypesGroupFieldValue;
|
|
1056
|
+
allCustomTypes?: CustomType[];
|
|
1057
|
+
ctFlatFieldMap: Record<string, NestableWidget | Group>;
|
|
1058
|
+
}): PickerFirstLevelGroupField | undefined {
|
|
1059
|
+
const { group, ctFlatFieldMap, allCustomTypes } = args;
|
|
1060
|
+
|
|
1061
|
+
// If allCustomTypes is undefined, avoid checking if the fields exist.
|
|
1062
|
+
const shouldValidate = allCustomTypes !== undefined;
|
|
1063
|
+
|
|
1064
|
+
const fieldEntries = group.fields.reduce<PickerFirstLevelGroupFieldValue>(
|
|
1065
|
+
(fields, field) => {
|
|
1066
|
+
// Check if the field exists (only if validating)
|
|
1067
|
+
const existingField = getGroupFieldFromMap(
|
|
1068
|
+
ctFlatFieldMap,
|
|
1069
|
+
group.id,
|
|
1070
|
+
getId(field),
|
|
1071
|
+
);
|
|
1072
|
+
if (shouldValidate && !existingField) return fields;
|
|
1073
|
+
|
|
1074
|
+
// Regular field
|
|
1075
|
+
if (typeof field === "string") {
|
|
1076
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1077
|
+
if (
|
|
1078
|
+
shouldValidate &&
|
|
1079
|
+
existingField !== undefined &&
|
|
1080
|
+
existingField.type === "Group"
|
|
1081
|
+
) {
|
|
1082
|
+
return fields;
|
|
987
1083
|
}
|
|
988
1084
|
|
|
1085
|
+
fields[field] = { type: "checkbox", value: true };
|
|
989
1086
|
return fields;
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// Content relationship field
|
|
1090
|
+
if ("customtypes" in field && field.customtypes !== undefined) {
|
|
1091
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1092
|
+
if (
|
|
1093
|
+
shouldValidate &&
|
|
1094
|
+
existingField !== undefined &&
|
|
1095
|
+
!isContentRelationshipField(existingField)
|
|
1096
|
+
) {
|
|
1097
|
+
return fields;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
const crFieldCheckMap = createContentRelationshipFieldCheckMap({
|
|
1101
|
+
field,
|
|
1102
|
+
allCustomTypes,
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
if (crFieldCheckMap) {
|
|
1106
|
+
fields[field.id] = crFieldCheckMap;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
return fields;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
return fields;
|
|
1113
|
+
},
|
|
1114
|
+
{},
|
|
1115
|
+
);
|
|
1116
|
+
|
|
1117
|
+
if (Object.keys(fieldEntries).length === 0) return undefined;
|
|
1118
|
+
|
|
1119
|
+
return {
|
|
1120
|
+
type: "group",
|
|
1121
|
+
value: fieldEntries,
|
|
993
1122
|
};
|
|
994
1123
|
}
|
|
995
1124
|
|
|
996
|
-
function createContentRelationshipFieldCheckMap(
|
|
997
|
-
field: LinkCustomtypesContentRelationshipFieldValue
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
value: {},
|
|
1002
|
-
};
|
|
1003
|
-
const crFieldCustomTypes = crField.value;
|
|
1125
|
+
function createContentRelationshipFieldCheckMap(args: {
|
|
1126
|
+
field: LinkCustomtypesContentRelationshipFieldValue;
|
|
1127
|
+
allCustomTypes?: CustomType[];
|
|
1128
|
+
}): PickerContentRelationshipField | undefined {
|
|
1129
|
+
const { field, allCustomTypes } = args;
|
|
1004
1130
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1131
|
+
// If allCustomTypes is undefined, avoid checking if the fields exists.
|
|
1132
|
+
const shouldValidate = allCustomTypes !== undefined;
|
|
1007
1133
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1134
|
+
const fieldEntries =
|
|
1135
|
+
field.customtypes.reduce<PickerContentRelationshipFieldValue>(
|
|
1136
|
+
(customTypes, customType) => {
|
|
1137
|
+
if (typeof customType === "string") return customTypes;
|
|
1010
1138
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
(
|
|
1139
|
+
let ctFlatFieldMap: Record<string, NestableWidget | Group> = {};
|
|
1140
|
+
|
|
1141
|
+
if (shouldValidate) {
|
|
1142
|
+
const existingCt = allCustomTypes.find((c) => c.id === customType.id);
|
|
1143
|
+
// Exit early if the custom type doesn't exist
|
|
1144
|
+
if (!existingCt) return customTypes;
|
|
1145
|
+
|
|
1146
|
+
ctFlatFieldMap = getCustomTypeStaticFieldsMap(existingCt);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
const ctFields = customType.fields.reduce<PickerNestedCustomTypeValue>(
|
|
1150
|
+
(nestedFields, nestedField) => {
|
|
1151
|
+
// Regular field
|
|
1152
|
+
if (typeof nestedField === "string") {
|
|
1153
|
+
const existingField = ctFlatFieldMap[nestedField];
|
|
1154
|
+
|
|
1155
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1156
|
+
if (
|
|
1157
|
+
shouldValidate &&
|
|
1158
|
+
(existingField === undefined || existingField.type === "Group")
|
|
1159
|
+
) {
|
|
1160
|
+
return nestedFields;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
nestedFields[nestedField] = { type: "checkbox", value: true };
|
|
1164
|
+
return nestedFields;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
if ("fields" in nestedField && nestedField.fields !== undefined) {
|
|
1168
|
+
// Group field
|
|
1169
|
+
const groupFields =
|
|
1170
|
+
nestedField.fields.reduce<PickerLeafGroupFieldValue>(
|
|
1171
|
+
(groupFields, groupField) => {
|
|
1172
|
+
const existingField = getGroupFieldFromMap(
|
|
1173
|
+
ctFlatFieldMap,
|
|
1174
|
+
nestedField.id,
|
|
1175
|
+
groupField,
|
|
1176
|
+
);
|
|
1177
|
+
|
|
1178
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1179
|
+
if (
|
|
1180
|
+
shouldValidate &&
|
|
1181
|
+
(existingField === undefined ||
|
|
1182
|
+
existingField.type === "Group")
|
|
1183
|
+
) {
|
|
1184
|
+
return groupFields;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
groupFields[groupField] = { type: "checkbox", value: true };
|
|
1188
|
+
return groupFields;
|
|
1189
|
+
},
|
|
1190
|
+
{},
|
|
1191
|
+
);
|
|
1192
|
+
|
|
1193
|
+
if (Object.keys(groupFields).length > 0) {
|
|
1194
|
+
nestedFields[nestedField.id] = {
|
|
1195
|
+
type: "group",
|
|
1196
|
+
value: groupFields,
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
return nestedFields;
|
|
1202
|
+
},
|
|
1203
|
+
{},
|
|
1019
1204
|
);
|
|
1020
1205
|
|
|
1021
|
-
if (
|
|
1022
|
-
|
|
1023
|
-
type: "group",
|
|
1024
|
-
value: Object.fromEntries(groupFieldsEntries),
|
|
1025
|
-
};
|
|
1206
|
+
if (Object.keys(ctFields).length > 0) {
|
|
1207
|
+
customTypes[customType.id] = ctFields;
|
|
1026
1208
|
}
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
1209
|
|
|
1031
|
-
|
|
1210
|
+
return customTypes;
|
|
1211
|
+
},
|
|
1212
|
+
{},
|
|
1213
|
+
);
|
|
1214
|
+
|
|
1215
|
+
if (Object.keys(fieldEntries).length === 0) return undefined;
|
|
1216
|
+
|
|
1217
|
+
return {
|
|
1218
|
+
type: "contentRelationship",
|
|
1219
|
+
value: fieldEntries,
|
|
1220
|
+
};
|
|
1032
1221
|
}
|
|
1033
1222
|
|
|
1034
1223
|
/**
|
|
@@ -1037,27 +1226,22 @@ function createContentRelationshipFieldCheckMap(
|
|
|
1037
1226
|
* made correctly and that the order is preserved.
|
|
1038
1227
|
*/
|
|
1039
1228
|
function mergeAndConvertCheckMapToLinkCustomtypes(args: {
|
|
1040
|
-
|
|
1041
|
-
|
|
1229
|
+
linkCustomtypes: LinkCustomtypes | undefined;
|
|
1230
|
+
fieldCheckMap: PickerCustomTypes;
|
|
1042
1231
|
newCustomType: PickerCustomType;
|
|
1043
1232
|
customTypeId: string;
|
|
1044
1233
|
}): LinkCustomtypes {
|
|
1045
|
-
const {
|
|
1046
|
-
existingLinkCustomtypes,
|
|
1047
|
-
previousPickerCustomtypes,
|
|
1048
|
-
newCustomType,
|
|
1049
|
-
customTypeId,
|
|
1050
|
-
} = args;
|
|
1234
|
+
const { linkCustomtypes, fieldCheckMap, newCustomType, customTypeId } = args;
|
|
1051
1235
|
|
|
1052
1236
|
const result: NonReadonly<LinkCustomtypes> = [];
|
|
1053
1237
|
const pickerLinkCustomtypes = convertFieldCheckMapToLinkCustomtypes({
|
|
1054
|
-
...
|
|
1238
|
+
...fieldCheckMap,
|
|
1055
1239
|
[customTypeId]: newCustomType,
|
|
1056
1240
|
});
|
|
1057
1241
|
|
|
1058
|
-
if (!
|
|
1242
|
+
if (!linkCustomtypes) return pickerLinkCustomtypes;
|
|
1059
1243
|
|
|
1060
|
-
for (const existingLinkCt of
|
|
1244
|
+
for (const existingLinkCt of linkCustomtypes) {
|
|
1061
1245
|
const existingPickerLinkCt = pickerLinkCustomtypes.find((ct) => {
|
|
1062
1246
|
return getId(ct) === getId(existingLinkCt);
|
|
1063
1247
|
});
|
|
@@ -1229,6 +1413,10 @@ export function countPickedFields(
|
|
|
1229
1413
|
);
|
|
1230
1414
|
}
|
|
1231
1415
|
|
|
1416
|
+
function isContentRelationshipField(field: DynamicWidget): field is Link {
|
|
1417
|
+
return field.type === "Link" && field.config?.select === "document";
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1232
1420
|
/**
|
|
1233
1421
|
* Check if the field is a Content Relationship Link with a **single** custom
|
|
1234
1422
|
* type. CRs with multiple custom types are not currently supported (legacy).
|
|
@@ -1237,34 +1425,65 @@ function isContentRelationshipFieldWithSingleCustomtype(
|
|
|
1237
1425
|
field: NestableWidget | Group,
|
|
1238
1426
|
): field is Link {
|
|
1239
1427
|
return !!(
|
|
1240
|
-
field
|
|
1241
|
-
field.config?.select === "document" &&
|
|
1428
|
+
isContentRelationshipField(field) &&
|
|
1242
1429
|
field.config?.customtypes &&
|
|
1243
1430
|
field.config.customtypes.length === 1
|
|
1244
1431
|
);
|
|
1245
1432
|
}
|
|
1246
1433
|
|
|
1247
|
-
|
|
1434
|
+
/**
|
|
1435
|
+
* Flattens all custom type tabs and fields into an array of [fieldId, field] tuples.
|
|
1436
|
+
* Also filters out invalid fields.
|
|
1437
|
+
*/
|
|
1438
|
+
function getCustomTypeStaticFields(
|
|
1439
|
+
customType: CustomType,
|
|
1440
|
+
): [fieldId: string, field: NestableWidget | Group][] {
|
|
1248
1441
|
return Object.values(customType.json).flatMap((tabFields) => {
|
|
1249
|
-
return Object.entries(tabFields).flatMap
|
|
1250
|
-
|
|
1251
|
-
field
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
// API and is not part of the data object in the document.
|
|
1255
|
-
// We also filter by key "uid", because (as of the time of writing
|
|
1256
|
-
// this), creating any field with that API id will result in it being
|
|
1257
|
-
// used for metadata.
|
|
1258
|
-
(field.type !== "UID" || fieldId !== "uid")
|
|
1259
|
-
) {
|
|
1260
|
-
return { fieldId, field: field as NestableWidget | Group };
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
return [];
|
|
1264
|
-
});
|
|
1442
|
+
return Object.entries(tabFields).flatMap<[string, NestableWidget | Group]>(
|
|
1443
|
+
([fieldId, field]) => {
|
|
1444
|
+
return isValidField(fieldId, field) ? [[fieldId, field]] : [];
|
|
1445
|
+
},
|
|
1446
|
+
);
|
|
1265
1447
|
});
|
|
1266
1448
|
}
|
|
1267
1449
|
|
|
1450
|
+
/**
|
|
1451
|
+
* Flattens all custom type tabs and fields into a map of field ids to fields.
|
|
1452
|
+
* Also filters out invalid fields.
|
|
1453
|
+
*/
|
|
1454
|
+
function getCustomTypeStaticFieldsMap(
|
|
1455
|
+
customType: CustomType,
|
|
1456
|
+
): Record<string, NestableWidget | Group> {
|
|
1457
|
+
return Object.fromEntries(getCustomTypeStaticFields(customType));
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
function getGroupFieldFromMap(
|
|
1461
|
+
flattenFields: Record<string, NestableWidget | Group>,
|
|
1462
|
+
groupId: string,
|
|
1463
|
+
fieldId: string,
|
|
1464
|
+
) {
|
|
1465
|
+
const group = flattenFields[groupId];
|
|
1466
|
+
if (group === undefined || group.type !== "Group") return undefined;
|
|
1467
|
+
return group.config?.fields?.[fieldId];
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
function isValidField(
|
|
1471
|
+
fieldId: string,
|
|
1472
|
+
field: DynamicWidget,
|
|
1473
|
+
): field is NestableWidget | Group {
|
|
1474
|
+
return (
|
|
1475
|
+
field.type !== "Slices" &&
|
|
1476
|
+
field.type !== "Choice" &&
|
|
1477
|
+
// We don't display uid fields because they're a special field returned by
|
|
1478
|
+
// the API and they're not included in the document data object.
|
|
1479
|
+
// We also filter by key "uid", because (as of the time of writing this)
|
|
1480
|
+
// creating any field with that API id will result in it being used for
|
|
1481
|
+
// metadata, regardless of its type.
|
|
1482
|
+
field.type !== "UID" &&
|
|
1483
|
+
fieldId !== "uid"
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1268
1487
|
function getGroupFields(group: Group) {
|
|
1269
1488
|
if (!group.config?.fields) return [];
|
|
1270
1489
|
return Object.entries(group.config.fields).map(([fieldId, field]) => {
|