@strapi/admin 4.12.6 → 4.13.0-alpha.0
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/admin/src/StrapiApp.js +1 -1
- package/admin/src/components/AuthenticatedApp/index.js +118 -0
- package/admin/src/components/AuthenticatedApp/utils/api.js +85 -0
- package/admin/src/components/AuthenticatedApp/utils/checkLatestStrapiVersion.js +11 -0
- package/admin/src/components/GuidedTour/Modal/index.js +3 -1
- package/admin/src/components/NpsSurvey/hooks/useNpsSurveySettings.js +17 -0
- package/admin/src/components/NpsSurvey/index.js +365 -0
- package/admin/src/components/PluginsInitializer/index.js +68 -0
- package/admin/src/components/PluginsInitializer/init.js +11 -0
- package/admin/src/components/PluginsInitializer/reducer.js +22 -0
- package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumns.js +2 -0
- package/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js +1 -1
- package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +8 -1
- package/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.js +42 -0
- package/admin/src/content-manager/components/Filter/Filter.js +54 -0
- package/admin/src/content-manager/components/Filter/index.js +1 -0
- package/admin/src/content-manager/components/InputUID/index.js +222 -216
- package/admin/src/content-manager/components/RelationInput/RelationInput.js +4 -0
- package/admin/src/content-manager/components/RepeatableComponent/index.js +32 -2
- package/admin/src/content-manager/components/Wysiwyg/Editor.js +432 -68
- package/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.js +0 -7
- package/admin/src/content-manager/components/Wysiwyg/index.js +147 -152
- package/admin/src/content-manager/hooks/useAllowedAttributes.js +47 -0
- package/admin/src/content-manager/pages/App/index.js +16 -5
- package/admin/src/content-manager/pages/EditView/Information/index.js +9 -8
- package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +40 -7
- package/admin/src/content-manager/pages/ListSettingsView/index.js +6 -2
- package/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.js +2 -2
- package/admin/src/content-manager/pages/ListView/components/FieldPicker/index.js +67 -69
- package/admin/src/content-manager/pages/ListView/components/TableRows/index.js +1 -1
- package/admin/src/content-manager/pages/ListView/components/ViewSettingsMenu/index.js +80 -0
- package/admin/src/content-manager/pages/ListView/index.js +236 -67
- package/admin/src/content-manager/utils/getDisplayName.js +33 -0
- package/admin/src/content-manager/utils/index.js +1 -0
- package/admin/src/hooks/useSettingsForm/index.js +3 -14
- package/admin/src/hooks/useSettingsMenu/index.js +2 -2
- package/admin/src/hooks/useSettingsMenu/utils/formatLinks.js +3 -1
- package/admin/src/hooks/useSettingsMenu/utils/sortLinks.js +3 -1
- package/admin/src/index.js +1 -1
- package/admin/src/layouts/AppLayout/index.js +33 -0
- package/admin/src/pages/Admin/Onboarding/index.js +3 -1
- package/admin/src/pages/Admin/index.js +73 -77
- package/admin/src/pages/App/constants.js +1 -1
- package/admin/src/pages/App/index.js +122 -160
- package/admin/src/pages/AuthPage/components/Register/index.js +5 -0
- package/admin/src/pages/AuthPage/index.js +4 -2
- package/admin/src/pages/HomePage/index.js +3 -1
- package/admin/src/pages/InstalledPluginsPage/index.js +3 -1
- package/admin/src/pages/{InternalErrorPage.js → InternalErrorPage/index.js} +4 -3
- package/admin/src/pages/{NotFoundPage.js → NotFoundPage/index.js} +3 -1
- package/admin/src/pages/ProfilePage/index.js +4 -2
- package/admin/src/pages/SettingsPage/constants.js +132 -67
- package/admin/src/pages/SettingsPage/index.js +18 -23
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +1 -2
- package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
- package/admin/src/pages/UseCasePage/index.js +175 -0
- package/admin/src/plugins.js +7 -8
- package/admin/src/translations/en.json +10 -1
- package/admin/src/utils/checkFormValidity.js +15 -0
- package/admin/src/utils/createRoute.js +7 -5
- package/admin/src/utils/formatAPIErrors.js +3 -1
- package/admin/src/utils/getAttributesToDisplay.js +19 -0
- package/admin/src/utils/getExistingActions.js +32 -0
- package/admin/src/utils/getFullName.js +1 -1
- package/admin/src/utils/index.js +9 -0
- package/admin/src/utils/makeUniqueRoutes.js +6 -0
- package/admin/src/utils/sortLinks.js +3 -1
- package/admin/src/utils/uniqueAdminHash.js +9 -2
- package/build/{1049.9d69d231.chunk.js → 1049.ec69f5e0.chunk.js} +1 -1
- package/build/1227.9f37e1dc.chunk.js +1 -0
- package/build/1386.ea73b677.chunk.js +7 -0
- package/build/{2225.33287e1b.chunk.js → 2225.649fb7bc.chunk.js} +2 -2
- package/build/{2237.03792b63.chunk.js → 2237.b832ae6e.chunk.js} +4 -4
- package/build/{2379.401f56f3.chunk.js → 2379.1f98a31a.chunk.js} +1 -1
- package/build/{2395.e6a79fbb.chunk.js → 2395.0e5e8ded.chunk.js} +1 -1
- package/build/{2801.31393ffe.chunk.js → 2801.8e1aa82a.chunk.js} +1 -1
- package/build/3483.19381b40.chunk.js +1 -0
- package/build/3739.63e352f1.chunk.js +103 -0
- package/build/4174.f1f39e40.chunk.js +1 -0
- package/build/448.829e1344.chunk.js +1 -0
- package/build/4546.a5946d22.chunk.js +1 -0
- package/build/4724.aea5c8c1.chunk.js +6 -0
- package/build/{502.8dd074ff.chunk.js → 502.7bba43b1.chunk.js} +1 -1
- package/build/6158.c3c13c20.chunk.js +1 -0
- package/build/6691.4985ef22.chunk.js +105 -0
- package/build/{7464.592a9295.chunk.js → 7464.eb057bec.chunk.js} +1 -1
- package/build/78.dcc6df5c.chunk.js +1 -0
- package/build/{8276.e519a707.chunk.js → 8276.be3ed581.chunk.js} +2 -2
- package/build/{2747.d1442a90.chunk.js → 9806.5d5a0e8d.chunk.js} +64 -72
- package/build/9944.7af075a5.chunk.js +26 -0
- package/build/Admin-authenticatedApp.43b6ec9a.chunk.js +79 -0
- package/build/Admin_InternalErrorPage.38155af3.chunk.js +1 -0
- package/build/Admin_homePage.6f128523.chunk.js +81 -0
- package/build/Admin_marketplace.061a6e5a.chunk.js +55 -0
- package/build/Admin_pluginsPage.16f837b8.chunk.js +6 -0
- package/build/Admin_profilePage.678bce24.chunk.js +13 -0
- package/build/Admin_settingsPage.af7309e4.chunk.js +111 -0
- package/build/{Upload_ConfigureTheView.345ac1e0.chunk.js → Upload_ConfigureTheView.3fc1c100.chunk.js} +1 -1
- package/build/admin-app.d63bd229.chunk.js +36 -0
- package/build/{admin-edit-roles-page.24bdf746.chunk.js → admin-edit-roles-page.38a6c863.chunk.js} +3 -3
- package/build/admin-edit-users.545fc882.chunk.js +10 -0
- package/build/{admin-roles-list.23ddff26.chunk.js → admin-roles-list.1e2e814d.chunk.js} +1 -1
- package/build/admin-users.b8ea5677.chunk.js +11 -0
- package/build/{api-tokens-create-page.46c2ea84.chunk.js → api-tokens-create-page.e0c15627.chunk.js} +1 -1
- package/build/{api-tokens-edit-page.58139df9.chunk.js → api-tokens-edit-page.9f2dce47.chunk.js} +1 -1
- package/build/{api-tokens-list-page.0af7d431.chunk.js → api-tokens-list-page.d747051c.chunk.js} +2 -2
- package/build/{audit-logs-settings-page.0f73ccf8.chunk.js → audit-logs-settings-page.96f9d608.chunk.js} +1 -1
- package/build/content-manager.ccff1078.chunk.js +1097 -0
- package/build/{content-type-builder-list-view.bf9be456.chunk.js → content-type-builder-list-view.b71cf240.chunk.js} +1 -1
- package/build/{content-type-builder.66066281.chunk.js → content-type-builder.e5669749.chunk.js} +18 -18
- package/build/{email-settings-page.2f7e35c0.chunk.js → email-settings-page.2809f0bf.chunk.js} +1 -1
- package/build/en-json.e12fd5fc.chunk.js +1 -0
- package/build/{i18n-settings-page.47f78016.chunk.js → i18n-settings-page.5f716172.chunk.js} +1 -1
- package/build/index.html +1 -1
- package/build/main.c6c9e04c.js +2859 -0
- package/build/{review-workflows-settings-create-view.d24a32b9.chunk.js → review-workflows-settings-create-view.4a156a19.chunk.js} +1 -1
- package/build/{review-workflows-settings-edit-view.6044b022.chunk.js → review-workflows-settings-edit-view.ce984d1f.chunk.js} +1 -1
- package/build/{review-workflows-settings-list-view.3f0ef4bc.chunk.js → review-workflows-settings-list-view.419b8deb.chunk.js} +2 -2
- package/build/runtime~main.dcf1cb45.js +2 -0
- package/build/{sso-settings-page.4dba0670.chunk.js → sso-settings-page.45153df5.chunk.js} +1 -1
- package/build/{transfer-tokens-create-page.1597e6ab.chunk.js → transfer-tokens-create-page.ebba16d8.chunk.js} +1 -1
- package/build/{transfer-tokens-edit-page.8741529f.chunk.js → transfer-tokens-edit-page.d7bb2b3e.chunk.js} +1 -1
- package/build/{transfer-tokens-list-page.d6986b03.chunk.js → transfer-tokens-list-page.cfe1736c.chunk.js} +2 -2
- package/build/{upload-settings.7f93d4c0.chunk.js → upload-settings.cc5ad813.chunk.js} +1 -1
- package/build/{upload.37488080.chunk.js → upload.756efc28.chunk.js} +1 -1
- package/build/{users-advanced-settings-page.17052d72.chunk.js → users-advanced-settings-page.818d84eb.chunk.js} +1 -1
- package/build/{users-email-settings-page.3de8ea50.chunk.js → users-email-settings-page.c1967c09.chunk.js} +1 -1
- package/build/{users-providers-settings-page.0eaa916d.chunk.js → users-providers-settings-page.11893e08.chunk.js} +1 -1
- package/build/{users-roles-settings-page.957ad48b.chunk.js → users-roles-settings-page.2b051e6a.chunk.js} +1 -1
- package/build/webhook-edit-page.de45c635.chunk.js +33 -0
- package/build/{webhook-list-page.65e1b5bb.chunk.js → webhook-list-page.ca91df8b.chunk.js} +1 -1
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js +42 -0
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/StageFilter.js +70 -0
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js +71 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +9 -217
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/AssigneeSelect.js +147 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/index.js +1 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/StageSelect.js +243 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/index.js +1 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/constants.js +2 -0
- package/ee/admin/content-manager/pages/ListSettingsView/constants.js +7 -0
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js +21 -0
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js +44 -17
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/index.js +1 -0
- package/ee/admin/pages/App/constants.js +5 -6
- package/ee/admin/pages/SettingsPage/constants.js +42 -27
- package/ee/server/constants/workflows.js +1 -0
- package/ee/server/controllers/index.js +1 -0
- package/ee/server/controllers/workflows/assignees/index.js +44 -0
- package/ee/server/routes/review-workflows.js +17 -0
- package/ee/server/services/index.js +1 -0
- package/ee/server/services/review-workflows/assignees.js +54 -0
- package/ee/server/services/review-workflows/metrics/index.js +5 -0
- package/ee/server/services/review-workflows/review-workflows.js +20 -11
- package/ee/server/validation/review-workflows.js +8 -0
- package/index.js +2 -6
- package/package.json +9 -9
- package/scripts/build.js +15 -15
- package/scripts/create-dev-plugins-file.js +5 -38
- package/server/controllers/role.js +2 -0
- package/server/controllers/user.js +2 -0
- package/server/services/permission/permissions-manager/index.js +3 -1
- package/server/services/permission/permissions-manager/sanitize.js +19 -7
- package/server/services/permission/permissions-manager/validate.js +218 -0
- package/utils/create-cache-dir.js +62 -16
- package/utils/create-plugins-exclude-path.js +3 -23
- package/utils/get-plugins.js +110 -0
- package/utils/index.js +1 -1
- package/webpack.config.js +10 -13
- package/admin/src/components/AuthenticatedApp.js +0 -229
- package/admin/src/content-manager/components/AttributeFilter/Filters.js +0 -58
- package/admin/src/content-manager/components/AttributeFilter/hooks/useAllowedAttributes.js +0 -42
- package/admin/src/content-manager/components/AttributeFilter/index.js +0 -40
- package/admin/src/content-manager/components/Wysiwyg/EditorStylesContainer.js +0 -344
- package/admin/src/pages/UseCasePage.js +0 -174
- package/build/2166.c837469a.chunk.js +0 -1
- package/build/3483.8517171f.chunk.js +0 -1
- package/build/3984.dda474f7.chunk.js +0 -1
- package/build/4546.7a3c0d03.chunk.js +0 -1
- package/build/5483.5bfbb00d.chunk.js +0 -6
- package/build/6158.c974fd83.chunk.js +0 -1
- package/build/748.fd2e5afd.chunk.js +0 -105
- package/build/773.6381d62d.chunk.js +0 -18
- package/build/7826.399afe81.chunk.js +0 -103
- package/build/8261.2525d35c.chunk.js +0 -7
- package/build/8299.62b67c72.chunk.js +0 -1
- package/build/Admin-AuthPage.90d64342.chunk.js +0 -35
- package/build/Admin-AuthenticatedApp.379ac945.chunk.js +0 -24
- package/build/Admin-UseCasePage.1f757db5.chunk.js +0 -13
- package/build/Admin_GuidedTourModal.8ccf1fbc.chunk.js +0 -12
- package/build/Admin_InternalErrorPage.9de92c6d.chunk.js +0 -9
- package/build/Admin_NotFoundPage.21620424.chunk.js +0 -9
- package/build/Admin_Onboarding.dbfa32f6.chunk.js +0 -43
- package/build/Admin_homePage.2000cbe9.chunk.js +0 -86
- package/build/Admin_marketplace.ec80e29b.chunk.js +0 -63
- package/build/Admin_pluginsPage.0c6851f8.chunk.js +0 -14
- package/build/Admin_profilePage.78cd8495.chunk.js +0 -21
- package/build/Admin_settingsPage.1760c3ce.chunk.js +0 -119
- package/build/StrapiApp.221fac30.chunk.js +0 -5
- package/build/admin-edit-users.5d10d444.chunk.js +0 -10
- package/build/admin-users.2b3e4305.chunk.js +0 -11
- package/build/content-manager.fb0833bd.chunk.js +0 -1099
- package/build/en-json.08c05fcf.chunk.js +0 -1
- package/build/main.ee3c1938.js +0 -2859
- package/build/runtime~main.397ee447.js +0 -2
- package/build/webhook-edit-page.665210af.chunk.js +0 -33
- package/scripts/create-plugins-file.js +0 -92
- package/utils/get-plugins-path.js +0 -41
- /package/server/services/permission/permissions-manager/{query-builers.js → query-builders.js} +0 -0
|
@@ -9,20 +9,29 @@ const getCustomAppConfigFile = require('./get-custom-app-config-file');
|
|
|
9
9
|
const getPkgPath = (name) => path.dirname(require.resolve(`${name}/package.json`));
|
|
10
10
|
|
|
11
11
|
async function createPluginsJs(plugins, dest) {
|
|
12
|
-
const pluginsArray = plugins.map(({ pathToPlugin, name }) => {
|
|
12
|
+
const pluginsArray = plugins.map(({ pathToPlugin, name, info }) => {
|
|
13
13
|
const shortName = _.camelCase(name);
|
|
14
14
|
|
|
15
|
+
let realPath = '';
|
|
16
|
+
|
|
15
17
|
/**
|
|
16
|
-
*
|
|
17
|
-
* The problem is that Webpack does not windows paths
|
|
18
|
-
* With this tool, we need to rely on "/" and not "\".
|
|
19
|
-
* This is the reason why '..\\..\\..\\node_modules\\@strapi\\plugin-content-type-builder/strapi-admin.js' was not working.
|
|
20
|
-
* The regexp at line 105 aims to replace the windows backslashes by standard slash so that webpack can deal with them.
|
|
21
|
-
* Backslash looks to work only for absolute paths with webpack => https://webpack.js.org/concepts/module-resolution/#absolute-paths
|
|
18
|
+
* We're using a module here so we want to keep using the module resolution procedure.
|
|
22
19
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
if (info?.packageName || info?.required) {
|
|
21
|
+
/**
|
|
22
|
+
* path.join, on windows, it uses backslashes to resolve path.
|
|
23
|
+
* The problem is that Webpack does not windows paths
|
|
24
|
+
* With this tool, we need to rely on "/" and not "\".
|
|
25
|
+
* This is the reason why '..\\..\\..\\node_modules\\@strapi\\plugin-content-type-builder/strapi-admin.js' was not working.
|
|
26
|
+
* The regexp at line 105 aims to replace the windows backslashes by standard slash so that webpack can deal with them.
|
|
27
|
+
* Backslash looks to work only for absolute paths with webpack => https://webpack.js.org/concepts/module-resolution/#absolute-paths
|
|
28
|
+
*/
|
|
29
|
+
realPath = path.join(pathToPlugin, 'strapi-admin').replace(/\\/g, '/');
|
|
30
|
+
} else {
|
|
31
|
+
realPath = path
|
|
32
|
+
.join(path.relative(path.resolve(dest, 'admin', 'src'), pathToPlugin), 'strapi-admin')
|
|
33
|
+
.replace(/\\/g, '/');
|
|
34
|
+
}
|
|
26
35
|
|
|
27
36
|
return {
|
|
28
37
|
name,
|
|
@@ -76,12 +85,49 @@ async function createCacheDir({ appDir, plugins }) {
|
|
|
76
85
|
'tsconfig.json'
|
|
77
86
|
);
|
|
78
87
|
|
|
79
|
-
const pluginsWithFront = Object.
|
|
80
|
-
.filter((
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
const pluginsWithFront = Object.entries(plugins)
|
|
89
|
+
.filter(([, plugin]) => {
|
|
90
|
+
/**
|
|
91
|
+
* There are two ways a plugin should be imported, either it's local to the strapi app,
|
|
92
|
+
* or it's an actual npm module that's installed and resolved via node_modules.
|
|
93
|
+
*
|
|
94
|
+
* We first check if the plugin is local to the strapi app, using a regular `resolve` because
|
|
95
|
+
* the pathToPlugin will be relative i.e. `/Users/my-name/strapi-app/src/plugins/my-plugin`.
|
|
96
|
+
*
|
|
97
|
+
* If the file doesn't exist well then it's probably a node_module, so instead we use `require.resolve`
|
|
98
|
+
* which will resolve the path to the module in node_modules. If it fails with the specific code `MODULE_NOT_FOUND`
|
|
99
|
+
* then it doesn't have an admin part to the package.
|
|
100
|
+
*
|
|
101
|
+
* NOTE: we should try to move to `./package.json[exports]` map with bundling of our own plugins,
|
|
102
|
+
* because these entry files are written in commonjs restricting features e.g. tree-shaking.
|
|
103
|
+
*/
|
|
104
|
+
try {
|
|
105
|
+
const isLocalPluginWithLegacyAdminFile = fs.existsSync(
|
|
106
|
+
path.resolve(`${plugin.pathToPlugin}/strapi-admin.js`)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if (!isLocalPluginWithLegacyAdminFile) {
|
|
110
|
+
const isModulewithLegacyAdminFile = require.resolve(
|
|
111
|
+
`${plugin.pathToPlugin}/strapi-admin.js`
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return isModulewithLegacyAdminFile;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return isLocalPluginWithLegacyAdminFile;
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (err.code === 'MODULE_NOT_FOUND') {
|
|
120
|
+
/**
|
|
121
|
+
* the plugin does not contain FE code, so we
|
|
122
|
+
* don't want to import it anyway
|
|
123
|
+
*/
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
83
129
|
})
|
|
84
|
-
.map((name) => ({ name, ...
|
|
130
|
+
.map(([name, plugin]) => ({ name, ...plugin }));
|
|
85
131
|
|
|
86
132
|
// create .cache dir
|
|
87
133
|
await fs.emptyDir(cacheDir);
|
|
@@ -128,4 +174,4 @@ async function createCacheDir({ appDir, plugins }) {
|
|
|
128
174
|
}
|
|
129
175
|
}
|
|
130
176
|
|
|
131
|
-
module.exports = createCacheDir;
|
|
177
|
+
module.exports = { createCacheDir, createPluginsJs };
|
|
@@ -1,40 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { sep, join } = require('path');
|
|
4
|
-
|
|
5
3
|
const NODE_MODULES = 'node_modules';
|
|
6
4
|
/**
|
|
7
5
|
* @param {string[]} pluginsPath – an array of paths to the plugins from the user's directory
|
|
8
6
|
* @returns {RegExp} a regex that will exclude _all_ node_modules except for the plugins in the pluginsPath array.
|
|
9
7
|
*/
|
|
10
8
|
const createPluginsExcludePath = (pluginsPath = []) => {
|
|
11
|
-
/**
|
|
12
|
-
* converts the full path to just the plugin path
|
|
13
|
-
* e.g. `/Users/username/strapi/node_modules/@scope/plugin-name`
|
|
14
|
-
* to `@scope/plugin-name`
|
|
15
|
-
*/
|
|
16
|
-
const tsxPlugins = pluginsPath.reduce((acc, curr) => {
|
|
17
|
-
const dirPaths = curr.split(sep);
|
|
18
|
-
|
|
19
|
-
const nodeModulePathIndex = dirPaths.findIndex((val) => val === NODE_MODULES);
|
|
20
|
-
|
|
21
|
-
if (nodeModulePathIndex > 0) {
|
|
22
|
-
const pluginNodeModulePath = dirPaths.slice(nodeModulePathIndex + 1);
|
|
23
|
-
return [...acc, join(...pluginNodeModulePath)];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return acc;
|
|
27
|
-
}, []);
|
|
28
|
-
|
|
29
9
|
/**
|
|
30
10
|
* If there aren't any plugins in the node_modules array, just return the node_modules regex
|
|
31
11
|
* without complicating it.
|
|
32
12
|
*/
|
|
33
|
-
if (
|
|
13
|
+
if (pluginsPath.length === 0) {
|
|
34
14
|
return /node_modules/;
|
|
35
15
|
}
|
|
36
16
|
|
|
37
|
-
return new RegExp(`${NODE_MODULES}/(?!(${
|
|
17
|
+
return new RegExp(`${NODE_MODULES}/(?!(${pluginsPath.join('|')}))`);
|
|
38
18
|
};
|
|
39
19
|
|
|
40
|
-
module.exports = createPluginsExcludePath;
|
|
20
|
+
module.exports = { createPluginsExcludePath };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { join, resolve, sep, posix } = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
6
|
+
const glob = require('glob');
|
|
7
|
+
|
|
8
|
+
const getPlugins = (pluginsAllowlist) => {
|
|
9
|
+
const rootPath = resolve(__dirname, '..', join('..', '..', '..', 'packages'));
|
|
10
|
+
/**
|
|
11
|
+
* So `glob` only supports '/' as a path separator, so we need to replace
|
|
12
|
+
* the path separator for the current OS with '/'. e.g. on windows it's `\`.
|
|
13
|
+
*
|
|
14
|
+
* see https://github.com/isaacs/node-glob/#windows for more information
|
|
15
|
+
*
|
|
16
|
+
* and see https://github.com/isaacs/node-glob/issues/467#issuecomment-1114240501 for the recommended fix.
|
|
17
|
+
*/
|
|
18
|
+
let corePath = join(rootPath, 'core', '*');
|
|
19
|
+
let pluginsPath = join(rootPath, 'plugins', '*');
|
|
20
|
+
|
|
21
|
+
if (process.platform === 'win32') {
|
|
22
|
+
corePath = corePath.split(sep).join(posix.sep);
|
|
23
|
+
pluginsPath = pluginsPath.split(sep).join(posix.sep);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const corePackageDirs = glob.sync(corePath);
|
|
27
|
+
const pluginsPackageDirs = glob.sync(pluginsPath);
|
|
28
|
+
|
|
29
|
+
const plugins = [...corePackageDirs, ...pluginsPackageDirs]
|
|
30
|
+
.map((directory) => {
|
|
31
|
+
const isCoreAdmin = directory.includes('packages/core/admin');
|
|
32
|
+
|
|
33
|
+
if (isCoreAdmin) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const { name, strapi } = require(join(directory, 'package.json'));
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* this will remove any of our packages that are
|
|
41
|
+
* not actually plugins for the application
|
|
42
|
+
*/
|
|
43
|
+
if (!strapi) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* we want the name of the node_module
|
|
49
|
+
*/
|
|
50
|
+
return {
|
|
51
|
+
pathToPlugin: name,
|
|
52
|
+
name: strapi.name,
|
|
53
|
+
info: { ...strapi, packageName: name },
|
|
54
|
+
directory,
|
|
55
|
+
};
|
|
56
|
+
})
|
|
57
|
+
.filter((plugin) => {
|
|
58
|
+
if (!plugin) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* There are two ways a plugin should be imported, either it's local to the strapi app,
|
|
64
|
+
* or it's an actual npm module that's installed and resolved via node_modules.
|
|
65
|
+
*
|
|
66
|
+
* We first check if the plugin is local to the strapi app, using a regular `resolve` because
|
|
67
|
+
* the pathToPlugin will be relative i.e. `/Users/my-name/strapi-app/src/plugins/my-plugin`.
|
|
68
|
+
*
|
|
69
|
+
* If the file doesn't exist well then it's probably a node_module, so instead we use `require.resolve`
|
|
70
|
+
* which will resolve the path to the module in node_modules. If it fails with the specific code `MODULE_NOT_FOUND`
|
|
71
|
+
* then it doesn't have an admin part to the package.
|
|
72
|
+
*
|
|
73
|
+
* NOTE: we should try to move to `./package.json[exports]` map with bundling of our own plugins,
|
|
74
|
+
* because these entry files are written in commonjs restricting features e.g. tree-shaking.
|
|
75
|
+
*/
|
|
76
|
+
try {
|
|
77
|
+
const isLocalPluginWithLegacyAdminFile = fs.existsSync(
|
|
78
|
+
resolve(`${plugin.pathToPlugin}/strapi-admin.js`)
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (!isLocalPluginWithLegacyAdminFile) {
|
|
82
|
+
const isModulewithLegacyAdminFile = require.resolve(
|
|
83
|
+
`${plugin.pathToPlugin}/strapi-admin.js`
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
return isModulewithLegacyAdminFile;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return isLocalPluginWithLegacyAdminFile;
|
|
90
|
+
} catch (err) {
|
|
91
|
+
if (err.code === 'MODULE_NOT_FOUND') {
|
|
92
|
+
/**
|
|
93
|
+
* the plugin does not contain FE code, so we
|
|
94
|
+
* don't want to import it anyway
|
|
95
|
+
*/
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (Array.isArray(pluginsAllowlist)) {
|
|
104
|
+
return plugins.filter((plugin) => pluginsAllowlist.includes(plugin.pathToPlugin));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return plugins;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
module.exports = { getPlugins };
|
package/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const createCacheDir = require('./create-cache-dir');
|
|
3
|
+
const { createCacheDir } = require('./create-cache-dir');
|
|
4
4
|
const getCustomWebpackConfig = require('./get-custom-webpack-config');
|
|
5
5
|
const shouldBuildAdmin = require('./should-build-admin');
|
|
6
6
|
const watchAdminFiles = require('./watch-admin-files');
|
package/webpack.config.js
CHANGED
|
@@ -4,24 +4,23 @@ const path = require('path');
|
|
|
4
4
|
const webpack = require('webpack');
|
|
5
5
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
6
6
|
const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin');
|
|
7
|
+
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
|
7
8
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
8
9
|
const { ESBuildMinifyPlugin } = require('esbuild-loader');
|
|
9
10
|
const WebpackBar = require('webpackbar');
|
|
10
|
-
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
|
11
11
|
const browserslist = require('browserslist');
|
|
12
12
|
const browserslistToEsbuild = require('browserslist-to-esbuild');
|
|
13
13
|
|
|
14
14
|
const alias = require('./webpack.alias');
|
|
15
15
|
const getClientEnvironment = require('./env');
|
|
16
|
-
const createPluginsExcludePath = require('./utils/create-plugins-exclude-path');
|
|
16
|
+
const { createPluginsExcludePath } = require('./utils/create-plugins-exclude-path');
|
|
17
17
|
|
|
18
18
|
module.exports = ({
|
|
19
|
-
cacheDir,
|
|
20
19
|
dest,
|
|
21
20
|
entry,
|
|
22
21
|
env,
|
|
23
22
|
optimize,
|
|
24
|
-
|
|
23
|
+
plugins,
|
|
25
24
|
options = {
|
|
26
25
|
backend: 'http://localhost:1337',
|
|
27
26
|
adminPath: '/admin/',
|
|
@@ -45,7 +44,11 @@ module.exports = ({
|
|
|
45
44
|
]
|
|
46
45
|
: [];
|
|
47
46
|
|
|
48
|
-
const
|
|
47
|
+
const nodeModulePluginPaths = Object.values(plugins)
|
|
48
|
+
.filter((plugin) => plugin.info?.packageName || plugin.info?.required)
|
|
49
|
+
.map((plugin) => plugin.pathToPlugin);
|
|
50
|
+
|
|
51
|
+
const excludeRegex = createPluginsExcludePath(nodeModulePluginPaths);
|
|
49
52
|
|
|
50
53
|
// Ensure we use the config in this directory, even if run with a different
|
|
51
54
|
// working directory
|
|
@@ -84,7 +87,6 @@ module.exports = ({
|
|
|
84
87
|
{
|
|
85
88
|
test: /\.tsx?$/,
|
|
86
89
|
loader: require.resolve('esbuild-loader'),
|
|
87
|
-
include: [cacheDir, ...pluginsPath],
|
|
88
90
|
exclude: excludeRegex,
|
|
89
91
|
options: {
|
|
90
92
|
loader: 'tsx',
|
|
@@ -92,8 +94,8 @@ module.exports = ({
|
|
|
92
94
|
},
|
|
93
95
|
},
|
|
94
96
|
{
|
|
95
|
-
test: /\.
|
|
96
|
-
|
|
97
|
+
test: /\.(js|jsx|mjs)$/,
|
|
98
|
+
exclude: excludeRegex,
|
|
97
99
|
use: {
|
|
98
100
|
loader: require.resolve('esbuild-loader'),
|
|
99
101
|
options: {
|
|
@@ -150,10 +152,7 @@ module.exports = ({
|
|
|
150
152
|
},
|
|
151
153
|
resolve: {
|
|
152
154
|
alias,
|
|
153
|
-
symlinks: false,
|
|
154
155
|
extensions: ['.js', '.jsx', '.react.js', '.ts', '.tsx'],
|
|
155
|
-
mainFields: ['browser', 'module', 'jsnext:main', 'main'],
|
|
156
|
-
modules: ['node_modules', path.resolve(__dirname, 'node_modules')],
|
|
157
156
|
},
|
|
158
157
|
plugins: [
|
|
159
158
|
new HtmlWebpackPlugin({
|
|
@@ -167,9 +166,7 @@ module.exports = ({
|
|
|
167
166
|
configFile: tsConfigFilePath,
|
|
168
167
|
},
|
|
169
168
|
}),
|
|
170
|
-
|
|
171
169
|
!isProduction && process.env.REACT_REFRESH !== 'false' && new ReactRefreshWebpackPlugin(),
|
|
172
|
-
|
|
173
170
|
...webpackPlugins,
|
|
174
171
|
].filter(Boolean),
|
|
175
172
|
};
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
AppInfoProvider,
|
|
5
|
-
auth,
|
|
6
|
-
LoadingIndicatorPage,
|
|
7
|
-
useFetchClient,
|
|
8
|
-
useGuidedTour,
|
|
9
|
-
useNotification,
|
|
10
|
-
useStrapiApp,
|
|
11
|
-
} from '@strapi/helper-plugin';
|
|
12
|
-
import { useQueries } from 'react-query';
|
|
13
|
-
import { valid, lt } from 'semver';
|
|
14
|
-
|
|
15
|
-
import packageJSON from '../../../package.json';
|
|
16
|
-
import { useConfigurations } from '../hooks';
|
|
17
|
-
import { Admin } from '../pages/Admin';
|
|
18
|
-
import { getFullName } from '../utils/getFullName';
|
|
19
|
-
import { hashAdminUserEmail } from '../utils/uniqueAdminHash';
|
|
20
|
-
|
|
21
|
-
import RBACProvider from './RBACProvider';
|
|
22
|
-
|
|
23
|
-
const strapiVersion = packageJSON.version;
|
|
24
|
-
|
|
25
|
-
const checkLatestStrapiVersion = (currentPackageVersion, latestPublishedVersion) => {
|
|
26
|
-
if (!valid(currentPackageVersion) || !valid(latestPublishedVersion)) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return lt(currentPackageVersion, latestPublishedVersion);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export const AuthenticatedApp = () => {
|
|
34
|
-
const { setGuidedTourVisibility } = useGuidedTour();
|
|
35
|
-
const toggleNotification = useNotification();
|
|
36
|
-
const userInfo = auth.getUserInfo();
|
|
37
|
-
const { get } = useFetchClient();
|
|
38
|
-
// TODO: replace with getDisplayName()
|
|
39
|
-
const [userDisplayName, setUserDisplayName] = React.useState(
|
|
40
|
-
userInfo?.userName ?? getFullName(userInfo.firstname, userInfo.lastname)
|
|
41
|
-
);
|
|
42
|
-
const [userId, setUserId] = React.useState(null);
|
|
43
|
-
const { showReleaseNotification } = useConfigurations();
|
|
44
|
-
const { plugins: appPlugins = {} } = useStrapiApp();
|
|
45
|
-
const [plugins, setPlugins] = React.useState(appPlugins);
|
|
46
|
-
const [
|
|
47
|
-
{ data: appInfos, isLoading: isLoadingAppInfos },
|
|
48
|
-
{ data: tagName },
|
|
49
|
-
{ data: permissions, isLoading: isLoadingPermissions, refetch },
|
|
50
|
-
{ data: userRoles },
|
|
51
|
-
] = useQueries([
|
|
52
|
-
{
|
|
53
|
-
queryKey: 'information',
|
|
54
|
-
async queryFn() {
|
|
55
|
-
const {
|
|
56
|
-
data: { data },
|
|
57
|
-
} = await get('/admin/information');
|
|
58
|
-
|
|
59
|
-
return data;
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
queryKey: 'strapi-release',
|
|
65
|
-
async queryFn() {
|
|
66
|
-
const res = await fetch('https://api.github.com/repos/strapi/strapi/releases/latest');
|
|
67
|
-
|
|
68
|
-
if (!res.ok) {
|
|
69
|
-
throw new Error('Failed to fetch latest Strapi version.');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const { tag_name } = await res.json();
|
|
73
|
-
|
|
74
|
-
return tag_name;
|
|
75
|
-
},
|
|
76
|
-
enabled: showReleaseNotification,
|
|
77
|
-
initialData: strapiVersion,
|
|
78
|
-
onSuccess(data) {
|
|
79
|
-
const shouldUpdateStrapi = checkLatestStrapiVersion(strapiVersion, data.tag_name);
|
|
80
|
-
|
|
81
|
-
if (shouldUpdateStrapi && !JSON.parse(localStorage.getItem('STRAPI_UPDATE_NOTIF'))) {
|
|
82
|
-
toggleNotification({
|
|
83
|
-
type: 'info',
|
|
84
|
-
message: { id: 'notification.version.update.message' },
|
|
85
|
-
link: {
|
|
86
|
-
url: `https://github.com/strapi/strapi/releases/tag/${data.tag_name}`,
|
|
87
|
-
label: {
|
|
88
|
-
id: 'global.see-more',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
blockTransition: true,
|
|
92
|
-
onClose: () => localStorage.setItem('STRAPI_UPDATE_NOTIF', true),
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
retry: false,
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
queryKey: ['users', 'me', 'permissions'],
|
|
100
|
-
async queryFn() {
|
|
101
|
-
const {
|
|
102
|
-
data: { data },
|
|
103
|
-
} = await get('/admin/users/me/permissions');
|
|
104
|
-
|
|
105
|
-
return data;
|
|
106
|
-
},
|
|
107
|
-
initialData: [],
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
{
|
|
111
|
-
queryKey: ['users', 'me'],
|
|
112
|
-
async queryFn() {
|
|
113
|
-
const {
|
|
114
|
-
data: {
|
|
115
|
-
data: { roles },
|
|
116
|
-
},
|
|
117
|
-
} = await get('/admin/users/me');
|
|
118
|
-
|
|
119
|
-
return roles;
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
]);
|
|
123
|
-
|
|
124
|
-
// Display the guided tour conditionally for super admins in development mode
|
|
125
|
-
React.useEffect(() => {
|
|
126
|
-
if (userRoles) {
|
|
127
|
-
const isUserSuperAdmin = userRoles.find(({ code }) => code === 'strapi-super-admin');
|
|
128
|
-
|
|
129
|
-
if (isUserSuperAdmin && appInfos?.currentEnvironment === 'development') {
|
|
130
|
-
setGuidedTourVisibility(true);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}, [userRoles, appInfos, setGuidedTourVisibility]);
|
|
134
|
-
|
|
135
|
-
// Create a hash of the users email adress and use it as ID for tracking
|
|
136
|
-
React.useEffect(() => {
|
|
137
|
-
const generateUserId = async (userInfo) => {
|
|
138
|
-
const userId = await hashAdminUserEmail(userInfo);
|
|
139
|
-
setUserId(userId);
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
if (userInfo) {
|
|
143
|
-
generateUserId(userInfo);
|
|
144
|
-
}
|
|
145
|
-
}, [userInfo]);
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
*
|
|
149
|
-
* I have spent some time trying to understand what is happening here, and wanted to
|
|
150
|
-
* leave that knowledge for my future me:
|
|
151
|
-
*
|
|
152
|
-
* `initializer` is an undocumented property of the `registerPlugin` API. At the time
|
|
153
|
-
* of writing it seems only to be used by the i18n plugin.
|
|
154
|
-
*
|
|
155
|
-
* How does it work?
|
|
156
|
-
*
|
|
157
|
-
* Every plugin that has an `initializer` component defined, receives the
|
|
158
|
-
* `setPlugin` function as a component prop. In the case of i18n the plugin fetches locales
|
|
159
|
-
* first and calls `setPlugin` with `pluginId` once they are loaded, which then triggers the
|
|
160
|
-
* reducer of the admin app defined above.
|
|
161
|
-
*
|
|
162
|
-
* Once all plugins are set to `isReady: true` the app renders.
|
|
163
|
-
*
|
|
164
|
-
* This API is used to block rendering of the admin app. We should remove that in v5 completely
|
|
165
|
-
* and make sure plugins can inject data into the global store before they are initialized, to avoid
|
|
166
|
-
* having a new prop-callback based communication channel between plugins and the core admin app.
|
|
167
|
-
*
|
|
168
|
-
*/
|
|
169
|
-
|
|
170
|
-
const hasApluginNotReady = Object.values(plugins).some((plugin) => plugin.isReady === false);
|
|
171
|
-
|
|
172
|
-
if (
|
|
173
|
-
!userDisplayName ||
|
|
174
|
-
!userId ||
|
|
175
|
-
isLoadingAppInfos ||
|
|
176
|
-
isLoadingPermissions ||
|
|
177
|
-
hasApluginNotReady
|
|
178
|
-
) {
|
|
179
|
-
const initializers = Object.keys(plugins).reduce((acc, current) => {
|
|
180
|
-
const InitializerComponent = plugins[current].initializer;
|
|
181
|
-
|
|
182
|
-
if (InitializerComponent) {
|
|
183
|
-
const key = plugins[current].pluginId;
|
|
184
|
-
|
|
185
|
-
acc.push(
|
|
186
|
-
<InitializerComponent
|
|
187
|
-
key={key}
|
|
188
|
-
setPlugin={(pluginId) => {
|
|
189
|
-
setPlugins((prev) => ({
|
|
190
|
-
...prev,
|
|
191
|
-
[pluginId]: {
|
|
192
|
-
...prev[pluginId],
|
|
193
|
-
isReady: true,
|
|
194
|
-
},
|
|
195
|
-
}));
|
|
196
|
-
}}
|
|
197
|
-
/>
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return acc;
|
|
202
|
-
}, []);
|
|
203
|
-
|
|
204
|
-
return (
|
|
205
|
-
<>
|
|
206
|
-
{initializers}
|
|
207
|
-
<LoadingIndicatorPage />
|
|
208
|
-
</>
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return (
|
|
213
|
-
<AppInfoProvider
|
|
214
|
-
{...appInfos}
|
|
215
|
-
userId={userId}
|
|
216
|
-
latestStrapiReleaseTag={tagName}
|
|
217
|
-
// TODO: setUserDisplayName should not exist and be removed, as it is only used
|
|
218
|
-
// to update the displayName immediately, in case a user updates their profile.
|
|
219
|
-
// This information should be derived from the state.
|
|
220
|
-
setUserDisplayName={setUserDisplayName}
|
|
221
|
-
shouldUpdateStrapi={checkLatestStrapiVersion(strapiVersion, tagName)}
|
|
222
|
-
userDisplayName={userDisplayName}
|
|
223
|
-
>
|
|
224
|
-
<RBACProvider permissions={permissions} refetchPermissions={refetch}>
|
|
225
|
-
<Admin />
|
|
226
|
-
</RBACProvider>
|
|
227
|
-
</AppInfoProvider>
|
|
228
|
-
);
|
|
229
|
-
};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import React, { useRef, useState } from 'react';
|
|
2
|
-
|
|
3
|
-
import { Box, Button } from '@strapi/design-system';
|
|
4
|
-
import { FilterListURLQuery, FilterPopoverURLQuery, useTracking } from '@strapi/helper-plugin';
|
|
5
|
-
import { Filter } from '@strapi/icons';
|
|
6
|
-
import PropTypes from 'prop-types';
|
|
7
|
-
import { useIntl } from 'react-intl';
|
|
8
|
-
|
|
9
|
-
const Filters = ({ displayedFilters }) => {
|
|
10
|
-
const [isVisible, setIsVisible] = useState(false);
|
|
11
|
-
const { formatMessage } = useIntl();
|
|
12
|
-
const buttonRef = useRef();
|
|
13
|
-
const { trackUsage } = useTracking();
|
|
14
|
-
|
|
15
|
-
const handleToggle = () => {
|
|
16
|
-
if (!isVisible) {
|
|
17
|
-
trackUsage('willFilterEntries');
|
|
18
|
-
}
|
|
19
|
-
setIsVisible((prev) => !prev);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<>
|
|
24
|
-
<Box paddingTop={1} paddingBottom={1}>
|
|
25
|
-
<Button
|
|
26
|
-
variant="tertiary"
|
|
27
|
-
ref={buttonRef}
|
|
28
|
-
startIcon={<Filter />}
|
|
29
|
-
onClick={handleToggle}
|
|
30
|
-
size="S"
|
|
31
|
-
>
|
|
32
|
-
{formatMessage({ id: 'app.utils.filters', defaultMessage: 'Filters' })}
|
|
33
|
-
</Button>
|
|
34
|
-
{isVisible && (
|
|
35
|
-
<FilterPopoverURLQuery
|
|
36
|
-
displayedFilters={displayedFilters}
|
|
37
|
-
isVisible={isVisible}
|
|
38
|
-
onToggle={handleToggle}
|
|
39
|
-
source={buttonRef}
|
|
40
|
-
/>
|
|
41
|
-
)}
|
|
42
|
-
</Box>
|
|
43
|
-
<FilterListURLQuery filtersSchema={displayedFilters} />
|
|
44
|
-
</>
|
|
45
|
-
);
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
Filters.propTypes = {
|
|
49
|
-
displayedFilters: PropTypes.arrayOf(
|
|
50
|
-
PropTypes.shape({
|
|
51
|
-
name: PropTypes.string.isRequired,
|
|
52
|
-
metadatas: PropTypes.shape({ label: PropTypes.string }),
|
|
53
|
-
fieldSchema: PropTypes.shape({ type: PropTypes.string }),
|
|
54
|
-
})
|
|
55
|
-
).isRequired,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export default Filters;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { findMatchingPermissions, useRBACProvider } from '@strapi/helper-plugin';
|
|
2
|
-
import get from 'lodash/get';
|
|
3
|
-
|
|
4
|
-
const NOT_ALLOWED_FILTERS = ['json', 'component', 'media', 'richtext', 'dynamiczone', 'password'];
|
|
5
|
-
const TIMESTAMPS = ['createdAt', 'updatedAt'];
|
|
6
|
-
|
|
7
|
-
const useAllowedAttributes = (contentType, slug) => {
|
|
8
|
-
const { allPermissions } = useRBACProvider();
|
|
9
|
-
|
|
10
|
-
const readPermissionsForSlug = findMatchingPermissions(allPermissions, [
|
|
11
|
-
{
|
|
12
|
-
action: 'plugin::content-manager.explorer.read',
|
|
13
|
-
subject: slug,
|
|
14
|
-
},
|
|
15
|
-
]);
|
|
16
|
-
|
|
17
|
-
const readPermissionForAttr = get(readPermissionsForSlug, ['0', 'properties', 'fields'], []);
|
|
18
|
-
const attributesArray = Object.keys(get(contentType, ['attributes']), {});
|
|
19
|
-
const allowedAttributes = attributesArray
|
|
20
|
-
.filter((attr) => {
|
|
21
|
-
const current = get(contentType, ['attributes', attr], {});
|
|
22
|
-
|
|
23
|
-
if (!current.type) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (NOT_ALLOWED_FILTERS.includes(current.type)) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (!readPermissionForAttr.includes(attr) && attr !== 'id' && !TIMESTAMPS.includes(attr)) {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return true;
|
|
36
|
-
})
|
|
37
|
-
.sort();
|
|
38
|
-
|
|
39
|
-
return allowedAttributes;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export default useAllowedAttributes;
|