@webbio/strapi-plugin-page-builder 0.6.0-platform → 0.8.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.
Files changed (58) hide show
  1. package/admin/src/api/has-page-relation.ts +1 -1
  2. package/admin/src/api/has-platform-relation.ts +1 -1
  3. package/admin/src/api/platform-page-types.ts +17 -19
  4. package/admin/src/api/platform.ts +2 -2
  5. package/admin/src/api/search-filtered-entity.ts +111 -0
  6. package/admin/src/api/template.ts +10 -7
  7. package/admin/src/components/Combobox/index.tsx +8 -6
  8. package/admin/src/components/Combobox/styles.ts +13 -1
  9. package/admin/src/components/EditView/CollectionTypeSettings/CreatePageButton/index.tsx +6 -2
  10. package/admin/src/components/EditView/Details/index.tsx +1 -1
  11. package/admin/src/components/EditView/PageSettings/index.tsx +1 -1
  12. package/admin/src/components/EditView/Template/TemplateSelect/index.tsx +3 -2
  13. package/admin/src/components/EditView/Template/TemplateSelect/use-template-modules.ts +5 -2
  14. package/admin/src/components/EditView/page-type-select.tsx +1 -1
  15. package/admin/src/components/EditView/wrapper.tsx +13 -7
  16. package/admin/src/components/GlobalPlatformSelect/index.tsx +0 -1
  17. package/admin/src/components/PageFilters/PageTypeFilter/index.tsx +1 -1
  18. package/admin/src/components/PageFilters/filters.tsx +1 -1
  19. package/admin/src/components/PageFilters/index.tsx +6 -1
  20. package/admin/src/components/PageTypeEditView/PageByPlatformSelect/index.tsx +112 -0
  21. package/admin/src/components/PageTypeEditView/TemplatePlatformSelect/index.tsx +55 -0
  22. package/admin/src/components/PageTypeEditView/index.tsx +28 -0
  23. package/admin/src/components/PlatformFilteredSelectField/InputIcon/index.tsx +23 -0
  24. package/admin/src/components/PlatformFilteredSelectField/Multi/index.tsx +191 -0
  25. package/admin/src/components/PlatformFilteredSelectField/Single/index.tsx +184 -0
  26. package/admin/src/components/PlatformFilteredSelectField/hooks/useRelationLoad.tsx +124 -0
  27. package/admin/src/components/PlatformFilteredSelectField/index.tsx +43 -0
  28. package/admin/src/components/PlatformFilteredSelectField/styles.tsx +77 -0
  29. package/admin/src/components/PlatformFilteredSelectField/utils/get-translations.ts +3 -0
  30. package/admin/src/components/PlatformFilteredSelectField/utils/relation-helper.ts +76 -0
  31. package/admin/src/index.tsx +26 -0
  32. package/admin/src/translations/en.json +4 -1
  33. package/admin/src/translations/nl.json +4 -1
  34. package/admin/src/utils/getObjectFromFormName.ts +31 -0
  35. package/admin/src/utils/hooks/usePlatformFormData.ts +1 -0
  36. package/dist/package.json +3 -3
  37. package/dist/server/controllers/page-type.js +6 -2
  38. package/dist/server/register.js +5 -0
  39. package/dist/server/routes/index.js +1 -1
  40. package/dist/server/schema/page-type-end.json +15 -5
  41. package/dist/server/schema/platform-start.json +0 -10
  42. package/dist/server/schema/template-end.json +40 -0
  43. package/dist/server/services/builder.js +4 -3
  44. package/dist/server/services/page-type.js +7 -3
  45. package/dist/tsconfig.server.tsbuildinfo +1 -1
  46. package/package.json +3 -3
  47. package/server/controllers/page-type.ts +6 -1
  48. package/server/register.ts +6 -0
  49. package/server/routes/index.ts +1 -1
  50. package/server/schema/page-type-end.json +15 -5
  51. package/server/schema/platform-start.json +0 -10
  52. package/server/schema/template-end.json +40 -0
  53. package/server/services/builder.ts +4 -3
  54. package/server/services/page-type.ts +7 -3
  55. package/admin/src/api/page-type.ts +0 -32
  56. package/dist/server/graphql/page-by-slug.js +0 -82
  57. package/dist/server/utils/graphql.js +0 -100
  58. package/dist/server/utils/paginationValidation.js +0 -31
