@webbio/strapi-plugin-page-builder 0.0.12 → 0.0.14
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/.prettierignore +17 -0
- package/admin/src/api/collection-type.ts +110 -0
- package/admin/src/api/has-page-relation.ts +34 -0
- package/admin/src/api/page-type.ts +31 -0
- package/admin/src/api/template.ts +25 -0
- package/admin/src/components/Combobox/index.tsx +77 -0
- package/admin/src/components/Combobox/react-select-custom-styles.tsx +111 -0
- package/admin/src/components/Combobox/styles.ts +22 -0
- package/admin/src/components/ConfirmModal/index.tsx +90 -0
- package/admin/src/components/EditView/CollectionTypeSearch/index.tsx +118 -0
- package/admin/src/components/EditView/CollectionTypeSettings/CreatePageButton/index.tsx +95 -0
- package/admin/src/components/EditView/CollectionTypeSettings/CreatePageButton/styles.ts +26 -0
- package/admin/src/components/EditView/CollectionTypeSettings/index.tsx +53 -0
- package/admin/src/components/EditView/Details/index.tsx +47 -0
- package/admin/src/components/EditView/Details/styles.ts +51 -0
- package/admin/src/components/EditView/PageSettings/index.tsx +104 -0
- package/admin/src/components/EditView/Template/TemplateConfirmModal/index.tsx +36 -0
- package/admin/src/components/EditView/Template/TemplateSelect/index.tsx +64 -0
- package/admin/src/components/EditView/Template/TemplateSelect/use-template-modules.ts +30 -0
- package/admin/src/components/EditView/index.tsx +27 -0
- package/admin/src/components/EditView/page-type-select.tsx +30 -0
- package/admin/src/components/EditView/wrapper.tsx +35 -0
- package/admin/src/components/Initializer/index.tsx +24 -0
- package/admin/src/components/PageTypeFilter/index.tsx +17 -0
- package/admin/src/components/PageTypeFilter/page-type-filter.tsx +130 -0
- package/admin/src/components/PluginIcon/index.tsx +12 -0
- package/admin/src/constants.ts +1 -0
- package/admin/src/index.tsx +59 -0
- package/admin/src/middlewares/index.tsx +37 -0
- package/admin/src/pluginId.ts +5 -0
- package/admin/src/translations/en.json +6 -0
- package/admin/src/translations/nl.json +6 -0
- package/admin/src/utils/getRequestUrl.ts +11 -0
- package/admin/src/utils/getTrad.ts +5 -0
- package/admin/src/utils/hooks/useDebounce.ts +17 -0
- package/admin/src/utils/hooks/useGetLocaleFromUrl.ts +9 -0
- package/admin/src/utils/hooks/usePrevious.ts +12 -0
- package/admin/src/utils/sanitizeModules.ts +10 -0
- package/custom.d.ts +5 -0
- package/dist/package.json +1 -1
- package/dist/server/services/builder.js +14 -5
- package/dist/tsconfig.server.tsbuildinfo +1 -1
- package/package.json +1 -5
- package/server/bootstrap.ts +106 -0
- package/server/config/index.ts +4 -0
- package/server/content-types/index.ts +1 -0
- package/server/controllers/collection-types.ts +27 -0
- package/server/controllers/index.ts +9 -0
- package/server/controllers/page-type.ts +12 -0
- package/server/controllers/page.ts +20 -0
- package/server/destroy.ts +5 -0
- package/server/index.ts +23 -0
- package/server/middlewares/index.ts +1 -0
- package/server/policies/index.ts +1 -0
- package/server/register.ts +5 -0
- package/server/routes/index.ts +42 -0
- package/server/schema/page-end.json +97 -0
- package/server/schema/page-start.json +87 -0
- package/server/schema/page-type-end.json +49 -0
- package/server/schema/page-type-start.json +44 -0
- package/server/schema/template.json +35 -0
- package/server/services/builder.ts +134 -0
- package/server/services/collection-types.ts +49 -0
- package/server/services/index.ts +11 -0
- package/server/services/page-type.ts +22 -0
- package/server/services/page.ts +24 -0
- package/server/utils/graphql.ts +110 -0
- package/server/utils/reload-strapi-on-load.ts +13 -0
- package/shared/utils/constants.ts +4 -0
- package/shared/utils/sleep.ts +1 -0
- package/strapi-admin.js +3 -0
- package/strapi-server.js +3 -0
- package/tsconfig.json +20 -0
- package/tsconfig.server.json +25 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import set from 'lodash/set';
|
|
3
|
+
|
|
4
|
+
import { SingleSelectOption, SingleSelect } from '@strapi/design-system';
|
|
5
|
+
import { useQueryParams } from '@strapi/helper-plugin';
|
|
6
|
+
|
|
7
|
+
import { useGetPageTypes } from '../../api/page-type';
|
|
8
|
+
import { PAGE_TYPE_NO_FILTER } from '../../constants';
|
|
9
|
+
import { PAGE_TYPE_PAGE } from '../../../../shared/utils/constants';
|
|
10
|
+
|
|
11
|
+
const PageTypeFilter = () => {
|
|
12
|
+
const [{ query }, setQuery] = useQueryParams();
|
|
13
|
+
const { data: pageTypes } = useGetPageTypes({});
|
|
14
|
+
const initialPageTypeUid = getInitialPageType(query, pageTypes);
|
|
15
|
+
const [selectedPageTypeUid, setSelectedPageTypeUid] = useState(initialPageTypeUid);
|
|
16
|
+
|
|
17
|
+
const removeFilters = () => {
|
|
18
|
+
const newAndFilters = query.filters?.$and?.filter(
|
|
19
|
+
(x?: Record<string, any>) => Object.keys(x || {})?.[0] !== 'pageType'
|
|
20
|
+
);
|
|
21
|
+
const filters = { ...query.filters, $and: newAndFilters };
|
|
22
|
+
|
|
23
|
+
if (newAndFilters && newAndFilters.length === 0) {
|
|
24
|
+
delete filters.$and;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setQuery({
|
|
28
|
+
page: 1,
|
|
29
|
+
filters
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handleFilterChange = (filters: Record<string, any>) => {
|
|
34
|
+
const currentFilters = query.filters?.$and ? query.filters : { ...query.filters, $and: [] }; // Make sure $and exists.
|
|
35
|
+
const pageTypeFilterIndex = currentFilters.$and.findIndex(
|
|
36
|
+
(x?: Record<string, any>) => Object.keys(x || {})?.[0] === 'pageType'
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (pageTypeFilterIndex > -1) {
|
|
40
|
+
set(currentFilters, `$and[${pageTypeFilterIndex}]`, filters); // If the pageType filter already exists, replace it
|
|
41
|
+
} else {
|
|
42
|
+
currentFilters.$and.push(filters);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setQuery({
|
|
46
|
+
page: 1,
|
|
47
|
+
filters: currentFilters
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const handleSelect = (value: string) => {
|
|
52
|
+
setSelectedPageTypeUid(value);
|
|
53
|
+
|
|
54
|
+
if (value === 'all') {
|
|
55
|
+
removeFilters();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (value === PAGE_TYPE_PAGE) {
|
|
60
|
+
handleFilterChange(nullPageTypeQueryFilter);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
handleFilterChange(getPageTypeQueryFilter(value));
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
setSelectedPageTypeUid(getInitialPageType(query, pageTypes));
|
|
69
|
+
}, [pageTypes]);
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (!query?.filters) {
|
|
73
|
+
setSelectedPageTypeUid(null);
|
|
74
|
+
}
|
|
75
|
+
}, [query]);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<SingleSelect placeholder="Select page type" onChange={handleSelect} size="S" value={selectedPageTypeUid}>
|
|
79
|
+
<SingleSelectOption key={PAGE_TYPE_NO_FILTER} value={PAGE_TYPE_NO_FILTER}>
|
|
80
|
+
All Pagetypes
|
|
81
|
+
</SingleSelectOption>
|
|
82
|
+
<SingleSelectOption key={PAGE_TYPE_PAGE} value={PAGE_TYPE_PAGE}>
|
|
83
|
+
Page
|
|
84
|
+
</SingleSelectOption>
|
|
85
|
+
{pageTypes?.map((pageType) => (
|
|
86
|
+
<SingleSelectOption key={pageType.uid} value={pageType.uid}>
|
|
87
|
+
{pageType.title || pageType.uid}
|
|
88
|
+
</SingleSelectOption>
|
|
89
|
+
))}
|
|
90
|
+
</SingleSelect>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export { PageTypeFilter };
|
|
95
|
+
|
|
96
|
+
const getPageTypeQueryFilter = (pageType: string) => ({
|
|
97
|
+
pageType: {
|
|
98
|
+
uid: {
|
|
99
|
+
$eq: pageType
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const nullPageTypeQueryFilter = {
|
|
105
|
+
pageType: {
|
|
106
|
+
uid: {
|
|
107
|
+
$null: true
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const getInitialPageType = (query: any, pageTypes: any) => {
|
|
113
|
+
const pageTypeFromQuery = query?.filters?.$and?.find(
|
|
114
|
+
(x?: Record<string, any>) => Object.keys(x || {})?.[0] === 'pageType'
|
|
115
|
+
)?.pageType;
|
|
116
|
+
|
|
117
|
+
if (pageTypeFromQuery?.uid?.$null === 'true') {
|
|
118
|
+
return PAGE_TYPE_PAGE;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (pageTypeFromQuery?.uid?.$eq) {
|
|
122
|
+
const matchingPageType = pageTypes?.find((pageType: any) => pageType?.uid === pageTypeFromQuery.uid.$eq);
|
|
123
|
+
|
|
124
|
+
if (matchingPageType) {
|
|
125
|
+
return matchingPageType.uid;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return PAGE_TYPE_NO_FILTER;
|
|
130
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const PAGE_TYPE_NO_FILTER = 'all';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { prefixPluginTranslations } from '@strapi/helper-plugin';
|
|
2
|
+
|
|
3
|
+
import pluginPkg from '../../package.json';
|
|
4
|
+
import pluginId from './pluginId';
|
|
5
|
+
import Initializer from './components/Initializer';
|
|
6
|
+
import PageTypeFilter from './components/PageTypeFilter';
|
|
7
|
+
import { EditView } from './components/EditView';
|
|
8
|
+
import middlewares from './middlewares';
|
|
9
|
+
|
|
10
|
+
const name = pluginPkg.strapi.name;
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
register(app: any) {
|
|
14
|
+
app.addMiddlewares(middlewares);
|
|
15
|
+
const plugin = {
|
|
16
|
+
id: pluginId,
|
|
17
|
+
initializer: Initializer,
|
|
18
|
+
isReady: false,
|
|
19
|
+
name
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
app.registerPlugin(plugin);
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
bootstrap(app: any) {
|
|
26
|
+
app.injectContentManagerComponent('editView', 'right-links', {
|
|
27
|
+
name: 'collection-type-picker',
|
|
28
|
+
Component: EditView
|
|
29
|
+
});
|
|
30
|
+
app.injectContentManagerComponent('listView', 'actions', {
|
|
31
|
+
name: 'page-type-filter',
|
|
32
|
+
Component: PageTypeFilter
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
async registerTrads(app: any) {
|
|
37
|
+
const { locales } = app;
|
|
38
|
+
|
|
39
|
+
const importedTrads = await Promise.all(
|
|
40
|
+
(locales as string[]).map((locale) => {
|
|
41
|
+
return import(`./translations/${locale}.json`)
|
|
42
|
+
.then(({ default: data }) => {
|
|
43
|
+
return {
|
|
44
|
+
data: prefixPluginTranslations(data, pluginId),
|
|
45
|
+
locale
|
|
46
|
+
};
|
|
47
|
+
})
|
|
48
|
+
.catch(() => {
|
|
49
|
+
return {
|
|
50
|
+
data: {},
|
|
51
|
+
locale
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
})
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return Promise.resolve(importedTrads);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getFetchClient } from '@strapi/helper-plugin';
|
|
2
|
+
|
|
3
|
+
import { PAGE_UID } from '../../../shared/utils/constants';
|
|
4
|
+
import getRequestUrl from '../utils/getRequestUrl';
|
|
5
|
+
|
|
6
|
+
const middleware =
|
|
7
|
+
() =>
|
|
8
|
+
({ getState }: any) =>
|
|
9
|
+
(next: any) =>
|
|
10
|
+
async (action: any) => {
|
|
11
|
+
// If data is being fetched or after a save
|
|
12
|
+
if (
|
|
13
|
+
action.type === 'ContentManager/CrudReducer/GET_DATA_SUCCEEDED' ||
|
|
14
|
+
action.type === 'ContentManager/CrudReducer/SUBMIT_SUCCEEDED'
|
|
15
|
+
) {
|
|
16
|
+
const store = getState();
|
|
17
|
+
const layoutSlice = store['content-manager_editViewLayoutManager'];
|
|
18
|
+
const uid = layoutSlice.currentLayout.contentType.uid;
|
|
19
|
+
|
|
20
|
+
if (uid !== PAGE_UID) {
|
|
21
|
+
return next(action);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { get } = await getFetchClient();
|
|
25
|
+
const { data: pageData } = await get(`${getRequestUrl('page')}/${action.data.id}`);
|
|
26
|
+
|
|
27
|
+
action.data.collectionTypeTitle = pageData?.collectionTypeData?.title;
|
|
28
|
+
action.data.collectionTypeId = pageData?.collectionTypeData?.id;
|
|
29
|
+
action.data.initialPageType = pageData?.pageType ? pageData.pageType : undefined;
|
|
30
|
+
|
|
31
|
+
return next(action);
|
|
32
|
+
}
|
|
33
|
+
return next(action);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const middlewares = [middleware];
|
|
37
|
+
export default middlewares;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"template.confirmModal.title": "Replace all page modules",
|
|
3
|
+
"template.confirmModal.body": "You are about to replace all modules on this page. Are you sure you want to continue?",
|
|
4
|
+
"template.confirmModal.buttons.cancel": "No, cancel",
|
|
5
|
+
"template.confirmModal.buttons.submit": "Yes, replace all"
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"template.confirmModal.title": "Pagina modules vervangen",
|
|
3
|
+
"template.confirmModal.body": "Weet je zeker dat je alle modules op deze pagina wilt vervangen?",
|
|
4
|
+
"template.confirmModal.buttons.cancel": "Nee, annuleer",
|
|
5
|
+
"template.confirmModal.buttons.submit": "Ja, vervang modules"
|
|
6
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export function useDebounce<T>(value: T, delay: number): T {
|
|
4
|
+
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
5
|
+
|
|
6
|
+
React.useEffect(() => {
|
|
7
|
+
const handler = setTimeout(() => {
|
|
8
|
+
setDebouncedValue(value);
|
|
9
|
+
}, delay);
|
|
10
|
+
|
|
11
|
+
return () => {
|
|
12
|
+
clearTimeout(handler);
|
|
13
|
+
};
|
|
14
|
+
}, [value, delay]);
|
|
15
|
+
|
|
16
|
+
return debouncedValue;
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useRef, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
// Hook
|
|
4
|
+
export const usePrevious = <T>(value: T): T | null => {
|
|
5
|
+
const ref: React.MutableRefObject<T | null> = useRef(null);
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
ref.current = value;
|
|
9
|
+
}, [value]);
|
|
10
|
+
|
|
11
|
+
return ref.current;
|
|
12
|
+
};
|
package/custom.d.ts
ADDED
package/dist/package.json
CHANGED
|
@@ -71,23 +71,32 @@ exports.default = {
|
|
|
71
71
|
},
|
|
72
72
|
getPageContentType(create) {
|
|
73
73
|
const page = create ? page_start_json_1.default : page_end_json_1.default;
|
|
74
|
-
const contentType = this.
|
|
74
|
+
const contentType = this.mergeCollectionTypeWithModules(page, constants_1.PAGE_UID);
|
|
75
75
|
return { uid: constants_1.PAGE_UID, contentType };
|
|
76
76
|
},
|
|
77
77
|
getPageTypeContentType(create) {
|
|
78
78
|
const pageType = create ? page_type_start_json_1.default : page_type_end_json_1.default;
|
|
79
|
-
const contentType = this.
|
|
79
|
+
const contentType = this.mergeCollectionTypeWithModules(pageType, constants_1.PAGE_TYPE_UID);
|
|
80
80
|
return { uid: constants_1.PAGE_TYPE_UID, contentType };
|
|
81
81
|
},
|
|
82
82
|
getTemplateContentType() {
|
|
83
|
-
const contentType = this.
|
|
83
|
+
const contentType = this.mergeCollectionTypeWithModules(template_json_1.default, constants_1.TEMPLATE_UID);
|
|
84
84
|
return { uid: constants_1.TEMPLATE_UID, contentType };
|
|
85
85
|
},
|
|
86
|
-
|
|
86
|
+
mergeCollectionTypeWithModules(collectionType, uid) {
|
|
87
|
+
const { pluginOptions: oldPluginOptions, __schema__: { attributes: oldAttributes } } = strapi.contentType(constants_1.PAGE_UID) || {};
|
|
87
88
|
const components = this.getConfigModuleComponents();
|
|
88
89
|
return {
|
|
89
90
|
...collectionType,
|
|
90
|
-
|
|
91
|
+
pluginOptions: {
|
|
92
|
+
...oldPluginOptions,
|
|
93
|
+
...collectionType === null || collectionType === void 0 ? void 0 : collectionType.pluginOptions
|
|
94
|
+
},
|
|
95
|
+
attributes: {
|
|
96
|
+
...oldAttributes,
|
|
97
|
+
...collectionType.attributes,
|
|
98
|
+
modules: { ...collectionType.attributes.modules, components }
|
|
99
|
+
}
|
|
91
100
|
};
|
|
92
101
|
},
|
|
93
102
|
getConfigModuleComponents() {
|