slice-machine-ui 2.17.0 → 2.17.1-alpha.jp-cr-ui-nested-ct-remove-section.2
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 → bn0k7fTPhMvXnRDmHW4YV}/_buildManifest.js +1 -1
- package/out/_next/static/chunks/630-4a8f19a6a113700f.js +1 -0
- package/out/_next/static/chunks/pages/{_app-e3fa2a0a57c571ce.js → _app-25ccfbe208347f9e.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 +425 -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 → bn0k7fTPhMvXnRDmHW4YV}/_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,90 @@ 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
|
+
// https://linear.app/prismic/issue/DT-2736/
|
|
740
|
+
// @ts-expect-error - TODO: Fix this when we are able to release editor packages
|
|
741
|
+
title={
|
|
742
|
+
<Text>
|
|
743
|
+
{fieldId} <Text color="grey11">→ {customType.id}</Text>
|
|
744
|
+
</Text>
|
|
745
|
+
}
|
|
746
|
+
subtitle={getPickedFieldsLabel(
|
|
747
|
+
countPickedFields(nestedCtFieldsCheckMap).pickedFields,
|
|
748
|
+
)}
|
|
749
|
+
badge={getTypeFormatLabel(customType.format)}
|
|
750
|
+
>
|
|
751
|
+
{renderedFields.length > 0 ? renderedFields : <NoFieldsAvailable />}
|
|
751
752
|
</TreeViewSection>
|
|
752
753
|
);
|
|
753
754
|
}
|
|
@@ -901,7 +902,7 @@ function getTypeFormatLabel(format: CustomType["format"]) {
|
|
|
901
902
|
}
|
|
902
903
|
|
|
903
904
|
/** Retrieves all existing page & custom types. */
|
|
904
|
-
function useCustomTypes(
|
|
905
|
+
function useCustomTypes(linkCustomtypes: LinkCustomtypes | undefined): {
|
|
905
906
|
/** Every existing custom type, used to discover nested custom types down the tree and the add type dropdown. */
|
|
906
907
|
allCustomTypes: CustomType[];
|
|
907
908
|
/** The custom types that are already picked. */
|
|
@@ -913,14 +914,14 @@ function useCustomTypes(value: LinkCustomtypes | undefined): {
|
|
|
913
914
|
void revalidateGetCustomTypes();
|
|
914
915
|
}, []);
|
|
915
916
|
|
|
916
|
-
if (!
|
|
917
|
+
if (!linkCustomtypes) {
|
|
917
918
|
return {
|
|
918
919
|
allCustomTypes,
|
|
919
920
|
pickedCustomTypes: [],
|
|
920
921
|
};
|
|
921
922
|
}
|
|
922
923
|
|
|
923
|
-
const pickedCustomTypes =
|
|
924
|
+
const pickedCustomTypes = linkCustomtypes.flatMap(
|
|
924
925
|
(pickedCt) => allCustomTypes.find((ct) => ct.id === getId(pickedCt)) ?? [],
|
|
925
926
|
);
|
|
926
927
|
|
|
@@ -932,10 +933,10 @@ function useCustomTypes(value: LinkCustomtypes | undefined): {
|
|
|
932
933
|
|
|
933
934
|
function resolveContentRelationshipCustomTypes(
|
|
934
935
|
linkCustomtypes: LinkCustomtypes,
|
|
935
|
-
|
|
936
|
+
allCustomTypes: CustomType[],
|
|
936
937
|
): CustomType[] {
|
|
937
938
|
return linkCustomtypes.flatMap((linkCustomtype) => {
|
|
938
|
-
return
|
|
939
|
+
return allCustomTypes.find((ct) => ct.id === getId(linkCustomtype)) ?? [];
|
|
939
940
|
});
|
|
940
941
|
}
|
|
941
942
|
|
|
@@ -943,92 +944,281 @@ function resolveContentRelationshipCustomTypes(
|
|
|
943
944
|
* Converts a Link config `customtypes` ({@link LinkCustomtypes}) structure into
|
|
944
945
|
* picker fields check map ({@link PickerCustomTypes}).
|
|
945
946
|
*/
|
|
946
|
-
export function convertLinkCustomtypesToFieldCheckMap(
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
947
|
+
export function convertLinkCustomtypesToFieldCheckMap(args: {
|
|
948
|
+
linkCustomtypes: LinkCustomtypes;
|
|
949
|
+
allCustomTypes?: CustomType[];
|
|
950
|
+
}): PickerCustomTypes {
|
|
951
|
+
const { linkCustomtypes, allCustomTypes } = args;
|
|
952
|
+
|
|
953
|
+
// If allCustomTypes is undefined, avoid checking if the fields exist.
|
|
954
|
+
const shouldValidate = allCustomTypes !== undefined;
|
|
955
|
+
|
|
956
|
+
const checkMap = linkCustomtypes.reduce<PickerCustomTypes>(
|
|
957
|
+
(customTypes, customType) => {
|
|
958
|
+
if (typeof customType === "string") return customTypes;
|
|
959
|
+
|
|
960
|
+
let ctFlatFieldMap: Record<string, NestableWidget | Group> = {};
|
|
961
|
+
|
|
962
|
+
if (shouldValidate) {
|
|
963
|
+
const existingCt = allCustomTypes.find((c) => c.id === customType.id);
|
|
964
|
+
// Exit early if the custom type doesn't exist
|
|
965
|
+
if (!existingCt) return customTypes;
|
|
966
|
+
|
|
967
|
+
ctFlatFieldMap = getCustomTypeStaticFieldsMap(existingCt);
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
const customTypeFields = customType.fields.reduce<PickerCustomType>(
|
|
971
|
+
(fields, field) => {
|
|
972
|
+
// Check if the field exists (only if validating)
|
|
973
|
+
const existingField = ctFlatFieldMap[getId(field)];
|
|
974
|
+
if (shouldValidate && existingField === undefined) return fields;
|
|
975
|
+
|
|
955
976
|
// Regular field
|
|
956
|
-
|
|
957
|
-
|
|
977
|
+
if (typeof field === "string") {
|
|
978
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
979
|
+
if (
|
|
980
|
+
shouldValidate &&
|
|
981
|
+
existingField !== undefined &&
|
|
982
|
+
existingField.type === "Group"
|
|
983
|
+
) {
|
|
984
|
+
return fields;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
fields[field] = { type: "checkbox", value: true };
|
|
988
|
+
return fields;
|
|
989
|
+
}
|
|
990
|
+
|
|
958
991
|
// Group field
|
|
959
|
-
|
|
960
|
-
|
|
992
|
+
if ("fields" in field && field.fields !== undefined) {
|
|
993
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
994
|
+
if (
|
|
995
|
+
shouldValidate &&
|
|
996
|
+
existingField !== undefined &&
|
|
997
|
+
existingField.type !== "Group"
|
|
998
|
+
) {
|
|
999
|
+
return fields;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
const groupFieldCheckMap = createGroupFieldCheckMap({
|
|
1003
|
+
group: field,
|
|
1004
|
+
allCustomTypes,
|
|
1005
|
+
ctFlatFieldMap,
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
if (groupFieldCheckMap) {
|
|
1009
|
+
fields[field.id] = groupFieldCheckMap;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
return fields;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
961
1015
|
// Content relationship field
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1016
|
+
if ("customtypes" in field && field.customtypes !== undefined) {
|
|
1017
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1018
|
+
if (
|
|
1019
|
+
shouldValidate &&
|
|
1020
|
+
existingField !== undefined &&
|
|
1021
|
+
!isContentRelationshipField(existingField)
|
|
1022
|
+
) {
|
|
1023
|
+
return fields;
|
|
1024
|
+
}
|
|
965
1025
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1026
|
+
const crFieldCheckMap = createContentRelationshipFieldCheckMap({
|
|
1027
|
+
field,
|
|
1028
|
+
allCustomTypes,
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
if (crFieldCheckMap) {
|
|
1032
|
+
fields[field.id] = crFieldCheckMap;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
return fields;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
return fields;
|
|
1039
|
+
},
|
|
1040
|
+
{},
|
|
1041
|
+
);
|
|
1042
|
+
|
|
1043
|
+
if (Object.keys(customTypeFields).length > 0) {
|
|
1044
|
+
customTypes[customType.id] = customTypeFields;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
return customTypes;
|
|
1048
|
+
},
|
|
1049
|
+
{},
|
|
1050
|
+
);
|
|
1051
|
+
|
|
1052
|
+
return checkMap;
|
|
972
1053
|
}
|
|
973
1054
|
|
|
974
|
-
function createGroupFieldCheckMap(
|
|
975
|
-
group: LinkCustomtypesGroupFieldValue
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1055
|
+
function createGroupFieldCheckMap(args: {
|
|
1056
|
+
group: LinkCustomtypesGroupFieldValue;
|
|
1057
|
+
allCustomTypes?: CustomType[];
|
|
1058
|
+
ctFlatFieldMap: Record<string, NestableWidget | Group>;
|
|
1059
|
+
}): PickerFirstLevelGroupField | undefined {
|
|
1060
|
+
const { group, ctFlatFieldMap, allCustomTypes } = args;
|
|
1061
|
+
|
|
1062
|
+
// If allCustomTypes is undefined, avoid checking if the fields exist.
|
|
1063
|
+
const shouldValidate = allCustomTypes !== undefined;
|
|
1064
|
+
|
|
1065
|
+
const fieldEntries = group.fields.reduce<PickerFirstLevelGroupFieldValue>(
|
|
1066
|
+
(fields, field) => {
|
|
1067
|
+
// Check if the field exists (only if validating)
|
|
1068
|
+
const existingField = getGroupFieldFromMap(
|
|
1069
|
+
ctFlatFieldMap,
|
|
1070
|
+
group.id,
|
|
1071
|
+
getId(field),
|
|
1072
|
+
);
|
|
1073
|
+
if (shouldValidate && !existingField) return fields;
|
|
1074
|
+
|
|
1075
|
+
// Regular field
|
|
1076
|
+
if (typeof field === "string") {
|
|
1077
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1078
|
+
if (
|
|
1079
|
+
shouldValidate &&
|
|
1080
|
+
existingField !== undefined &&
|
|
1081
|
+
existingField.type === "Group"
|
|
1082
|
+
) {
|
|
1083
|
+
return fields;
|
|
987
1084
|
}
|
|
988
1085
|
|
|
1086
|
+
fields[field] = { type: "checkbox", value: true };
|
|
989
1087
|
return fields;
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
// Content relationship field
|
|
1091
|
+
if ("customtypes" in field && field.customtypes !== undefined) {
|
|
1092
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1093
|
+
if (
|
|
1094
|
+
shouldValidate &&
|
|
1095
|
+
existingField !== undefined &&
|
|
1096
|
+
!isContentRelationshipField(existingField)
|
|
1097
|
+
) {
|
|
1098
|
+
return fields;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
const crFieldCheckMap = createContentRelationshipFieldCheckMap({
|
|
1102
|
+
field,
|
|
1103
|
+
allCustomTypes,
|
|
1104
|
+
});
|
|
1105
|
+
|
|
1106
|
+
if (crFieldCheckMap) {
|
|
1107
|
+
fields[field.id] = crFieldCheckMap;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
return fields;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
return fields;
|
|
1114
|
+
},
|
|
1115
|
+
{},
|
|
1116
|
+
);
|
|
1117
|
+
|
|
1118
|
+
if (Object.keys(fieldEntries).length === 0) return undefined;
|
|
1119
|
+
|
|
1120
|
+
return {
|
|
1121
|
+
type: "group",
|
|
1122
|
+
value: fieldEntries,
|
|
993
1123
|
};
|
|
994
1124
|
}
|
|
995
1125
|
|
|
996
|
-
function createContentRelationshipFieldCheckMap(
|
|
997
|
-
field: LinkCustomtypesContentRelationshipFieldValue
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
value: {},
|
|
1002
|
-
};
|
|
1003
|
-
const crFieldCustomTypes = crField.value;
|
|
1126
|
+
function createContentRelationshipFieldCheckMap(args: {
|
|
1127
|
+
field: LinkCustomtypesContentRelationshipFieldValue;
|
|
1128
|
+
allCustomTypes?: CustomType[];
|
|
1129
|
+
}): PickerContentRelationshipField | undefined {
|
|
1130
|
+
const { field, allCustomTypes } = args;
|
|
1004
1131
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1132
|
+
// If allCustomTypes is undefined, avoid checking if the fields exists.
|
|
1133
|
+
const shouldValidate = allCustomTypes !== undefined;
|
|
1007
1134
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1135
|
+
const fieldEntries =
|
|
1136
|
+
field.customtypes.reduce<PickerContentRelationshipFieldValue>(
|
|
1137
|
+
(customTypes, customType) => {
|
|
1138
|
+
if (typeof customType === "string") return customTypes;
|
|
1010
1139
|
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
(
|
|
1140
|
+
let ctFlatFieldMap: Record<string, NestableWidget | Group> = {};
|
|
1141
|
+
|
|
1142
|
+
if (shouldValidate) {
|
|
1143
|
+
const existingCt = allCustomTypes.find((c) => c.id === customType.id);
|
|
1144
|
+
// Exit early if the custom type doesn't exist
|
|
1145
|
+
if (!existingCt) return customTypes;
|
|
1146
|
+
|
|
1147
|
+
ctFlatFieldMap = getCustomTypeStaticFieldsMap(existingCt);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
const ctFields = customType.fields.reduce<PickerNestedCustomTypeValue>(
|
|
1151
|
+
(nestedFields, nestedField) => {
|
|
1152
|
+
// Regular field
|
|
1153
|
+
if (typeof nestedField === "string") {
|
|
1154
|
+
const existingField = ctFlatFieldMap[nestedField];
|
|
1155
|
+
|
|
1156
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1157
|
+
if (
|
|
1158
|
+
shouldValidate &&
|
|
1159
|
+
(existingField === undefined || existingField.type === "Group")
|
|
1160
|
+
) {
|
|
1161
|
+
return nestedFields;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
nestedFields[nestedField] = { type: "checkbox", value: true };
|
|
1165
|
+
return nestedFields;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
if ("fields" in nestedField && nestedField.fields !== undefined) {
|
|
1169
|
+
// Group field
|
|
1170
|
+
const groupFields =
|
|
1171
|
+
nestedField.fields.reduce<PickerLeafGroupFieldValue>(
|
|
1172
|
+
(groupFields, groupField) => {
|
|
1173
|
+
const existingField = getGroupFieldFromMap(
|
|
1174
|
+
ctFlatFieldMap,
|
|
1175
|
+
nestedField.id,
|
|
1176
|
+
groupField,
|
|
1177
|
+
);
|
|
1178
|
+
|
|
1179
|
+
// Check if the field matched the existing one in the custom type (only if validating)
|
|
1180
|
+
if (
|
|
1181
|
+
shouldValidate &&
|
|
1182
|
+
(existingField === undefined ||
|
|
1183
|
+
existingField.type === "Group")
|
|
1184
|
+
) {
|
|
1185
|
+
return groupFields;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
groupFields[groupField] = { type: "checkbox", value: true };
|
|
1189
|
+
return groupFields;
|
|
1190
|
+
},
|
|
1191
|
+
{},
|
|
1192
|
+
);
|
|
1193
|
+
|
|
1194
|
+
if (Object.keys(groupFields).length > 0) {
|
|
1195
|
+
nestedFields[nestedField.id] = {
|
|
1196
|
+
type: "group",
|
|
1197
|
+
value: groupFields,
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
return nestedFields;
|
|
1203
|
+
},
|
|
1204
|
+
{},
|
|
1019
1205
|
);
|
|
1020
1206
|
|
|
1021
|
-
if (
|
|
1022
|
-
|
|
1023
|
-
type: "group",
|
|
1024
|
-
value: Object.fromEntries(groupFieldsEntries),
|
|
1025
|
-
};
|
|
1207
|
+
if (Object.keys(ctFields).length > 0) {
|
|
1208
|
+
customTypes[customType.id] = ctFields;
|
|
1026
1209
|
}
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
1210
|
|
|
1031
|
-
|
|
1211
|
+
return customTypes;
|
|
1212
|
+
},
|
|
1213
|
+
{},
|
|
1214
|
+
);
|
|
1215
|
+
|
|
1216
|
+
if (Object.keys(fieldEntries).length === 0) return undefined;
|
|
1217
|
+
|
|
1218
|
+
return {
|
|
1219
|
+
type: "contentRelationship",
|
|
1220
|
+
value: fieldEntries,
|
|
1221
|
+
};
|
|
1032
1222
|
}
|
|
1033
1223
|
|
|
1034
1224
|
/**
|
|
@@ -1037,27 +1227,22 @@ function createContentRelationshipFieldCheckMap(
|
|
|
1037
1227
|
* made correctly and that the order is preserved.
|
|
1038
1228
|
*/
|
|
1039
1229
|
function mergeAndConvertCheckMapToLinkCustomtypes(args: {
|
|
1040
|
-
|
|
1041
|
-
|
|
1230
|
+
linkCustomtypes: LinkCustomtypes | undefined;
|
|
1231
|
+
fieldCheckMap: PickerCustomTypes;
|
|
1042
1232
|
newCustomType: PickerCustomType;
|
|
1043
1233
|
customTypeId: string;
|
|
1044
1234
|
}): LinkCustomtypes {
|
|
1045
|
-
const {
|
|
1046
|
-
existingLinkCustomtypes,
|
|
1047
|
-
previousPickerCustomtypes,
|
|
1048
|
-
newCustomType,
|
|
1049
|
-
customTypeId,
|
|
1050
|
-
} = args;
|
|
1235
|
+
const { linkCustomtypes, fieldCheckMap, newCustomType, customTypeId } = args;
|
|
1051
1236
|
|
|
1052
1237
|
const result: NonReadonly<LinkCustomtypes> = [];
|
|
1053
1238
|
const pickerLinkCustomtypes = convertFieldCheckMapToLinkCustomtypes({
|
|
1054
|
-
...
|
|
1239
|
+
...fieldCheckMap,
|
|
1055
1240
|
[customTypeId]: newCustomType,
|
|
1056
1241
|
});
|
|
1057
1242
|
|
|
1058
|
-
if (!
|
|
1243
|
+
if (!linkCustomtypes) return pickerLinkCustomtypes;
|
|
1059
1244
|
|
|
1060
|
-
for (const existingLinkCt of
|
|
1245
|
+
for (const existingLinkCt of linkCustomtypes) {
|
|
1061
1246
|
const existingPickerLinkCt = pickerLinkCustomtypes.find((ct) => {
|
|
1062
1247
|
return getId(ct) === getId(existingLinkCt);
|
|
1063
1248
|
});
|
|
@@ -1229,6 +1414,10 @@ export function countPickedFields(
|
|
|
1229
1414
|
);
|
|
1230
1415
|
}
|
|
1231
1416
|
|
|
1417
|
+
function isContentRelationshipField(field: DynamicWidget): field is Link {
|
|
1418
|
+
return field.type === "Link" && field.config?.select === "document";
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1232
1421
|
/**
|
|
1233
1422
|
* Check if the field is a Content Relationship Link with a **single** custom
|
|
1234
1423
|
* type. CRs with multiple custom types are not currently supported (legacy).
|
|
@@ -1237,34 +1426,65 @@ function isContentRelationshipFieldWithSingleCustomtype(
|
|
|
1237
1426
|
field: NestableWidget | Group,
|
|
1238
1427
|
): field is Link {
|
|
1239
1428
|
return !!(
|
|
1240
|
-
field
|
|
1241
|
-
field.config?.select === "document" &&
|
|
1429
|
+
isContentRelationshipField(field) &&
|
|
1242
1430
|
field.config?.customtypes &&
|
|
1243
1431
|
field.config.customtypes.length === 1
|
|
1244
1432
|
);
|
|
1245
1433
|
}
|
|
1246
1434
|
|
|
1247
|
-
|
|
1435
|
+
/**
|
|
1436
|
+
* Flattens all custom type tabs and fields into an array of [fieldId, field] tuples.
|
|
1437
|
+
* Also filters out invalid fields.
|
|
1438
|
+
*/
|
|
1439
|
+
function getCustomTypeStaticFields(
|
|
1440
|
+
customType: CustomType,
|
|
1441
|
+
): [fieldId: string, field: NestableWidget | Group][] {
|
|
1248
1442
|
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
|
-
});
|
|
1443
|
+
return Object.entries(tabFields).flatMap<[string, NestableWidget | Group]>(
|
|
1444
|
+
([fieldId, field]) => {
|
|
1445
|
+
return isValidField(fieldId, field) ? [[fieldId, field]] : [];
|
|
1446
|
+
},
|
|
1447
|
+
);
|
|
1265
1448
|
});
|
|
1266
1449
|
}
|
|
1267
1450
|
|
|
1451
|
+
/**
|
|
1452
|
+
* Flattens all custom type tabs and fields into a map of field ids to fields.
|
|
1453
|
+
* Also filters out invalid fields.
|
|
1454
|
+
*/
|
|
1455
|
+
function getCustomTypeStaticFieldsMap(
|
|
1456
|
+
customType: CustomType,
|
|
1457
|
+
): Record<string, NestableWidget | Group> {
|
|
1458
|
+
return Object.fromEntries(getCustomTypeStaticFields(customType));
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
function getGroupFieldFromMap(
|
|
1462
|
+
flattenFields: Record<string, NestableWidget | Group>,
|
|
1463
|
+
groupId: string,
|
|
1464
|
+
fieldId: string,
|
|
1465
|
+
) {
|
|
1466
|
+
const group = flattenFields[groupId];
|
|
1467
|
+
if (group === undefined || group.type !== "Group") return undefined;
|
|
1468
|
+
return group.config?.fields?.[fieldId];
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
function isValidField(
|
|
1472
|
+
fieldId: string,
|
|
1473
|
+
field: DynamicWidget,
|
|
1474
|
+
): field is NestableWidget | Group {
|
|
1475
|
+
return (
|
|
1476
|
+
field.type !== "Slices" &&
|
|
1477
|
+
field.type !== "Choice" &&
|
|
1478
|
+
// We don't display uid fields because they're a special field returned by
|
|
1479
|
+
// the API and they're not included in the document data object.
|
|
1480
|
+
// We also filter by key "uid", because (as of the time of writing this)
|
|
1481
|
+
// creating any field with that API id will result in it being used for
|
|
1482
|
+
// metadata, regardless of its type.
|
|
1483
|
+
field.type !== "UID" &&
|
|
1484
|
+
fieldId !== "uid"
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1268
1488
|
function getGroupFields(group: Group) {
|
|
1269
1489
|
if (!group.config?.fields) return [];
|
|
1270
1490
|
return Object.entries(group.config.fields).map(([fieldId, field]) => {
|