@@ -23,7 +23,7 @@ export const useHasPageRelation = (params: HasPageRelationQueryParams, options?:
23
23
 
24
24
  return useQuery<boolean, Error>(
25
25
  [
26
- QUERY_KEY,
26
+ [QUERY_KEY, params?.uid],
27
27
  {
28
28
  ...params
29
29
  }
@@ -26,7 +26,7 @@ export const useHasPlatformRelation = (
26
26
 
27
27
  return useQuery<boolean, Error>(
28
28
  [
29
- QUERY_KEY,
29
+ [QUERY_KEY, params?.uid],
30
30
  {
31
31
  ...params
32
32
  }
@@ -2,31 +2,29 @@ import { useQuery } from 'react-query';
2
2
 
3
3
  import { useFetchClient } from '@strapi/helper-plugin';
4
4
 
5
- import { PageType } from './page-type';
6
-
7
5
  const QUERY_KEY = 'pageTypesForPlatform';
8
6
 
7
+ export type PageType = {
8
+ id: number;
9
+ uid: string;
10
+ title?: string;
11
+ };
12
+
9
13
  const fetchPageTypesForPlatform = async ({ fetchClient, id }: Record<string, any>): Promise<PageType[]> => {
10
14
  if (!id) return [];
11
15
 
12
16
  const { get } = fetchClient;
13
- const pageTypesByPlatformResult = await get(
14
- `/content-manager/relations/api::platform.platform/${id}/pageTypes?page=1&pageSize=100`
15
- );
16
- const pageTypesResult = await get(`/content-manager/collection-types/api::page-type.page-type?page=1&pageSize=100`);
17
-
18
- return pageTypesByPlatformResult?.data?.results?.map((entity: Record<string, any>) => {
19
- const fullPageType = pageTypesResult?.data?.results?.find(
20
- (pageType: Record<string, any>) => pageType.id === entity.id
21
- );
22
-
23
- return {
24
- id: entity.id,
25
- uid: fullPageType.uid,
26
- title: fullPageType.title,
27
- templateId: fullPageType?.template?.id
28
- };
29
- });
17
+
18
+ const pageTypesResult = await get(`/content-manager/collection-types/api::page-type.page-type?page=1&pageSize=999`);
19
+
20
+ return pageTypesResult?.data?.results
21
+ ?.filter((x) => x?.platform?.id === id)
22
+ ?.map((pageType: Record<string, any>) => ({
23
+ id: pageType.id,
24
+ uid: pageType.uid,
25
+ title: pageType.title,
26
+ templateId: pageType?.template?.id
27
+ }));
30
28
  };
31
29
 
32
30
  export const useGetPageTypesForPlatform = (params: Record<string, any>) => {
@@ -2,7 +2,7 @@ import { useQuery } from 'react-query';
2
2
 
3
3
  import { useFetchClient } from '@strapi/helper-plugin';
4
4
 
5
- import { PageType } from './page-type';
5
+ import { PageType } from './platform-page-types';
6
6
 
7
7
  export type Platform = {
8
8
  id: number;
@@ -14,7 +14,7 @@ const QUERY_KEY = 'platforms';
14
14
 
15
15
  const fetchPlatforms = async ({ fetchClient }: Record<string, any>): Promise<Platform[]> => {
16
16
  const { get } = fetchClient;
17
- const result = await get('/content-manager/collection-types/api::platform.platform?page=1&pageSize=100');
17
+ const result = await get('/content-manager/collection-types/api::platform.platform?page=1&pageSize=999');
18
18
 
19
19
  return result?.data?.results.map((entity: Record<string, any>) => ({
20
20
  id: entity.id,
@@ -0,0 +1,111 @@
1
+ import { useQuery, UseQueryOptions } from 'react-query';
2
+ import orderBy from 'lodash/orderBy';
3
+
4
+ import { useFetchClient } from '@strapi/helper-plugin';
5
+
6
+ export type SearchFilteredEntitiesResult = {
7
+ pagination: {
8
+ page: number;
9
+ pageCount: number;
10
+ pageSize: number;
11
+ total: number;
12
+ };
13
+ results: {
14
+ id: number;
15
+ title: string;
16
+ href: string;
17
+ publicationState?: string;
18
+ publishedAt?: string;
19
+ }[];
20
+ };
21
+
22
+ type SearchFilteredEntitiesQueryParams = {
23
+ fetchClient?: any;
24
+ uid: string;
25
+ page: number;
26
+ locale: string;
27
+ searchQuery?: string;
28
+ platformTitle?: string;
29
+ notIds?: number[];
30
+ };
31
+
32
+ const QUERY_KEY = ['filteredEntities'];
33
+
34
+ export const getSearchFilteredEntities = async ({
35
+ fetchClient,
36
+ uid,
37
+ page,
38
+ locale,
39
+ searchQuery,
40
+ platformTitle,
41
+ notIds
42
+ }: SearchFilteredEntitiesQueryParams): Promise<SearchFilteredEntitiesResult> => {
43
+ try {
44
+ const { get } = fetchClient;
45
+ const searchParams = new URLSearchParams();
46
+ searchParams.append('page', String(page));
47
+ searchParams.append('pageSize', '20');
48
+ searchParams.append('locale', locale);
49
+
50
+ if (searchQuery) {
51
+ searchParams.delete('sort');
52
+ searchParams.append('sort', 'title:ASC');
53
+ searchParams.append('_q', searchQuery);
54
+ }
55
+
56
+ if (platformTitle) {
57
+ searchParams.append('filters[$and][0][platform][title][$contains]', String(platformTitle));
58
+ }
59
+
60
+ if (notIds && notIds.length > 0) {
61
+ for (let index = 0; index < notIds.length; index++) {
62
+ const id = notIds[index];
63
+ searchParams.append(`filters[$and][${index + 1}][id][$ne]`, String(id));
64
+ }
65
+ }
66
+
67
+ const { data } = await get(`/content-manager/collection-types/${uid}?${searchParams.toString()}`);
68
+
69
+ const mapResults = data.results.map(
70
+ (result: Record<string, any>): SearchFilteredEntitiesResult['results'][number] => ({
71
+ id: result.id,
72
+ title: result.title,
73
+ publicationState: result?.publishedAt ? 'published' : 'draft',
74
+ publishedAt: result?.publishedAt,
75
+ href: `/content-manager/collectionType/${uid}/${result.id}`
76
+ })
77
+ );
78
+
79
+ return {
80
+ pagination: data.pagination,
81
+ results: orderBy(mapResults, ['title'], ['asc'])
82
+ };
83
+ } catch (e) {
84
+ return {
85
+ pagination: { page: 1, pageCount: 0, pageSize: 0, total: 0 },
86
+ results: []
87
+ };
88
+ }
89
+ };
90
+
91
+ export const useSearchFilteredEntities = (
92
+ params: SearchFilteredEntitiesQueryParams,
93
+ options?: UseQueryOptions<SearchFilteredEntitiesResult, Error>
94
+ ) => {
95
+ const fetchClient = useFetchClient();
96
+
97
+ return useQuery<SearchFilteredEntitiesResult, Error>(
98
+ [
99
+ [QUERY_KEY, params.uid],
100
+ {
101
+ ...params
102
+ }
103
+ ],
104
+ () =>
105
+ getSearchFilteredEntities({
106
+ ...params,
107
+ fetchClient
108
+ }),
109
+ options
110
+ );
111
+ };
@@ -1,27 +1,30 @@
1
1
  import { useQuery } from 'react-query';
2
+
2
3
  import { useFetchClient } from '@strapi/helper-plugin';
3
- import getRequestUrl from '../utils/getRequestUrl';
4
4
 
5
5
  export type Template = {
6
6
  id: number;
7
7
  title: string;
8
- modules: any[];
8
+ modules: Record<string, any>[];
9
9
  };
10
10
 
11
11
  const QUERY_KEY = ['templates'];
12
12
 
13
- const fetchTemplates = async ({ fetchClient }: any): Promise<Template[]> => {
13
+ const fetchTemplates = async ({ fetchClient, id }: Record<string, any>): Promise<Template[]> => {
14
14
  const { get } = fetchClient;
15
- const result = await get(getRequestUrl('/template'));
15
+ const result = await get(`/content-manager/collection-types/api::template.template?page=1&pageSize=999`);
16
16
 
17
- return result?.data;
17
+ return result?.data?.results
18
+ ?.filter((x?: Record<string, any>) => x?.platform?.id === id)
19
+ ?.map((template: Record<string, any>) => ({ id: template.id, title: template.title, modules: template.modules }));
18
20
  };
19
21
 
20
- export const useGetTemplates = (params: any) => {
22
+ export const useGetTemplates = (params: Record<string, any>) => {
21
23
  const fetchClient = useFetchClient();
22
24
  params = {
23
25
  ...params,
24
26
  fetchClient
25
27
  };
26
- return useQuery<Template[], Error>(QUERY_KEY, () => fetchTemplates(params));
28
+
29
+ return useQuery<Template[], Error>([QUERY_KEY, params?.id], () => fetchTemplates(params));
27
30
  };
@@ -3,7 +3,7 @@ import { ClearIndicatorProps, DropdownIndicatorProps, GroupBase, components } fr
3
3
  import AsyncSelect, { AsyncProps } from 'react-select/async';
4
4
 
5
5
  import { CarretDown, Cross } from '@strapi/icons';
6
- import { Typography } from '@strapi/design-system';
6
+ import { FieldLabel } from '@strapi/design-system';
7
7
 
8
8
  import S from './styles';
9
9
  import { useReactSelectCustomStyles } from './react-select-custom-styles';
@@ -12,6 +12,8 @@ export interface IComboboxProps extends AsyncProps<IReactSelectValue, false, Gro
12
12
  customOption?: typeof components.Option<IReactSelectValue, false, GroupBase<IReactSelectValue>>;
13
13
  label?: string;
14
14
  id: string;
15
+ extraLabelElement?: React.ReactNode;
16
+ labelAction?: React.ReactNode;
15
17
  }
16
18
 
17
19
  export interface IReactSelectValue {
@@ -21,7 +23,7 @@ export interface IReactSelectValue {
21
23
  }
22
24
 
23
25
  const Combobox = (props: IComboboxProps) => {
24
- const { label, customOption, id, ...selectProps } = props;
26
+ const { label, customOption, extraLabelElement, labelAction, id, ...selectProps } = props;
25
27
  const styles = useReactSelectCustomStyles();
26
28
  const [inputValue, setInputValue] = useState<string | undefined>(props.inputValue);
27
29
 
@@ -32,9 +34,10 @@ const Combobox = (props: IComboboxProps) => {
32
34
  return (
33
35
  <S.Wrapper>
34
36
  {props.label && (
35
- <Typography as="label" htmlFor={id} variant="pi" fontWeight="bold" textColor="neutral800">
36
- {props.label}
37
- </Typography>
37
+ <S.LabelWrapper>
38
+ <FieldLabel action={labelAction}>{props.label}</FieldLabel>
39
+ {extraLabelElement}
40
+ </S.LabelWrapper>
38
41
  )}
39
42
  <AsyncSelect
40
43
  {...selectProps}
@@ -44,7 +47,6 @@ const Combobox = (props: IComboboxProps) => {
44
47
  props.onInputChange?.(value, actionMeta);
45
48
  setInputValue(value);
46
49
  }}
47
- // @ts-ignore
48
50
  styles={styles}
49
51
  inputValue={inputValue}
50
52
  components={{
@@ -14,9 +14,21 @@ const Option = styled.span`
14
14
  flex-direction: column;
15
15
  `;
16
16
 
17
+ const LabelWrapper = styled.div`
18
+ ${({ theme }) => css`
19
+ width: 100%;
20
+ display: flex;
21
+ gap: 4px;
22
+ justify-content: space-between;
23
+ color: ${theme.colors.neutral800};
24
+ font-size: ${theme.fontSizes[1]};
25
+ `}
26
+ `;
27
+
17
28
  const ComboboxStyles = {
18
29
  Wrapper,
19
- Option
30
+ Option,
31
+ LabelWrapper
20
32
  };
21
33
 
22
34
  export default ComboboxStyles;
@@ -24,7 +24,7 @@ export const CreatePageButton = () => {
24
24
  const handleCreatePage = async (e: React.MouseEvent<HTMLAnchorElement>) => {
25
25
  e.preventDefault();
26
26
  try {
27
- const pageTypeUrl = getRequestUrl(`/page-types/${layout.uid}`);
27
+ const pageTypeUrl = getRequestUrl(`/page-types/${layout.uid}/${initialData.platform[0]?.id}`);
28
28
  const { data: pageType } = await get(pageTypeUrl);
29
29
  const mappedLocalizations = (initialData?.localizations || []).map((x: any) => x?.id).join(',');
30
30
  const linkedPages: { data: IGetTranslationPageLinks[] } = await get(
@@ -50,6 +50,7 @@ export const CreatePageButton = () => {
50
50
  locale,
51
51
  pageTypeId: pageType.id,
52
52
  platformId: initialData.platform[0]?.id,
53
+ parentId: pageType?.defaultParent?.id,
53
54
  collectionTypeId: initialData.id,
54
55
  layoutUid: layout.uid,
55
56
  relatedEntityId: createLocalizedPage ? linkedPages.data?.[0]?.id : undefined
@@ -82,6 +83,7 @@ interface ICreateNewPageProps {
82
83
  pageTypeId: number;
83
84
  platformId: number;
84
85
  relatedEntityId?: number;
86
+ parentId?: number;
85
87
  }
86
88
 
87
89
  const createNewPage = async ({
@@ -93,7 +95,8 @@ const createNewPage = async ({
93
95
  modules,
94
96
  pageTypeId,
95
97
  platformId,
96
- relatedEntityId
98
+ relatedEntityId,
99
+ parentId
97
100
  }: ICreateNewPageProps) => {
98
101
  // Including locale in url is neccesary.
99
102
  const relatedEntityIdQuery = relatedEntityId ? `&plugins[i18n][relatedEntityId]=${relatedEntityId}` : '';
@@ -113,6 +116,7 @@ const createNewPage = async ({
113
116
  locale,
114
117
  pageType: { connect: [{ id: pageTypeId }] },
115
118
  platform: { connect: [{ id: platformId }] },
119
+ ...(parentId && { parent: { connect: [{ id: parentId }] } }),
116
120
  collectionTypeData: {
117
121
  id: collectionTypeId,
118
122
  __type: layoutUid,
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import { Flex } from '@strapi/design-system';
4
4
  import { Link } from '@strapi/icons';
5
5
 
6
- import { PageType } from '../../../api/page-type';
6
+ import { PageType } from '../../../api/platform-page-types';
7
7
  import { PAGE_TYPE_PAGE } from '../../../../../shared/utils/constants';
8
8
  import S from './styles';
9
9
 
@@ -7,7 +7,7 @@ import { TemplateSelect } from '../Template/TemplateSelect';
7
7
  import { PageTypeSelect } from '../page-type-select';
8
8
  import { CollectionTypeSearch } from '../CollectionTypeSearch';
9
9
  import { Wrapper } from '../wrapper';
10
- import { PageType } from '../../../api/page-type';
10
+ import { PageType } from '../../../api/platform-page-types';
11
11
  import { Details } from '../Details';
12
12
  import { Platform } from '../../../api/platform';
13
13
  import { usePlatformFormData } from '../../../utils/hooks/usePlatformFormData';
@@ -21,7 +21,8 @@ export const TemplateSelect = ({ disabled }: Props) => {
21
21
 
22
22
  const handleSelectTemplate = (templateId?: string) => {
23
23
  const template = templates?.find((template) => template.id === Number(templateId));
24
- template == null ? setSelectedTemplate(null) : setSelectedTemplate(template);
24
+
25
+ setSelectedTemplate(template || null);
25
26
 
26
27
  setTemplateIdToSelect(undefined);
27
28
  };
@@ -50,7 +51,7 @@ export const TemplateSelect = ({ disabled }: Props) => {
50
51
  onChange={handleSelectChange}
51
52
  disabled={Boolean(disabled)}
52
53
  >
53
- <SingleSelectOption value={0}>None</SingleSelectOption>
54
+ <SingleSelectOption value={0}>Kies een template om in te laden</SingleSelectOption>
54
55
  {templates?.map((template) => (
55
56
  <SingleSelectOption key={template.id} value={template.id}>
56
57
  {template.title}
@@ -1,12 +1,15 @@
1
+ import { useFetchClient } from '@strapi/helper-plugin';
2
+
1
3
  import { Template, useGetTemplates } from '../../../../api/template';
2
4
  import { sanitizeModules } from '../../../../utils/sanitizeModules';
3
- import { useFetchClient } from '@strapi/helper-plugin';
4
5
  import getRequestUrl from '../../../../utils/getRequestUrl';
6
+ import { useDefaultPlatformFromLocalStorage } from '../../../../utils/hooks/useDefaultPlatformFromLocalStorage';
5
7
 
6
8
  type OnChangeFormType = (props: { target: Record<string, any>; shouldSetInitialValue: boolean }) => void;
7
9
 
8
10
  export const useTemplateModules = (onChange: OnChangeFormType) => {
9
- const { data: templates } = useGetTemplates({});
11
+ const { selectedPlatform } = useDefaultPlatformFromLocalStorage();
12
+ const { data: templates } = useGetTemplates({ id: selectedPlatform?.id });
10
13
  const fetchClient = useFetchClient();
11
14
 
12
15
  return {
@@ -2,7 +2,7 @@ import React from 'react';
2
2
 
3
3
  import { SingleSelect, SingleSelectOption } from '@strapi/design-system';
4
4
 
5
- import { PageType } from '../../api/page-type';
5
+ import { PageType } from '../../api/platform-page-types';
6
6
  import { PAGE_TYPE_PAGE } from '../../../../shared/utils/constants';
7
7
 
8
8
  interface Props {
@@ -2,8 +2,9 @@ import React from 'react';
2
2
  import { Flex, Box, Divider, Typography } from '@strapi/design-system';
3
3
 
4
4
  interface Props {
5
- title: string;
5
+ title?: string;
6
6
  children: React.ReactNode;
7
+ flexProps?: Record<string, any>;
7
8
  }
8
9
 
9
10
  export const Wrapper = (props: Props) => {
@@ -20,14 +21,19 @@ export const Wrapper = (props: Props) => {
20
21
  paddingLeft={4}
21
22
  shadow="tableShadow"
22
23
  alignItems="left"
24
+ {...props.flexProps}
23
25
  >
24
- <Typography variant="sigma" textColor="neutral600" id="additional-information">
25
- {props.title}
26
- </Typography>
26
+ {props.title && (
27
+ <>
28
+ <Typography variant="sigma" textColor="neutral600" id="additional-information">
29
+ {props.title}
30
+ </Typography>
27
31
 
28
- <Box paddingTop={2} paddingBottom={4}>
29
- <Divider />
30
- </Box>
32
+ <Box paddingTop={2} paddingBottom={4}>
33
+ <Divider />
34
+ </Box>
35
+ </>
36
+ )}
31
37
 
32
38
  {props.children}
33
39
  </Flex>
@@ -19,7 +19,6 @@ const GlobalPlatformSelect = ({ small }: IGlobalPlatformSelectProps) => {
19
19
  const { selectedPlatform, setSelectedPlatform } = useDefaultPlatformFromLocalStorage();
20
20
 
21
21
  const handlePlatformChange = (platform: Platform) => {
22
- console.log('handlePlatformChange', platform);
23
22
  setSelectedPlatform(platform);
24
23
 
25
24
  if (typeof window !== 'undefined' && pathname.split('/').filter(Boolean).length > 3) {
@@ -2,7 +2,7 @@ import React from 'react';
2
2
 
3
3
  import { SingleSelectOption, SingleSelect } from '@strapi/design-system';
4
4
 
5
- import { PageType } from '../../../api/page-type';
5
+ import { PageType } from '../../../api/platform-page-types';
6
6
  import { PAGE_TYPE_NO_FILTER } from '../../../constants';
7
7
  import { PAGE_TYPE_PAGE } from '../../../../../shared/utils/constants';
8
8
 
@@ -8,7 +8,7 @@ import PageTypeFilter from './PageTypeFilter';
8
8
  import { PAGE_TYPE_PAGE, PLATFORM } from '../../../../shared/utils/constants';
9
9
  import { Platform, useGetPlatforms } from '../../api/platform';
10
10
  import { PAGE_TYPE, PAGE_TYPE_NO_FILTER, PLATFORM_NO_FILTER } from '../../constants';
11
- import { PageType } from '../../api/page-type';
11
+ import { PageType } from '../../api/platform-page-types';
12
12
  import { useGetPageTypesForPlatform } from '../../api/platform-page-types';
13
13
  import { useDefaultPlatformFromLocalStorage } from '../../utils/hooks/useDefaultPlatformFromLocalStorage';
14
14
  import { useHideOverviewFilterTags } from '../../utils/hooks/useHideOverviewFilterTags';
@@ -6,6 +6,7 @@ import { PAGE_UID } from '../../../../shared/utils/constants';
6
6
 
7
7
  import PageFilters from './filters';
8
8
  import { useHasPageRelation } from '../../api/has-page-relation';
9
+ import { useHasPlatformRelation } from '../../api/has-platform-relation';
9
10
 
10
11
  const PageFiltersContainer = () => {
11
12
  const { pathname } = useLocation();
@@ -16,11 +17,15 @@ const PageFiltersContainer = () => {
16
17
  uid
17
18
  });
18
19
 
20
+ const { data: hasPlatformRelation, isLoading: isLoadingPlatformRelation } = useHasPlatformRelation({
21
+ uid
22
+ });
23
+
19
24
  if (isPageCollectionType) {
20
25
  return <PageFilters />;
21
26
  }
22
27
 
23
- if (!isPageCollectionType && hasPageRelation && !isLoading) {
28
+ if (!isPageCollectionType && !isLoading && !isLoadingPlatformRelation && (hasPageRelation || hasPlatformRelation)) {
24
29
  return <PageFilters hidePageType />;
25
30
  }
26
31
 
@@ -0,0 +1,112 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { useSelector } from 'react-redux';
3
+ import debounce from 'lodash/debounce';
4
+ import { SingleValue } from 'react-select';
5
+ import { useCMEditViewDataManager, useFetchClient } from '@strapi/helper-plugin';
6
+ import { useGetLocaleFromUrl } from '../../../utils/hooks/useGetLocaleFromUrl';
7
+ import { IReactSelectValue, Combobox } from '../../Combobox';
8
+ import { getSearchFilteredEntities } from '../../../api/search-filtered-entity';
9
+ import { PAGE_UID } from '../../../../../shared/utils/constants';
10
+
11
+ const SEARCH_DEBOUNCE_MS = 150;
12
+ const PAGE = 1;
13
+
14
+ export const PageByPlatformSearch = () => {
15
+ const fetchClient = useFetchClient();
16
+ const { onChange, initialData, modifiedData, isCreatingEntry } = useCMEditViewDataManager() as any;
17
+ const { locales } = useSelector((state: any) => state.i18n_locales);
18
+ const urlLocale = useGetLocaleFromUrl();
19
+ const defaultLocale = locales.find((locale: any) => locale.isDefault);
20
+ const selectedLocale = initialData?.locale ?? urlLocale ?? defaultLocale.code;
21
+
22
+ const [selected, setSelected] = useState<SingleValue<IReactSelectValue | null>>();
23
+
24
+ useEffect(() => {
25
+ const initialSelect = getInitialSelectItem(
26
+ modifiedData?.defaultParent?.[0]?.id,
27
+ modifiedData?.defaultParent?.[0]?.title
28
+ );
29
+
30
+ setSelected(initialSelect);
31
+ }, [modifiedData?.defaultParent]);
32
+
33
+ useEffect(() => {
34
+ if (isCreatingEntry) {
35
+ setSelected(null);
36
+ }
37
+ }, []);
38
+
39
+ const setFormValue = (name: string, value?: string | Record<string, any>[]) => {
40
+ onChange({
41
+ target: {
42
+ name,
43
+ value
44
+ },
45
+ shouldSetInitialValue: true
46
+ });
47
+ };
48
+
49
+ const handleSelectDefaultParent = (value?: SingleValue<IReactSelectValue>) => {
50
+ if (value) {
51
+ const defaultParent = {
52
+ id: value.value,
53
+ title: value.label,
54
+ mainField: value.label,
55
+ label: value.label,
56
+ value: value.value
57
+ };
58
+ setFormValue('defaultParent', [defaultParent]);
59
+ } else {
60
+ setFormValue('defaultParent', []);
61
+ }
62
+ };
63
+
64
+ const getItems = async (inputValue?: string, platformTitle?: string): Promise<IReactSelectValue[]> => {
65
+ const pages = await getSearchFilteredEntities({
66
+ fetchClient,
67
+ page: PAGE,
68
+ uid: PAGE_UID,
69
+ locale: selectedLocale,
70
+ searchQuery: inputValue,
71
+ platformTitle
72
+ });
73
+
74
+ return pages?.results.map((x) => ({
75
+ value: String(x.id),
76
+ label: x.title
77
+ }));
78
+ };
79
+
80
+ const debouncedFetch = debounce((searchTerm, callback, selectedPlatformTitle?: string) => {
81
+ promiseOptions(searchTerm, selectedPlatformTitle).then((result) => {
82
+ return callback(result || []);
83
+ });
84
+ }, SEARCH_DEBOUNCE_MS);
85
+
86
+ const promiseOptions = (inputValue: string, selectedPlatformTitle?: string): Promise<IReactSelectValue[]> =>
87
+ new Promise<IReactSelectValue[]>((resolve) => {
88
+ resolve(getItems(inputValue, selectedPlatformTitle));
89
+ });
90
+
91
+ return (
92
+ <Combobox
93
+ key={`rerenderOnPlatformChange-${initialData?.platform?.[0]?.id}`}
94
+ id="pagesSearch"
95
+ label="Standaard overzichtspagina"
96
+ loadOptions={(i, c) => debouncedFetch(i, c, initialData?.platform?.[0]?.title)}
97
+ cacheOptions
98
+ onChange={handleSelectDefaultParent}
99
+ value={selected}
100
+ defaultOptions
101
+ />
102
+ );
103
+ };
104
+
105
+ const getInitialSelectItem = (id?: string, title?: string): SingleValue<IReactSelectValue | null> =>
106
+ id
107
+ ? {
108
+ value: String(id),
109
+ label: title ?? '',
110
+ initialSelected: true
111
+ }
112
+ : null;