@webbio/strapi-plugin-page-builder 0.13.0-platform → 0.14.1-platform
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/README.md +12 -3
- package/admin/src/api/search-filtered-entity.ts +6 -2
- package/admin/src/components/PlatformFilteredSelectField/Multi/index.tsx +12 -6
- package/admin/src/components/PlatformFilteredSelectField/Single/index.tsx +12 -6
- package/admin/src/components/PlatformFilteredSelectField/hooks/useRelationLoad.tsx +1 -1
- package/admin/src/components/PlatformFilteredSelectField/index.tsx +7 -1
- package/admin/src/components/PlatformFilteredSelectField/styles.tsx +1 -1
- package/admin/src/components/PlatformFilteredSelectField/utils/get-condition-filters.ts +82 -0
- package/admin/src/components/PlatformFilteredSelectField/utils/relation-helper.ts +23 -8
- package/admin/src/components/StrapiCore/admin/admin/src/content-manager/components/Relations/RelationInput.tsx +4 -6
- package/admin/src/components/StrapiCore/admin/admin/src/content-manager/components/Relations/utils/normalizeRelations.ts +1 -0
- package/admin/src/utils/isJson.ts +9 -0
- package/dist/package.json +1 -1
- package/dist/tsconfig.server.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,14 +134,23 @@ Ik wil een lijst van vacature relaties selecteren. Deze vacatures moeten van het
|
|
|
134
134
|
"targetField": "vacatures",
|
|
135
135
|
// (Default: undefined) Adds filters to the $and query for result filtering
|
|
136
136
|
"customFilters": [{ "title": { "$contains": "Hoi" } }],
|
|
137
|
-
// (Default:
|
|
137
|
+
// (Default: false). Disables result filtering by globally selected platform
|
|
138
138
|
"disablePlatformFilter": boolean,
|
|
139
139
|
// (Default: false) Hides id of the entity that is edited if it's the same as the targetField uid. So if this is enabled on a vacancy entity and also targets other vacancies, the current vacancy that is edited will not be shown.
|
|
140
140
|
"hideSameEntity": boolean,
|
|
141
141
|
// (Default: ['title']) Defines searchable fields
|
|
142
142
|
"searchableFields": string[],
|
|
143
|
-
// If set the field will show a subtitle with the value that results in following this path.
|
|
144
|
-
"subTitlePath": string
|
|
143
|
+
// (Default: undefined) If set the field will show a subtitle with the value that results in following this path.
|
|
144
|
+
"subTitlePath": string,
|
|
145
|
+
// (Default: undefined)
|
|
146
|
+
// Conditional filters add the posibility to who results based on values from other fields.
|
|
147
|
+
// For now this only works for fields on the same level as the targetfield.
|
|
148
|
+
// The value found will be replacing the '${value}' string.
|
|
149
|
+
"conditionalFilters": {
|
|
150
|
+
"targetField": string,
|
|
151
|
+
"targetFieldKey": string,
|
|
152
|
+
"filter": [{ "title": { "$contains": "${value}" } }]
|
|
153
|
+
}[];
|
|
145
154
|
}
|
|
146
155
|
},
|
|
147
156
|
"type": "customField",
|
|
@@ -4,6 +4,7 @@ import objGet from 'lodash/get';
|
|
|
4
4
|
|
|
5
5
|
import { useFetchClient } from '@strapi/helper-plugin';
|
|
6
6
|
import qs from 'qs';
|
|
7
|
+
import { getConditionalFilters } from '../components/PlatformFilteredSelectField/utils/get-condition-filters';
|
|
7
8
|
|
|
8
9
|
export type SearchFilteredEntitiesResult = {
|
|
9
10
|
pagination: {
|
|
@@ -34,6 +35,7 @@ type SearchFilteredEntitiesQueryParams = {
|
|
|
34
35
|
searchableFields?: string[];
|
|
35
36
|
subTitlePath?: string;
|
|
36
37
|
mainFieldName?: string;
|
|
38
|
+
conditionalFilters?: Record<string, any>[];
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
const QUERY_KEY = 'filteredEntities';
|
|
@@ -49,7 +51,8 @@ export const getSearchFilteredEntities = async ({
|
|
|
49
51
|
customFilters,
|
|
50
52
|
searchableFields = ['title'],
|
|
51
53
|
subTitlePath,
|
|
52
|
-
mainFieldName = 'title'
|
|
54
|
+
mainFieldName = 'title',
|
|
55
|
+
conditionalFilters = []
|
|
53
56
|
}: SearchFilteredEntitiesQueryParams): Promise<SearchFilteredEntitiesResult> => {
|
|
54
57
|
try {
|
|
55
58
|
const { get } = fetchClient;
|
|
@@ -71,7 +74,8 @@ export const getSearchFilteredEntities = async ({
|
|
|
71
74
|
$or: fieldFilters
|
|
72
75
|
},
|
|
73
76
|
...notIdFilters,
|
|
74
|
-
...customFilterObject
|
|
77
|
+
...customFilterObject,
|
|
78
|
+
...conditionalFilters
|
|
75
79
|
]
|
|
76
80
|
}
|
|
77
81
|
});
|
|
@@ -14,6 +14,7 @@ import { useGetLocaleFromUrl } from '../../../utils/hooks/useGetLocaleFromUrl';
|
|
|
14
14
|
import { getSearchFilteredEntities } from '../../../api/search-filtered-entity';
|
|
15
15
|
import RelationHelper, { IPlatformFilteredSelectFieldProps } from '../utils/relation-helper';
|
|
16
16
|
import { getTranslation } from '../utils/get-translations';
|
|
17
|
+
import { getConditionalFilters } from '../utils/get-condition-filters';
|
|
17
18
|
|
|
18
19
|
const PAGE = 1;
|
|
19
20
|
|
|
@@ -72,11 +73,7 @@ const MultiPlatformFilteredSelectField = ({
|
|
|
72
73
|
const { formatMessage } = useIntl();
|
|
73
74
|
|
|
74
75
|
const { targetAttributes, targetFieldValue, targetField, relationMainFieldName } = RelationHelper.getTargetAttributes(
|
|
75
|
-
name,
|
|
76
|
-
attribute,
|
|
77
|
-
modifiedData,
|
|
78
|
-
layout,
|
|
79
|
-
allLayoutData
|
|
76
|
+
{ fieldName: name, attribute, modifiedData, layout, allLayoutData }
|
|
80
77
|
);
|
|
81
78
|
|
|
82
79
|
const label = intlLabel?.id
|
|
@@ -92,6 +89,14 @@ const MultiPlatformFilteredSelectField = ({
|
|
|
92
89
|
}, [targetFieldValue]);
|
|
93
90
|
|
|
94
91
|
const getItems = async (inputValue?: string) => {
|
|
92
|
+
const conditionalFilters = getConditionalFilters({
|
|
93
|
+
fieldName: name,
|
|
94
|
+
allLayoutData,
|
|
95
|
+
attribute,
|
|
96
|
+
layout,
|
|
97
|
+
modifiedData
|
|
98
|
+
});
|
|
99
|
+
|
|
95
100
|
const entities = await getSearchFilteredEntities({
|
|
96
101
|
fetchClient,
|
|
97
102
|
page: PAGE,
|
|
@@ -103,7 +108,8 @@ const MultiPlatformFilteredSelectField = ({
|
|
|
103
108
|
customFilters: attribute?.pluginOptions?.filteredSelect?.customFilters,
|
|
104
109
|
searchableFields: attribute?.pluginOptions?.filteredSelect?.searchableFields,
|
|
105
110
|
subTitlePath: attribute?.pluginOptions?.filteredSelect?.subTitlePath,
|
|
106
|
-
mainFieldName: relationMainFieldName
|
|
111
|
+
mainFieldName: relationMainFieldName,
|
|
112
|
+
conditionalFilters
|
|
107
113
|
});
|
|
108
114
|
|
|
109
115
|
const mapped = entities?.results.map((x) => ({
|
|
@@ -15,6 +15,7 @@ import { getSearchFilteredEntities } from '../../../api/search-filtered-entity';
|
|
|
15
15
|
import S from './../styles';
|
|
16
16
|
import getTrad from '../../../utils/getTrad';
|
|
17
17
|
import RelationHelper, { IPlatformFilteredSelectFieldProps } from '../utils/relation-helper';
|
|
18
|
+
import { getConditionalFilters } from '../utils/get-condition-filters';
|
|
18
19
|
|
|
19
20
|
export interface ISinglePlatformFilteredSelectFieldProps extends IPlatformFilteredSelectFieldProps {}
|
|
20
21
|
|
|
@@ -53,11 +54,7 @@ const SinglePlatformFilteredSelectField = ({
|
|
|
53
54
|
const { formatMessage } = useIntl();
|
|
54
55
|
|
|
55
56
|
const { targetAttributes, targetFieldValue, targetField, relationMainFieldName } = RelationHelper.getTargetAttributes(
|
|
56
|
-
name,
|
|
57
|
-
attribute,
|
|
58
|
-
modifiedData,
|
|
59
|
-
layout,
|
|
60
|
-
allLayoutData
|
|
57
|
+
{ fieldName: name, attribute, modifiedData, layout, allLayoutData }
|
|
61
58
|
);
|
|
62
59
|
|
|
63
60
|
const label = intlLabel?.id
|
|
@@ -110,6 +107,14 @@ const SinglePlatformFilteredSelectField = ({
|
|
|
110
107
|
};
|
|
111
108
|
|
|
112
109
|
const getItems = async (inputValue?: string, platformTitle?: string): Promise<CustomReactSelectValue[]> => {
|
|
110
|
+
const conditionalFilters = getConditionalFilters({
|
|
111
|
+
fieldName: name,
|
|
112
|
+
allLayoutData,
|
|
113
|
+
attribute,
|
|
114
|
+
layout,
|
|
115
|
+
modifiedData
|
|
116
|
+
});
|
|
117
|
+
|
|
113
118
|
const pages = await getSearchFilteredEntities({
|
|
114
119
|
fetchClient,
|
|
115
120
|
page: PAGE,
|
|
@@ -121,7 +126,8 @@ const SinglePlatformFilteredSelectField = ({
|
|
|
121
126
|
notIds: hiddenId,
|
|
122
127
|
searchableFields: attribute?.pluginOptions?.filteredSelect?.searchableFields,
|
|
123
128
|
subTitlePath: attribute?.pluginOptions?.filteredSelect?.subTitlePath,
|
|
124
|
-
mainFieldName: relationMainFieldName
|
|
129
|
+
mainFieldName: relationMainFieldName,
|
|
130
|
+
conditionalFilters
|
|
125
131
|
});
|
|
126
132
|
|
|
127
133
|
return pages?.results.map((x) => ({
|
|
@@ -24,7 +24,7 @@ const useRelationLoad = ({ name, attribute }: IRelationLoadProps) => {
|
|
|
24
24
|
const entityId = origin || modifiedData.id;
|
|
25
25
|
|
|
26
26
|
const { componentUid, componentId, relationMainFieldName, targetAttributes, targetField, targetFieldName } =
|
|
27
|
-
RelationHelper.getTargetAttributes(fieldName, attribute, modifiedData, layout, allLayoutData);
|
|
27
|
+
RelationHelper.getTargetAttributes({ fieldName, attribute, modifiedData, layout, allLayoutData });
|
|
28
28
|
|
|
29
29
|
const nameSplit = targetFieldName.split('.');
|
|
30
30
|
const isComponentRelation = Boolean(componentUid);
|
|
@@ -13,7 +13,13 @@ const PlatformFilteredSelectField = (props: IPlatformFilteredSelectFieldProps) =
|
|
|
13
13
|
const { modifiedData, layout, allLayoutData } = form;
|
|
14
14
|
const { selectedPlatform } = usePlatformFormData(form);
|
|
15
15
|
const { relations, isCloningEntry, totalRelations, relationsFromModifiedData } = useRelationLoad(props);
|
|
16
|
-
const { targetAttributes } = RelationHelper.getTargetAttributes(
|
|
16
|
+
const { targetAttributes } = RelationHelper.getTargetAttributes({
|
|
17
|
+
fieldName: name,
|
|
18
|
+
attribute,
|
|
19
|
+
modifiedData,
|
|
20
|
+
layout,
|
|
21
|
+
allLayoutData
|
|
22
|
+
});
|
|
17
23
|
const toOneRelation = ['oneWay', 'oneToOne', 'manyToOne', 'oneToManyMorph', 'oneToOneMorph'].includes(
|
|
18
24
|
targetAttributes?.relation || ''
|
|
19
25
|
);
|
|
@@ -34,7 +34,7 @@ const CustomOption = styled(Box)`
|
|
|
34
34
|
const CustomOptionSubTitle = styled(Box)`
|
|
35
35
|
${({ theme, disabled }) => css`
|
|
36
36
|
font-size: ${theme.fontSizes[1]};
|
|
37
|
-
|
|
37
|
+
color: ${theme.colors.neutral400};
|
|
38
38
|
white-space: nowrap;
|
|
39
39
|
overflow: hidden;
|
|
40
40
|
text-overflow: ellipsis;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { isJSON } from '../../../utils/isJson';
|
|
2
|
+
import RelationHelper, { IRelationHelperProps } from './relation-helper';
|
|
3
|
+
|
|
4
|
+
interface IGetConditionalFiltersProps extends IRelationHelperProps {}
|
|
5
|
+
|
|
6
|
+
export const getConditionalFilters = ({
|
|
7
|
+
attribute,
|
|
8
|
+
modifiedData,
|
|
9
|
+
layout,
|
|
10
|
+
allLayoutData,
|
|
11
|
+
fieldName
|
|
12
|
+
}: IGetConditionalFiltersProps): Record<string, any>[] => {
|
|
13
|
+
const conditionalFilters = (attribute?.pluginOptions?.filteredSelect?.conditionalFilters || []).filter(
|
|
14
|
+
(x) => x.filter && x.targetField
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const filters: Record<string, any>[] = [];
|
|
18
|
+
|
|
19
|
+
for (const { targetField, filter, targetFieldKey } of conditionalFilters) {
|
|
20
|
+
const completeFieldNamePath = (fieldName || '').split('.');
|
|
21
|
+
completeFieldNamePath.pop();
|
|
22
|
+
completeFieldNamePath.push(targetField || '');
|
|
23
|
+
const { targetFieldValue } = RelationHelper.getTargetAttributes({
|
|
24
|
+
fieldName,
|
|
25
|
+
attribute,
|
|
26
|
+
modifiedData,
|
|
27
|
+
layout,
|
|
28
|
+
allLayoutData,
|
|
29
|
+
customTargetField: targetField
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const value = getTargetFieldValue(targetFieldValue, targetFieldKey);
|
|
33
|
+
|
|
34
|
+
// If the value is an array, we need to create an OR filter
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
const orFilters: { $or: Record<string, any>[] } = {
|
|
37
|
+
$or: []
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
for (const val of value) {
|
|
41
|
+
const filterReplacement = replaceObj(filter, val);
|
|
42
|
+
if (val && filterReplacement) {
|
|
43
|
+
orFilters.$or.push(filterReplacement);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
filters.push(orFilters);
|
|
47
|
+
} else {
|
|
48
|
+
const filterReplacement = replaceObj(filter, value);
|
|
49
|
+
|
|
50
|
+
if (value) {
|
|
51
|
+
filters.push(filterReplacement);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return filters.filter(Boolean);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const getTargetFieldValue = (targetFieldValue?: any, targetFieldKey?: string): any => {
|
|
60
|
+
const key = targetFieldKey || 'id';
|
|
61
|
+
|
|
62
|
+
if (typeof targetFieldValue !== 'object' || !targetFieldValue) {
|
|
63
|
+
return targetFieldValue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (Array.isArray(targetFieldValue)) {
|
|
67
|
+
return targetFieldValue.map((x) => x?.[key]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return targetFieldValue?.[key];
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const replaceObj = (filter?: Record<string, any>, value?: string) => {
|
|
74
|
+
const stringFilter = JSON.stringify(filter || {}).replaceAll('${value}', value || '');
|
|
75
|
+
const json = isJSON(stringFilter);
|
|
76
|
+
|
|
77
|
+
if (!json) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return JSON.parse(stringFilter);
|
|
82
|
+
};
|
|
@@ -31,6 +31,11 @@ export interface IPlatformFilteredSelectFieldProps {
|
|
|
31
31
|
hideSameEntity?: boolean;
|
|
32
32
|
searchableFields?: string[];
|
|
33
33
|
subTitlePath?: string;
|
|
34
|
+
conditionalFilters?: {
|
|
35
|
+
targetField?: string;
|
|
36
|
+
targetFieldKey?: string;
|
|
37
|
+
filter?: Record<string, any>;
|
|
38
|
+
}[];
|
|
34
39
|
};
|
|
35
40
|
};
|
|
36
41
|
required?: boolean;
|
|
@@ -48,16 +53,26 @@ export interface IPlatformFilteredSelectFieldProps {
|
|
|
48
53
|
hiddenId?: number[];
|
|
49
54
|
}
|
|
50
55
|
|
|
56
|
+
export interface IRelationHelperProps {
|
|
57
|
+
fieldName?: string;
|
|
58
|
+
attribute?: IPlatformFilteredSelectFieldProps['attribute'];
|
|
59
|
+
modifiedData?: Record<string, any>;
|
|
60
|
+
layout?: Record<string, any>;
|
|
61
|
+
allLayoutData?: Record<string, any>;
|
|
62
|
+
customTargetField?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
51
65
|
const RelationHelper = {
|
|
52
|
-
getTargetAttributes: (
|
|
53
|
-
fieldName
|
|
54
|
-
attribute
|
|
55
|
-
modifiedData
|
|
56
|
-
layout
|
|
57
|
-
allLayoutData
|
|
58
|
-
|
|
66
|
+
getTargetAttributes: ({
|
|
67
|
+
fieldName = '',
|
|
68
|
+
attribute,
|
|
69
|
+
modifiedData,
|
|
70
|
+
layout,
|
|
71
|
+
allLayoutData,
|
|
72
|
+
customTargetField
|
|
73
|
+
}: IRelationHelperProps) => {
|
|
59
74
|
const lastFieldName = fieldName?.split('.')?.[fieldName?.split('.')?.length - 1];
|
|
60
|
-
const targetField = attribute?.pluginOptions?.filteredSelect?.targetField || fieldName || '';
|
|
75
|
+
const targetField = customTargetField || attribute?.pluginOptions?.filteredSelect?.targetField || fieldName || '';
|
|
61
76
|
const targetFieldName = (fieldName || '')?.replace(lastFieldName || '', targetField);
|
|
62
77
|
const component = getComponent(targetFieldName, modifiedData, allLayoutData);
|
|
63
78
|
const result: GetTargetAttributesResult = {
|
|
@@ -312,8 +312,7 @@ const RelationInput = ({
|
|
|
312
312
|
onRelationDisconnect,
|
|
313
313
|
publicationStateTranslations,
|
|
314
314
|
relations,
|
|
315
|
-
updatePositionOfRelation: handleUpdatePositionOfRelation
|
|
316
|
-
subTitle: 'ho'
|
|
315
|
+
updatePositionOfRelation: handleUpdatePositionOfRelation
|
|
317
316
|
}}
|
|
318
317
|
itemKey={(index) => `${relations[index].mainField}_${relations[index].id}`}
|
|
319
318
|
innerElementType="ol"
|
|
@@ -452,7 +451,6 @@ interface ListItemProps extends Pick<RelationItemProps, 'index' | 'style'> {
|
|
|
452
451
|
published: string;
|
|
453
452
|
};
|
|
454
453
|
relations: NormalizedRelation[];
|
|
455
|
-
subTitle?: string;
|
|
456
454
|
};
|
|
457
455
|
}
|
|
458
456
|
|
|
@@ -472,7 +470,7 @@ const ListItem = ({ data, index, style }: ListItemProps) => {
|
|
|
472
470
|
relations,
|
|
473
471
|
updatePositionOfRelation
|
|
474
472
|
} = data;
|
|
475
|
-
const { publicationState, href, mainField, id } = relations[index];
|
|
473
|
+
const { publicationState, href, mainField, id, subTitle } = relations[index];
|
|
476
474
|
const statusColor = publicationState === 'draft' ? 'secondary' : 'success';
|
|
477
475
|
|
|
478
476
|
return (
|
|
@@ -512,14 +510,14 @@ const ListItem = ({ data, index, style }: ListItemProps) => {
|
|
|
512
510
|
{href ? (
|
|
513
511
|
<Flex direction="column" alignItems="start" gap={0}>
|
|
514
512
|
<LinkEllipsis to={href}>{mainField ?? id}</LinkEllipsis>
|
|
515
|
-
{
|
|
513
|
+
{subTitle && <S.CustomOptionSubTitle>{subTitle}</S.CustomOptionSubTitle>}
|
|
516
514
|
</Flex>
|
|
517
515
|
) : (
|
|
518
516
|
<Flex direction="column" alignItems="start" gap={0}>
|
|
519
517
|
<Typography textColor={disabled ? 'neutral600' : 'primary600'} ellipsis>
|
|
520
518
|
{mainField ?? id}
|
|
521
519
|
</Typography>
|
|
522
|
-
{
|
|
520
|
+
{subTitle && <S.CustomOptionSubTitle>{subTitle}</S.CustomOptionSubTitle>}
|
|
523
521
|
</Flex>
|
|
524
522
|
)}
|
|
525
523
|
</Tooltip>
|
package/dist/package.json
CHANGED