@webbio/strapi-plugin-page-builder 0.12.8-platform → 0.14.0-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.
@@ -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
+ };
@@ -1,6 +1,7 @@
1
1
  import { IntlFormatters, MessageDescriptor } from '@formatjs/intl';
2
2
  import get from 'lodash/get';
3
3
  import { pointPathToGetPath } from '../../../utils/getObjectFromFormName';
4
+ import { Platform } from '../../../api/platform';
4
5
 
5
6
  export interface GetTargetAttributesResult {
6
7
  targetAttributes?: {
@@ -28,6 +29,13 @@ export interface IPlatformFilteredSelectFieldProps {
28
29
  customFilters?: Record<string, any>[];
29
30
  disablePlatformFilter?: boolean;
30
31
  hideSameEntity?: boolean;
32
+ searchableFields?: string[];
33
+ subTitlePath?: string;
34
+ conditionalFilters?: {
35
+ targetField?: string;
36
+ targetFieldKey?: string;
37
+ filter?: Record<string, any>;
38
+ }[];
31
39
  };
32
40
  };
33
41
  required?: boolean;
@@ -41,20 +49,31 @@ export interface IPlatformFilteredSelectFieldProps {
41
49
  value?: string;
42
50
  contentTypeUID?: string;
43
51
  placeholder?: MessageDescriptor & Parameters<IntlFormatters['formatMessage']>;
52
+ selectedPlatform?: Platform;
53
+ hiddenId?: number[];
54
+ }
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;
44
63
  }
45
64
 
46
65
  const RelationHelper = {
47
- getTargetAttributes: (
48
- fieldName?: string,
49
- attribute?: IPlatformFilteredSelectFieldProps['attribute'],
50
- modifiedData?: Record<string, any>,
51
- layout?: Record<string, any>,
52
- allLayoutData?: Record<string, any>
53
- ) => {
66
+ getTargetAttributes: ({
67
+ fieldName = '',
68
+ attribute,
69
+ modifiedData,
70
+ layout,
71
+ allLayoutData,
72
+ customTargetField
73
+ }: IRelationHelperProps) => {
54
74
  const lastFieldName = fieldName?.split('.')?.[fieldName?.split('.')?.length - 1];
55
- const targetField = attribute?.pluginOptions?.filteredSelect?.targetField || fieldName || '';
75
+ const targetField = customTargetField || attribute?.pluginOptions?.filteredSelect?.targetField || fieldName || '';
56
76
  const targetFieldName = (fieldName || '')?.replace(lastFieldName || '', targetField);
57
-
58
77
  const component = getComponent(targetFieldName, modifiedData, allLayoutData);
59
78
  const result: GetTargetAttributesResult = {
60
79
  targetAttributes: undefined,
@@ -32,6 +32,7 @@ import { getTranslation } from '../../utils/translations';
32
32
  import type { NormalizedRelation } from './utils/normalizeRelations';
33
33
  import type { Contracts } from '../../../../../../content-manager/shared';
34
34
  import type { Entity } from '@strapi/types';
35
+ import S from '../../../../../../../PlatformFilteredSelectField/styles';
35
36
 
36
37
  const RELATION_ITEM_HEIGHT = 50;
37
38
  const RELATION_GUTTER = 4;
@@ -81,6 +82,7 @@ interface RelationInputProps
81
82
  hasNextPage?: boolean;
82
83
  };
83
84
  size: number;
85
+ mainField?: string;
84
86
  }
85
87
 
86
88
  const RelationInput = ({
@@ -114,6 +116,7 @@ const RelationInput = ({
114
116
  required,
115
117
  relations: paginatedRelations,
116
118
  searchResults,
119
+ mainField,
117
120
  size
118
121
  }: RelationInputProps) => {
119
122
  const [textValue, setTextValue] = React.useState<string | undefined>('');
@@ -265,9 +268,9 @@ const RelationInput = ({
265
268
  onSearch(event.currentTarget.value);
266
269
  }}
267
270
  >
268
- {options.map((opt) => {
269
- return <Option key={opt.id} {...opt} />;
270
- })}
271
+ {options.map((opt) => (
272
+ <Option key={opt.id} {...opt} />
273
+ ))}
271
274
  </Combobox>
272
275
  </ComboboxWrapper>
273
276
 
@@ -309,7 +312,8 @@ const RelationInput = ({
309
312
  onRelationDisconnect,
310
313
  publicationStateTranslations,
311
314
  relations,
312
- updatePositionOfRelation: handleUpdatePositionOfRelation
315
+ updatePositionOfRelation: handleUpdatePositionOfRelation,
316
+ subTitle: 'ho'
313
317
  }}
314
318
  itemKey={(index) => `${relations[index].mainField}_${relations[index].id}`}
315
319
  innerElementType="ol"
@@ -366,8 +370,9 @@ const ShadowBox = styled(Box)<{ overflowDirection?: 'top-bottom' | 'top' | 'bott
366
370
  const Option = ({
367
371
  publicationState,
368
372
  mainField,
369
- id
370
- }: Pick<NormalizedRelation, 'id' | 'mainField' | 'publicationState'>) => {
373
+ id,
374
+ subTitle
375
+ }: Pick<NormalizedRelation, 'id' | 'mainField' | 'publicationState'> & { subTitle?: string }) => {
371
376
  const { formatMessage } = useIntl();
372
377
  const stringifiedDisplayValue = (mainField ?? id).toString();
373
378
 
@@ -384,18 +389,32 @@ const Option = ({
384
389
  const title = isDraft ? formatMessage(draftMessage) : formatMessage(publishedMessage);
385
390
 
386
391
  return (
387
- <ComboboxOption value={id.toString()} textValue={stringifiedDisplayValue}>
392
+ <ComboboxOption
393
+ value={id.toString()}
394
+ textValue={stringifiedDisplayValue}
395
+ style={{ paddingTop: 5, paddingBottom: 5 }}
396
+ >
388
397
  <Flex>
389
398
  <StyledBullet title={title} isDraft={isDraft} />
390
- <Typography ellipsis>{stringifiedDisplayValue}</Typography>
399
+ <S.CustomOptionItemWrapper direction="column" alignItems="start">
400
+ <Typography ellipsis>{stringifiedDisplayValue}</Typography>
401
+ {subTitle && <S.CustomOptionSubTitle>{subTitle}</S.CustomOptionSubTitle>}
402
+ </S.CustomOptionItemWrapper>
391
403
  </Flex>
392
404
  </ComboboxOption>
393
405
  );
394
406
  }
395
407
 
396
408
  return (
397
- <ComboboxOption value={id.toString()} textValue={stringifiedDisplayValue}>
398
- {stringifiedDisplayValue}
409
+ <ComboboxOption
410
+ value={id.toString()}
411
+ textValue={stringifiedDisplayValue}
412
+ style={{ paddingTop: 5, paddingBottom: 5 }}
413
+ >
414
+ <S.CustomOptionItemWrapper direction="column" alignItems="start" gap={0}>
415
+ {stringifiedDisplayValue}
416
+ {subTitle && <S.CustomOptionSubTitle>{subTitle}</S.CustomOptionSubTitle>}
417
+ </S.CustomOptionItemWrapper>
399
418
  </ComboboxOption>
400
419
  );
401
420
  };
@@ -433,6 +452,7 @@ interface ListItemProps extends Pick<RelationItemProps, 'index' | 'style'> {
433
452
  published: string;
434
453
  };
435
454
  relations: NormalizedRelation[];
455
+ subTitle?: string;
436
456
  };
437
457
  }
438
458
 
@@ -487,14 +507,20 @@ const ListItem = ({ data, index, style }: ListItemProps) => {
487
507
  }}
488
508
  updatePositionOfRelation={updatePositionOfRelation}
489
509
  >
490
- <Box minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
510
+ <Box minWidth={0} paddingRight={4}>
491
511
  <Tooltip description={mainField ?? `${id}`}>
492
512
  {href ? (
493
- <LinkEllipsis to={href}>{mainField ?? id}</LinkEllipsis>
513
+ <Flex direction="column" alignItems="start" gap={0}>
514
+ <LinkEllipsis to={href}>{mainField ?? id}</LinkEllipsis>
515
+ {data?.subTitle && <S.CustomOptionSubTitle>{data.subTitle}</S.CustomOptionSubTitle>}
516
+ </Flex>
494
517
  ) : (
495
- <Typography textColor={disabled ? 'neutral600' : 'primary600'} ellipsis>
496
- {mainField ?? id}
497
- </Typography>
518
+ <Flex direction="column" alignItems="start" gap={0}>
519
+ <Typography textColor={disabled ? 'neutral600' : 'primary600'} ellipsis>
520
+ {mainField ?? id}
521
+ </Typography>
522
+ {data?.subTitle && <S.CustomOptionSubTitle>{data.subTitle}</S.CustomOptionSubTitle>}
523
+ </Flex>
498
524
  )}
499
525
  </Tooltip>
500
526
  </Box>
@@ -0,0 +1,52 @@
1
+ import { parse, stringify } from 'qs';
2
+ import { useMemo, useCallback } from 'react';
3
+ import { useLocation, useHistory } from 'react-router-dom';
4
+
5
+ interface IUseQueryParamsObj {
6
+ query: Record<string, any>;
7
+ rawQuery: string;
8
+ }
9
+
10
+ type ISetQuery = (nextParams: Record<string, any>, method?: string, routerMethod?: string) => void;
11
+
12
+ // We created this as a copy of the useQueryParams hook from the Strapi plugin
13
+ // This one however supports the replace and push methods from the useHistory hook
14
+ const useQueryParams = (initialParams?: Record<string, any>): [IUseQueryParamsObj, ISetQuery] => {
15
+ const { search } = useLocation();
16
+ const { replace, push } = useHistory();
17
+
18
+ const query = useMemo(() => {
19
+ const searchQuery = search.substring(1);
20
+ if (!search) {
21
+ return initialParams || {};
22
+ }
23
+ return parse(searchQuery);
24
+ }, [search, initialParams]);
25
+
26
+ const setQuery = useCallback(
27
+ (nextParams: Record<string, any>, method = 'push', routerMethod = 'push') => {
28
+ let nextQuery = { ...query };
29
+ if (method === 'remove') {
30
+ Object.keys(nextParams).forEach((key) => {
31
+ if (Object.prototype.hasOwnProperty.call(nextQuery, key)) {
32
+ delete nextQuery[key];
33
+ }
34
+ });
35
+ } else {
36
+ nextQuery = { ...query, ...nextParams };
37
+ }
38
+ const props = { search: stringify(nextQuery, { encode: false }) };
39
+
40
+ if (routerMethod === 'replace') {
41
+ replace(props);
42
+ } else {
43
+ push(props);
44
+ }
45
+ },
46
+ [push, replace, query]
47
+ );
48
+
49
+ return [{ query, rawQuery: search }, setQuery];
50
+ };
51
+
52
+ export { useQueryParams };
@@ -0,0 +1,9 @@
1
+ export const isJSON = (value?: string) => {
2
+ if (!value) return false;
3
+
4
+ try {
5
+ return !!(JSON.parse(value) && value);
6
+ } catch (e) {
7
+ return false;
8
+ }
9
+ };
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webbio/strapi-plugin-page-builder",
3
- "version": "0.12.8-platform",
3
+ "version": "0.14.0-platform",
4
4
  "description": "This is the description of the plugin.",
5
5
  "scripts": {
6
6
  "develop": "tsc -p tsconfig.server.json -w",
@@ -20,7 +20,7 @@ exports.default = async ({ strapi }) => {
20
20
  displayName,
21
21
  category: 'Platform',
22
22
  handler: async (x) => {
23
- var _a, _b, _c, _d;
23
+ var _a, _b, _c;
24
24
  if (((_a = x === null || x === void 0 ? void 0 : x.permission) === null || _a === void 0 ? void 0 : _a.subject) === 'api::platform.platform') {
25
25
  return {
26
26
  id: {
@@ -34,25 +34,28 @@ exports.default = async ({ strapi }) => {
34
34
  limit: -1,
35
35
  populate: '*'
36
36
  })));
37
- // checks which role the user has
38
- const foundRole = roles.filter((role) => {
39
- return x.roles.find((userRole) => userRole.name === role.name);
40
- });
37
+ // checks which roles the user has
38
+ const foundRoles = roles.filter((role) => x.roles.find((userRole) => userRole.name === role.name));
39
+ // Get all permissions from the roles the user has
40
+ const allPermissions = [foundRoles === null || foundRoles === void 0 ? void 0 : foundRoles[0]]
41
+ .map((role) => role === null || role === void 0 ? void 0 : role.permissions)
42
+ .flat()
43
+ .filter(Boolean);
41
44
  // get the right platform permissions, and filters out the platform
42
45
  // this is neccesary because of multiple platforms. if you can see Vacancy from platform 1 and collegue from platform 2
43
46
  // it will show both at page level, so this filters out the wrong page
44
- const platformPermission = (_d = foundRole === null || foundRole === void 0 ? void 0 : foundRole[0]) === null || _d === void 0 ? void 0 : _d.permissions.map((permission) => {
45
- return {
46
- permission: permission.subject,
47
- condition: permission.conditions.filter((condition) => condition.includes(platform.title))
48
- };
49
- });
50
- // get the right permission for platform
51
- const permissions = platformPermission.map((permission) => {
52
- if (permission.condition.length > 0) {
53
- return permission.permission;
47
+ const platformPermission = allPermissions.map((permission) => ({
48
+ subject: permission.subject,
49
+ conditions: permission === null || permission === void 0 ? void 0 : permission.conditions.filter((condition) => condition.includes(platform.title))
50
+ }));
51
+ // Get the right permission for platform
52
+ const permissions = platformPermission
53
+ .map((permission) => {
54
+ if (permission.conditions.length > 0) {
55
+ return permission.subject;
54
56
  }
55
- });
57
+ })
58
+ .filter(Boolean);
56
59
  const uniquePermissions = (0, uniq_1.default)(permissions);
57
60
  return {
58
61
  $and: [
@@ -8,7 +8,7 @@ exports.default = {
8
8
  return ctx.redirect(callbackUrl);
9
9
  }
10
10
  catch (error) {
11
- console.log(ctx);
11
+ console.log('Activate User Error', error, ctx);
12
12
  return ctx.unauthorized('User is already confirmed or token is invalid');
13
13
  }
14
14
  },