@strapi/admin 4.2.3 → 4.3.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/app.js +7 -4
- package/admin/src/components/LeftMenu/index.js +12 -2
- package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +5 -4
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +0 -8
- package/admin/src/content-manager/components/SelectMany/index.js +2 -4
- package/admin/src/content-manager/components/SelectWrapper/index.js +1 -13
- package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +2 -2
- package/admin/src/content-manager/pages/ListView/FieldPicker/index.js +9 -1
- package/admin/src/content-manager/utils/removeKeyInObject.js +0 -4
- package/admin/src/hooks/useFetchMarketplaceProviders/index.js +1 -1
- package/admin/src/index.js +1 -1
- package/admin/src/pages/Admin/index.js +21 -7
- package/admin/src/pages/App/constants.js +1 -0
- package/admin/src/pages/App/index.js +21 -3
- package/admin/src/pages/App/reducer.js +22 -0
- package/admin/src/pages/InstalledPluginsPage/Plugins.js +10 -2
- package/admin/src/pages/ProfilePage/index.js +19 -18
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromUrlForm.js +7 -3
- package/admin/src/pages/SettingsPage/pages/Users/EditPage/utils/layout.js +3 -1
- package/admin/src/pages/SettingsPage/pages/Users/ListPage/DynamicTable/TableRows/index.js +1 -1
- package/admin/src/pages/SettingsPage/pages/Users/ListPage/utils/tableHeaders.js +18 -4
- package/admin/src/pages/SettingsPage/pages/Users/components/SelectRoles/index.js +4 -1
- package/admin/src/reducers.js +4 -2
- package/admin/src/translations/en.json +37 -0
- package/admin/src/translations/zh-Hans.json +55 -8
- package/admin/src/tsconfig.json +10 -0
- package/build/1669.341e10d8.chunk.js +1 -0
- package/build/20.9e5a98b6.chunk.js +308 -0
- package/build/3332.1e443103.chunk.js +102 -0
- package/build/413.d5986568.chunk.js +284 -0
- package/build/{3180.ad280cb4.chunk.js → 5520.3c6bf86a.chunk.js} +34 -34
- package/build/{9166.5c585d7c.chunk.js → 8655.9073e17e.chunk.js} +59 -58
- package/build/8773.1b2ec266.chunk.js +327 -0
- package/build/9730.8fbe43ee.chunk.js +12 -0
- package/build/9799.ce46400f.chunk.js +760 -0
- package/build/Admin-authenticatedApp.ea608aff.chunk.js +80 -0
- package/build/{6102.1482bf98.chunk.js → Admin_InternalErrorPage.25c53284.chunk.js} +1 -1
- package/build/{Admin_homePage.4cc54224.chunk.js → Admin_homePage.118926e0.chunk.js} +1 -1
- package/build/{Admin_marketplace.91a1aacd.chunk.js → Admin_marketplace.8efd3fd0.chunk.js} +2 -2
- package/build/Admin_pluginsPage.0992c2b5.chunk.js +1 -0
- package/build/Admin_profilePage.35ce8e94.chunk.js +15 -0
- package/build/Admin_settingsPage.5fc517d7.chunk.js +178 -0
- package/build/admin-app.1bd5f67e.chunk.js +112 -0
- package/build/admin-edit-roles-page.358d98c1.chunk.js +1 -0
- package/build/admin-edit-users.714863af.chunk.js +10 -0
- package/build/admin-users.2bd6fb37.chunk.js +11 -0
- package/build/{api-tokens-edit-page.d41a0165.chunk.js → api-tokens-create-page.442e3be0.chunk.js} +1 -1
- package/build/api-tokens-edit-page.5f34eec7.chunk.js +1 -0
- package/build/{api-tokens-list-page.ec7c36f0.chunk.js → api-tokens-list-page.5ea3f6ce.chunk.js} +1 -1
- package/build/{codemirror-css.269ff90a.chunk.js → codemirror-css.4e2bbed3.chunk.js} +1 -1
- package/build/{codemirror-theme.bd70dd4c.chunk.js → codemirror-theme.a82cae4e.chunk.js} +1 -1
- package/build/content-manager.39bc9201.chunk.js +1176 -0
- package/build/content-type-builder-list-view.b12687b2.chunk.js +194 -0
- package/build/content-type-builder-translation-en-json.201bfb78.chunk.js +1 -0
- package/build/content-type-builder.ec6ccb59.chunk.js +142 -0
- package/build/{cropper-css.f4896679.chunk.js → cropper-css.12fe038c.chunk.js} +1 -1
- package/build/{email-settings-page.f12299bd.chunk.js → email-settings-page.818761d5.chunk.js} +2 -2
- package/build/email-translation-en-json.3d74ff95.chunk.js +1 -0
- package/build/email-translation-zh-Hans-json.8172da08.chunk.js +1 -0
- package/build/en-json.6d70e9ff.chunk.js +1 -0
- package/build/{fontawesome-css-all.4ecf62f5.chunk.js → fontawesome-css-all.15068c6e.chunk.js} +1 -1
- package/build/{fontawesome-css.18f0d57b.chunk.js → fontawesome-css.418f40da.chunk.js} +1 -1
- package/build/{highlight.js.22f875ca.chunk.js → highlight.js.af2de364.chunk.js} +1 -1
- package/build/i18n-settings-page.9d426e96.chunk.js +101 -0
- package/build/index.html +1 -1
- package/build/main.b19c2ee3.js +8675 -0
- package/build/runtime~main.426f9375.js +2 -0
- package/build/{sso-settings-page.2dbec3a3.chunk.js → sso-settings-page.445184e0.chunk.js} +1 -1
- package/build/{upload-settings.6c0eb939.chunk.js → upload-settings.4bad0bdd.chunk.js} +1 -1
- package/build/upload-translation-de-json.745613c0.chunk.js +1 -0
- package/build/upload-translation-dk-json.cb25dcf0.chunk.js +1 -0
- package/build/upload-translation-en-json.bc79c867.chunk.js +1 -0
- package/build/upload-translation-es-json.1f344b53.chunk.js +1 -0
- package/build/upload-translation-fr-json.e21c0c7a.chunk.js +1 -0
- package/build/upload-translation-he-json.4ce77b7b.chunk.js +1 -0
- package/build/upload-translation-it-json.5ce11e0b.chunk.js +1 -0
- package/build/upload-translation-ja-json.22afae44.chunk.js +1 -0
- package/build/upload-translation-ko-json.9a2c21cb.chunk.js +1 -0
- package/build/upload-translation-ms-json.0605d6da.chunk.js +1 -0
- package/build/upload-translation-pl-json.c1f86b50.chunk.js +1 -0
- package/build/upload-translation-pt-BR-json.95686cfb.chunk.js +1 -0
- package/build/upload-translation-ru-json.37bd1546.chunk.js +1 -0
- package/build/upload-translation-sk-json.b03d4904.chunk.js +1 -0
- package/build/upload-translation-th-json.64dd70ce.chunk.js +1 -0
- package/build/upload-translation-uk-json.1328cb3e.chunk.js +1 -0
- package/build/upload-translation-zh-Hans-json.37a2981e.chunk.js +1 -0
- package/build/upload-translation-zh-json.ee8fba96.chunk.js +1 -0
- package/build/upload.1346f4b1.chunk.js +7 -0
- package/build/{users-advanced-settings-page.06330ec9.chunk.js → users-advanced-settings-page.f38654fc.chunk.js} +1 -1
- package/build/users-email-settings-page.824a3cdb.chunk.js +101 -0
- package/build/{users-providers-settings-page.f011f210.chunk.js → users-providers-settings-page.a0b0fe39.chunk.js} +1 -1
- package/build/{users-roles-settings-page.d756dce9.chunk.js → users-roles-settings-page.3db986a4.chunk.js} +2 -2
- package/build/{webhook-edit-page.181ea60a.chunk.js → webhook-edit-page.3417d93c.chunk.js} +2 -2
- package/build/{webhook-list-page.b6000354.chunk.js → webhook-list-page.2ab4bbf0.chunk.js} +1 -1
- package/build/zh-Hans-json.eac1d90a.chunk.js +1 -0
- package/ee/admin/pages/SettingsPage/pages/Roles/CreatePage/index.js +3 -3
- package/index.js +47 -239
- package/package.json +14 -10
- package/scripts/build.js +19 -3
- package/server/controllers/admin.js +21 -0
- package/server/policies/index.js +1 -0
- package/server/policies/isTelemetryEnabled.js +16 -0
- package/server/routes/admin.js +8 -0
- package/server/routes/serve-admin-panel.js +1 -1
- package/utils/create-cache-dir.js +131 -0
- package/utils/get-custom-app-config-file.js +28 -0
- package/utils/get-custom-webpack-config.js +38 -0
- package/utils/get-plugins-path.js +26 -0
- package/utils/index.js +13 -0
- package/utils/should-build-admin.js +52 -0
- package/utils/watch-admin-files.js +59 -0
- package/webpack.alias.js +0 -1
- package/webpack.config.js +32 -10
- package/admin/src/content-manager/components/SelectWrapper/ClearIndicator.js +0 -18
- package/admin/src/content-manager/components/SelectWrapper/DropdownIndicator.js +0 -24
- package/admin/src/content-manager/components/SelectWrapper/IconBox.js +0 -20
- package/admin/src/content-manager/components/SelectWrapper/IndicatorSeparator.js +0 -3
- package/admin/src/content-manager/components/SelectWrapper/utils/getSelectStyles.js +0 -92
- package/build/2912.dd031292.chunk.js +0 -253
- package/build/3526.849d6a28.chunk.js +0 -162
- package/build/4094.ff4573b6.chunk.js +0 -194
- package/build/4982.c57c5675.chunk.js +0 -308
- package/build/6925.fb35248e.chunk.js +0 -761
- package/build/7810.c0d5e393.chunk.js +0 -113
- package/build/7841.9e9cf739.chunk.js +0 -253
- package/build/8681.334d9893.chunk.js +0 -163
- package/build/9298.fbe24a6e.chunk.js +0 -334
- package/build/948.d64fb515.chunk.js +0 -2
- package/build/Admin-authenticatedApp.a13de617.chunk.js +0 -80
- package/build/Admin_pluginsPage.b339b9c3.chunk.js +0 -1
- package/build/Admin_profilePage.369a0308.chunk.js +0 -15
- package/build/Admin_settingsPage.9bc7a0f0.chunk.js +0 -180
- package/build/admin-edit-roles-page.31acda7c.chunk.js +0 -1
- package/build/admin-edit-users.98a32ee5.chunk.js +0 -11
- package/build/admin-users.ab8ba52e.chunk.js +0 -12
- package/build/api-tokens-create-page.a3b9c8bd.chunk.js +0 -1
- package/build/content-manager.02509825.chunk.js +0 -1198
- package/build/content-type-builder-translation-en-json.ea3c66b3.chunk.js +0 -1
- package/build/content-type-builder.af41a338.chunk.js +0 -142
- package/build/email-translation-en-json.6da7e388.chunk.js +0 -1
- package/build/email-translation-zh-Hans-json.b463cb25.chunk.js +0 -1
- package/build/en-json.4f6bd46a.chunk.js +0 -1
- package/build/i18n-settings-page.c1ecebbc.chunk.js +0 -101
- package/build/main.48e0f6dc.js +0 -8434
- package/build/runtime~main.e9852fed.js +0 -2
- package/build/upload-translation-de-json.b642da08.chunk.js +0 -1
- package/build/upload-translation-dk-json.fc61df13.chunk.js +0 -1
- package/build/upload-translation-en-json.59269508.chunk.js +0 -1
- package/build/upload-translation-es-json.8ec935ef.chunk.js +0 -1
- package/build/upload-translation-fr-json.eb9b4f84.chunk.js +0 -1
- package/build/upload-translation-he-json.c226f2dc.chunk.js +0 -1
- package/build/upload-translation-it-json.8e58456e.chunk.js +0 -1
- package/build/upload-translation-ja-json.1378a2e7.chunk.js +0 -1
- package/build/upload-translation-ko-json.5e06e112.chunk.js +0 -1
- package/build/upload-translation-ms-json.dc3bf0d7.chunk.js +0 -1
- package/build/upload-translation-pl-json.bb2aa937.chunk.js +0 -1
- package/build/upload-translation-pt-BR-json.7e8d9550.chunk.js +0 -1
- package/build/upload-translation-ru-json.da2529f3.chunk.js +0 -1
- package/build/upload-translation-sk-json.bfdf4f09.chunk.js +0 -1
- package/build/upload-translation-th-json.6a48b826.chunk.js +0 -1
- package/build/upload-translation-uk-json.6fb09148.chunk.js +0 -1
- package/build/upload-translation-zh-Hans-json.c9622577.chunk.js +0 -1
- package/build/upload-translation-zh-json.711f804b.chunk.js +0 -1
- package/build/upload.92d5c845.chunk.js +0 -105
- package/build/users-email-settings-page.151b35a9.chunk.js +0 -1
- package/build/zh-Hans-json.cbc69f3d.chunk.js +0 -1
package/scripts/build.js
CHANGED
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const webpack = require('webpack');
|
|
5
5
|
const { isObject } = require('lodash');
|
|
6
|
+
// eslint-disable-next-line node/no-extraneous-require
|
|
7
|
+
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
|
|
8
|
+
|
|
6
9
|
const webpackConfig = require('../webpack.config');
|
|
10
|
+
const getPluginsPath = require('../utils/get-plugins-path');
|
|
7
11
|
const {
|
|
8
12
|
getCorePluginsPath,
|
|
9
13
|
getPluginToInstallPath,
|
|
@@ -12,29 +16,41 @@ const {
|
|
|
12
16
|
|
|
13
17
|
const PLUGINS_TO_INSTALL = ['i18n', 'users-permissions'];
|
|
14
18
|
|
|
19
|
+
// Wrapper that outputs the webpack speed
|
|
20
|
+
const smp = new SpeedMeasurePlugin();
|
|
21
|
+
|
|
15
22
|
const buildAdmin = async () => {
|
|
16
23
|
const entry = path.join(__dirname, '..', 'admin', 'src');
|
|
17
24
|
const dest = path.join(__dirname, '..', 'build');
|
|
25
|
+
const tsConfigFilePath = path.join(__dirname, '..', 'admin', 'src', 'tsconfig.json');
|
|
26
|
+
|
|
18
27
|
const corePlugins = getCorePluginsPath();
|
|
19
28
|
const plugins = getPluginToInstallPath(PLUGINS_TO_INSTALL);
|
|
20
29
|
const allPlugins = { ...corePlugins, ...plugins };
|
|
30
|
+
const pluginsPath = getPluginsPath();
|
|
21
31
|
|
|
22
32
|
await createPluginsFile(allPlugins);
|
|
23
33
|
|
|
24
34
|
const args = {
|
|
25
35
|
entry,
|
|
26
36
|
dest,
|
|
27
|
-
cacheDir: path.
|
|
28
|
-
pluginsPath
|
|
37
|
+
cacheDir: path.join(__dirname, '..'),
|
|
38
|
+
pluginsPath,
|
|
29
39
|
env: 'production',
|
|
30
40
|
optimize: true,
|
|
31
41
|
options: {
|
|
32
42
|
backend: 'http://localhost:1337',
|
|
33
43
|
adminPath: '/admin/',
|
|
34
44
|
},
|
|
45
|
+
tsConfigFilePath,
|
|
35
46
|
};
|
|
36
47
|
|
|
37
|
-
const
|
|
48
|
+
const config =
|
|
49
|
+
process.env.MEASURE_BUILD_SPEED === 'true'
|
|
50
|
+
? smp.wrap(webpackConfig(args))
|
|
51
|
+
: webpackConfig(args);
|
|
52
|
+
|
|
53
|
+
const compiler = webpack(config);
|
|
38
54
|
|
|
39
55
|
console.log('Building the admin panel');
|
|
40
56
|
|
|
@@ -5,6 +5,7 @@ const execa = require('execa');
|
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
const { exists } = require('fs-extra');
|
|
7
7
|
const { ValidationError } = require('@strapi/utils').errors;
|
|
8
|
+
const { isUsingTypeScript } = require('@strapi/typescript-utils');
|
|
8
9
|
// eslint-disable-next-line node/no-extraneous-require
|
|
9
10
|
const ee = require('@strapi/strapi/lib/utils/ee');
|
|
10
11
|
|
|
@@ -81,6 +82,26 @@ module.exports = {
|
|
|
81
82
|
return projectSettingsService.updateProjectSettings({ ...body, ...formatedFiles });
|
|
82
83
|
},
|
|
83
84
|
|
|
85
|
+
async telemetryProperties(ctx) {
|
|
86
|
+
// If the telemetry is disabled, ignore the request and return early
|
|
87
|
+
if (strapi.telemetry.isDisabled) {
|
|
88
|
+
ctx.status = 204;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const useTypescriptOnServer = await isUsingTypeScript(strapi.dirs.app.root);
|
|
93
|
+
const useTypescriptOnAdmin = await isUsingTypeScript(
|
|
94
|
+
path.join(strapi.dirs.app.root, 'src', 'admin')
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
data: {
|
|
99
|
+
useTypescriptOnServer,
|
|
100
|
+
useTypescriptOnAdmin,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
|
|
84
105
|
async information() {
|
|
85
106
|
const currentEnvironment = strapi.config.get('environment');
|
|
86
107
|
const autoReload = strapi.config.get('autoReload', false);
|
package/server/policies/index.js
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { createPolicy } = require('@strapi/utils').policy;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* This policy is used for routes dealing with telemetry and analytics content.
|
|
7
|
+
* It will fails when the telemetry has been disabled on the server.
|
|
8
|
+
*/
|
|
9
|
+
module.exports = createPolicy({
|
|
10
|
+
name: 'admin::isTelemetryEnabled',
|
|
11
|
+
handler(_ctx, _config, { strapi }) {
|
|
12
|
+
if (strapi.telemetry.isDisabled) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
});
|
package/server/routes/admin.js
CHANGED
|
@@ -49,6 +49,14 @@ module.exports = [
|
|
|
49
49
|
policies: ['admin::isAuthenticatedAdmin'],
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
|
+
{
|
|
53
|
+
method: 'GET',
|
|
54
|
+
path: '/telemetry-properties',
|
|
55
|
+
handler: 'admin.telemetryProperties',
|
|
56
|
+
config: {
|
|
57
|
+
auth: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
52
60
|
{
|
|
53
61
|
method: 'GET',
|
|
54
62
|
path: '/plugins',
|
|
@@ -5,7 +5,7 @@ const fse = require('fs-extra');
|
|
|
5
5
|
const koaStatic = require('koa-static');
|
|
6
6
|
|
|
7
7
|
const registerAdminPanelRoute = ({ strapi }) => {
|
|
8
|
-
let buildDir = resolve(strapi.dirs.root, 'build');
|
|
8
|
+
let buildDir = resolve(strapi.dirs.dist.root, 'build');
|
|
9
9
|
|
|
10
10
|
if (!fse.pathExistsSync(buildDir)) {
|
|
11
11
|
buildDir = resolve(__dirname, '../../build');
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const _ = require('lodash');
|
|
5
|
+
const fs = require('fs-extra');
|
|
6
|
+
const tsUtils = require('@strapi/typescript-utils');
|
|
7
|
+
const getCustomAppConfigFile = require('./get-custom-app-config-file');
|
|
8
|
+
|
|
9
|
+
const getPkgPath = name => path.dirname(require.resolve(`${name}/package.json`));
|
|
10
|
+
|
|
11
|
+
async function createPluginsJs(plugins, dest) {
|
|
12
|
+
const pluginsArray = plugins.map(({ pathToPlugin, name }) => {
|
|
13
|
+
const shortName = _.camelCase(name);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* path.join, on windows, it uses backslashes to resolve path.
|
|
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
|
|
22
|
+
*/
|
|
23
|
+
const realPath = path
|
|
24
|
+
.join(path.relative(path.resolve(dest, 'admin', 'src'), pathToPlugin), 'strapi-admin.js')
|
|
25
|
+
.replace(/\\/g, '/');
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
name,
|
|
29
|
+
pathToPlugin: realPath,
|
|
30
|
+
shortName,
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const content = `
|
|
35
|
+
${pluginsArray
|
|
36
|
+
.map(({ pathToPlugin, shortName }) => {
|
|
37
|
+
const req = `'${pathToPlugin}'`;
|
|
38
|
+
|
|
39
|
+
return `import ${shortName} from ${req};`;
|
|
40
|
+
})
|
|
41
|
+
.join('\n')}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
const plugins = {
|
|
45
|
+
${[...pluginsArray]
|
|
46
|
+
.map(({ name, shortName }) => {
|
|
47
|
+
return ` '${name}': ${shortName},`;
|
|
48
|
+
})
|
|
49
|
+
.join('\n')}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default plugins;
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
return fs.writeFile(path.resolve(dest, 'admin', 'src', 'plugins.js'), content);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function copyAdmin(dest) {
|
|
59
|
+
const adminPath = getPkgPath('@strapi/admin');
|
|
60
|
+
|
|
61
|
+
// TODO copy ee folders for plugins
|
|
62
|
+
await fs.copy(path.resolve(adminPath, 'ee', 'admin'), path.resolve(dest, 'ee', 'admin'));
|
|
63
|
+
|
|
64
|
+
await fs.ensureDir(path.resolve(dest, 'config'));
|
|
65
|
+
await fs.copy(path.resolve(adminPath, 'admin'), path.resolve(dest, 'admin'));
|
|
66
|
+
|
|
67
|
+
// Copy package.json
|
|
68
|
+
await fs.copy(path.resolve(adminPath, 'package.json'), path.resolve(dest, 'package.json'));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function createCacheDir({ appDir, plugins }) {
|
|
72
|
+
const cacheDir = path.resolve(appDir, '.cache');
|
|
73
|
+
|
|
74
|
+
const useTypeScript = await tsUtils.isUsingTypeScript(
|
|
75
|
+
path.join(appDir, 'src', 'admin'),
|
|
76
|
+
'tsconfig.json'
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const pluginsWithFront = Object.keys(plugins)
|
|
80
|
+
.filter(pluginName => {
|
|
81
|
+
const pluginInfo = plugins[pluginName];
|
|
82
|
+
return fs.existsSync(path.resolve(pluginInfo.pathToPlugin, 'strapi-admin.js'));
|
|
83
|
+
})
|
|
84
|
+
.map(name => ({ name, ...plugins[name] }));
|
|
85
|
+
|
|
86
|
+
// create .cache dir
|
|
87
|
+
await fs.emptyDir(cacheDir);
|
|
88
|
+
|
|
89
|
+
// copy admin core code
|
|
90
|
+
await copyAdmin(cacheDir);
|
|
91
|
+
|
|
92
|
+
// Retrieve the custom config file extension
|
|
93
|
+
const customAdminAppConfigFile = await getCustomAppConfigFile(appDir, useTypeScript);
|
|
94
|
+
|
|
95
|
+
if (customAdminAppConfigFile) {
|
|
96
|
+
const defaultAdminConfigFilePath = path.resolve(cacheDir, 'admin', 'src', 'app.js');
|
|
97
|
+
const customAdminAppConfigFilePath = path.join(
|
|
98
|
+
appDir,
|
|
99
|
+
'src',
|
|
100
|
+
'admin',
|
|
101
|
+
customAdminAppConfigFile
|
|
102
|
+
);
|
|
103
|
+
const dest = path.resolve(cacheDir, 'admin', 'src', customAdminAppConfigFile);
|
|
104
|
+
|
|
105
|
+
if (useTypeScript) {
|
|
106
|
+
// Remove the default config file
|
|
107
|
+
await fs.remove(defaultAdminConfigFilePath);
|
|
108
|
+
// Copy the custom one
|
|
109
|
+
await fs.copy(customAdminAppConfigFilePath, dest);
|
|
110
|
+
} else {
|
|
111
|
+
await fs.copy(customAdminAppConfigFilePath, dest);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Copy admin extensions folder
|
|
116
|
+
const adminExtensionFolder = path.join(appDir, 'src', 'admin', 'extensions');
|
|
117
|
+
|
|
118
|
+
if (fs.existsSync(adminExtensionFolder)) {
|
|
119
|
+
await fs.copy(adminExtensionFolder, path.resolve(cacheDir, 'admin', 'src', 'extensions'));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// create plugins.js with plugins requires
|
|
123
|
+
await createPluginsJs(pluginsWithFront, cacheDir);
|
|
124
|
+
|
|
125
|
+
// create the tsconfig.json file so we can develop plugins in ts while being in a JS project
|
|
126
|
+
if (!useTypeScript) {
|
|
127
|
+
await tsUtils.admin.createTSConfigFile(cacheDir);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = createCacheDir;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { join } = require('path');
|
|
4
|
+
const fse = require('fs-extra');
|
|
5
|
+
const { isUsingTypeScript } = require('@strapi/typescript-utils');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Retrieve the custom admin entry file name
|
|
9
|
+
* @param {String} dir - Directory of the admin panel
|
|
10
|
+
* @returns String
|
|
11
|
+
*/
|
|
12
|
+
const getCustomAppConfigFile = async dir => {
|
|
13
|
+
const adminSrcPath = join(dir, 'src', 'admin');
|
|
14
|
+
const useTypeScript = await isUsingTypeScript(adminSrcPath, 'tsconfig.json');
|
|
15
|
+
|
|
16
|
+
const files = await fse.readdir(adminSrcPath);
|
|
17
|
+
|
|
18
|
+
const appJsx = files.find(file => /^app.jsx?$/.test(file));
|
|
19
|
+
const appTsx = files.find(file => /^app.tsx?$/.test(file));
|
|
20
|
+
|
|
21
|
+
if (useTypeScript) {
|
|
22
|
+
return appTsx || appJsx;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return appJsx;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
module.exports = getCustomAppConfigFile;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const _ = require('lodash');
|
|
6
|
+
const webpack = require('webpack');
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const getWebpackConfig = require('../webpack.config');
|
|
9
|
+
|
|
10
|
+
const getCustomWebpackConfig = (dir, config) => {
|
|
11
|
+
const adminConfigPath = path.join(dir, 'src', 'admin', 'webpack.config.js');
|
|
12
|
+
|
|
13
|
+
let webpackConfig = getWebpackConfig(config);
|
|
14
|
+
|
|
15
|
+
if (fs.existsSync(adminConfigPath)) {
|
|
16
|
+
const webpackAdminConfig = require(path.resolve(adminConfigPath));
|
|
17
|
+
|
|
18
|
+
if (_.isFunction(webpackAdminConfig)) {
|
|
19
|
+
// Expose the devServer configuration
|
|
20
|
+
if (config.devServer) {
|
|
21
|
+
webpackConfig.devServer = config.devServer;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
webpackConfig = webpackAdminConfig(webpackConfig, webpack);
|
|
25
|
+
|
|
26
|
+
if (!webpackConfig) {
|
|
27
|
+
console.error(
|
|
28
|
+
`${chalk.red('Error:')} Nothing was returned from your custom webpack configuration`
|
|
29
|
+
);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return webpackConfig;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
module.exports = getCustomWebpackConfig;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { join, resolve } = require('path');
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const glob = require('glob');
|
|
6
|
+
|
|
7
|
+
// Only for dev environement
|
|
8
|
+
const getPluginsPath = () => {
|
|
9
|
+
const rootPath = resolve(__dirname, '..', join('..', '..', '..', 'packages'));
|
|
10
|
+
const corePath = join(rootPath, 'core', '*');
|
|
11
|
+
const pluginsPath = join(rootPath, 'plugins', '*');
|
|
12
|
+
const corePackageDirs = glob.sync(corePath);
|
|
13
|
+
const pluginsPackageDirs = glob.sync(pluginsPath);
|
|
14
|
+
|
|
15
|
+
const packageDirs = [...corePackageDirs, ...pluginsPackageDirs].filter(dir => {
|
|
16
|
+
const isCoreAdmin = dir.includes('packages/core/admin');
|
|
17
|
+
const pathToEntryPoint = join(dir, 'admin', 'src', 'index.js');
|
|
18
|
+
const doesAdminFolderExist = fs.pathExistsSync(pathToEntryPoint);
|
|
19
|
+
|
|
20
|
+
return !isCoreAdmin && doesAdminFolderExist;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return packageDirs.map(dir => resolve(__dirname, '..', join(dir, 'admin', 'src')));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
module.exports = getPluginsPath;
|
package/utils/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const createCacheDir = require('./create-cache-dir');
|
|
4
|
+
const getCustomWebpackConfig = require('./get-custom-webpack-config');
|
|
5
|
+
const shouldBuildAdmin = require('./should-build-admin');
|
|
6
|
+
const watchAdminFiles = require('./watch-admin-files');
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
createCacheDir,
|
|
10
|
+
getCustomWebpackConfig,
|
|
11
|
+
shouldBuildAdmin,
|
|
12
|
+
watchAdminFiles,
|
|
13
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const getCustomAppConfigFile = require('./get-custom-app-config-file');
|
|
6
|
+
|
|
7
|
+
const DEFAULT_PLUGINS = [
|
|
8
|
+
'content-type-builder',
|
|
9
|
+
'content-manager',
|
|
10
|
+
'upload',
|
|
11
|
+
'email',
|
|
12
|
+
'i18n',
|
|
13
|
+
'users-permissions',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Checks if the project's installed plugins are not the same as a default one.
|
|
18
|
+
* @param {Object} plugins
|
|
19
|
+
* @returns {boolean}
|
|
20
|
+
*/
|
|
21
|
+
const hasNonDefaultPlugins = plugins => {
|
|
22
|
+
// List of plugins that are not the ones installed in a generated app
|
|
23
|
+
const installedPlugins = Object.keys(plugins).filter(x => !DEFAULT_PLUGINS.includes(x));
|
|
24
|
+
|
|
25
|
+
// List of default plugins uninstalled from a generated app
|
|
26
|
+
const missingPlugins = DEFAULT_PLUGINS.filter(x => !Object.keys(plugins).includes(x));
|
|
27
|
+
|
|
28
|
+
const diff = [...installedPlugins, ...missingPlugins];
|
|
29
|
+
|
|
30
|
+
return diff.length > 0;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const hasCustomAdminCode = async dir => {
|
|
34
|
+
const customAdminPath = path.join(dir, 'src', 'admin');
|
|
35
|
+
|
|
36
|
+
const customAdminAppConfigFile = await getCustomAppConfigFile(dir);
|
|
37
|
+
const customAdminWebpackFile = path.join(customAdminPath, 'webpack.config.js');
|
|
38
|
+
|
|
39
|
+
const hasCustomConfigFile = !!customAdminAppConfigFile;
|
|
40
|
+
const hasCustomWebpackFile = await fs.pathExists(customAdminWebpackFile);
|
|
41
|
+
|
|
42
|
+
return hasCustomConfigFile || hasCustomWebpackFile;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const shouldBuildAdmin = async ({ appDir, plugins }) => {
|
|
46
|
+
const appHasCustomAdminCode = await hasCustomAdminCode(appDir);
|
|
47
|
+
const appHasNonDefaultPlugins = hasNonDefaultPlugins(plugins);
|
|
48
|
+
|
|
49
|
+
return appHasCustomAdminCode || appHasNonDefaultPlugins;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
module.exports = shouldBuildAdmin;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const chokidar = require('chokidar');
|
|
6
|
+
const { isUsingTypeScript } = require('@strapi/typescript-utils');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Listen to files change and copy the changed files in the .cache/admin folder
|
|
10
|
+
* when using the dev mode
|
|
11
|
+
* @param {string} dir
|
|
12
|
+
*/
|
|
13
|
+
async function watchAdminFiles(dir) {
|
|
14
|
+
const useTypeScript = await isUsingTypeScript(path.join(dir, 'src', 'admin'), 'tsconfig.json');
|
|
15
|
+
|
|
16
|
+
const cacheDir = path.join(dir, '.cache');
|
|
17
|
+
const targetExtensionFile = useTypeScript ? 'app.tsx' : 'app.js';
|
|
18
|
+
const appExtensionFile = path.join(dir, 'src', 'admin', targetExtensionFile);
|
|
19
|
+
const extensionsPath = path.join(dir, 'src', 'admin', 'extensions');
|
|
20
|
+
|
|
21
|
+
// Only watch the admin/app.js file and the files that are in the ./admin/extensions/folder
|
|
22
|
+
const filesToWatch = [appExtensionFile, extensionsPath];
|
|
23
|
+
|
|
24
|
+
const watcher = chokidar.watch(filesToWatch, {
|
|
25
|
+
ignoreInitial: true,
|
|
26
|
+
ignorePermissionErrors: true,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
watcher.on('all', async (event, filePath) => {
|
|
30
|
+
const isAppFile = filePath.includes(appExtensionFile);
|
|
31
|
+
|
|
32
|
+
// The app.js file needs to be copied in the .cache/admin/src/app.js and the other ones needs to
|
|
33
|
+
// be copied in the .cache/admin/src/extensions folder
|
|
34
|
+
const targetPath = isAppFile
|
|
35
|
+
? path.join(path.normalize(filePath.split(appExtensionFile)[1]), targetExtensionFile)
|
|
36
|
+
: path.join('extensions', path.normalize(filePath.split(extensionsPath)[1]));
|
|
37
|
+
|
|
38
|
+
const destFolder = path.join(cacheDir, 'admin', 'src');
|
|
39
|
+
|
|
40
|
+
if (event === 'unlink' || event === 'unlinkDir') {
|
|
41
|
+
// Remove the file or folder
|
|
42
|
+
// We need to copy the original files when deleting an override one
|
|
43
|
+
try {
|
|
44
|
+
fs.removeSync(path.join(destFolder, targetPath));
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.log('An error occured while deleting the file', err);
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
// In any other case just copy the file into the .cache/admin/src folder
|
|
50
|
+
try {
|
|
51
|
+
await fs.copy(filePath, path.join(destFolder, targetPath));
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.log(err);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = watchAdminFiles;
|
package/webpack.alias.js
CHANGED
package/webpack.config.js
CHANGED
|
@@ -4,6 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const fse = require('fs-extra');
|
|
5
5
|
const webpack = require('webpack');
|
|
6
6
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
7
|
+
const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin');
|
|
7
8
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
8
9
|
const { ESBuildMinifyPlugin } = require('esbuild-loader');
|
|
9
10
|
const WebpackBar = require('webpackbar');
|
|
@@ -16,12 +17,12 @@ const getClientEnvironment = require('./env');
|
|
|
16
17
|
const EE_REGEX = /from.* ['"]ee_else_ce\//;
|
|
17
18
|
|
|
18
19
|
module.exports = ({
|
|
19
|
-
entry,
|
|
20
20
|
cacheDir,
|
|
21
|
-
pluginsPath,
|
|
22
21
|
dest,
|
|
22
|
+
entry,
|
|
23
23
|
env,
|
|
24
24
|
optimize,
|
|
25
|
+
pluginsPath,
|
|
25
26
|
options = {
|
|
26
27
|
backend: 'http://localhost:1337',
|
|
27
28
|
adminPath: '/admin/',
|
|
@@ -31,6 +32,7 @@ module.exports = ({
|
|
|
31
32
|
eeRoot: './ee/admin',
|
|
32
33
|
ceRoot: './admin/src',
|
|
33
34
|
},
|
|
35
|
+
tsConfigFilePath,
|
|
34
36
|
}) => {
|
|
35
37
|
const isProduction = env === 'production';
|
|
36
38
|
|
|
@@ -38,10 +40,6 @@ module.exports = ({
|
|
|
38
40
|
|
|
39
41
|
const webpackPlugins = isProduction
|
|
40
42
|
? [
|
|
41
|
-
new webpack.IgnorePlugin({
|
|
42
|
-
resourceRegExp: /^\.\/locale$/,
|
|
43
|
-
contextRegExp: /moment$/,
|
|
44
|
-
}),
|
|
45
43
|
new MiniCssExtractPlugin({
|
|
46
44
|
filename: '[name].[chunkhash].css',
|
|
47
45
|
chunkFilename: '[name].[chunkhash].chunkhash.css',
|
|
@@ -51,12 +49,15 @@ module.exports = ({
|
|
|
51
49
|
]
|
|
52
50
|
: [];
|
|
53
51
|
|
|
52
|
+
// Directly inject a polyfill in the webpack entry point before the entry point
|
|
53
|
+
// FIXME: I have noticed a bug regarding the helper-plugin and esbuild-loader
|
|
54
|
+
// The only I could fix it was to inject the babel polyfill
|
|
54
55
|
const babelPolyfill = '@babel/polyfill/dist/polyfill.min.js';
|
|
55
56
|
|
|
56
57
|
return {
|
|
57
58
|
mode: isProduction ? 'production' : 'development',
|
|
58
59
|
bail: isProduction ? true : false,
|
|
59
|
-
devtool: false,
|
|
60
|
+
devtool: isProduction ? false : 'eval-source-map',
|
|
60
61
|
experiments: {
|
|
61
62
|
topLevelAwait: true,
|
|
62
63
|
},
|
|
@@ -77,10 +78,21 @@ module.exports = ({
|
|
|
77
78
|
css: true, // Apply minification to CSS assets
|
|
78
79
|
}),
|
|
79
80
|
],
|
|
81
|
+
moduleIds: 'deterministic',
|
|
80
82
|
runtimeChunk: true,
|
|
81
83
|
},
|
|
82
84
|
module: {
|
|
83
85
|
rules: [
|
|
86
|
+
{
|
|
87
|
+
test: /\.tsx?$/,
|
|
88
|
+
loader: require.resolve('esbuild-loader'),
|
|
89
|
+
include: [cacheDir, ...pluginsPath],
|
|
90
|
+
exclude: /node_modules/,
|
|
91
|
+
options: {
|
|
92
|
+
loader: 'tsx',
|
|
93
|
+
target: 'es2015',
|
|
94
|
+
},
|
|
95
|
+
},
|
|
84
96
|
{
|
|
85
97
|
test: /\.m?jsx?$/,
|
|
86
98
|
include: cacheDir,
|
|
@@ -96,6 +108,10 @@ module.exports = ({
|
|
|
96
108
|
try {
|
|
97
109
|
const fileContent = fse.readFileSync(filePath).toString();
|
|
98
110
|
|
|
111
|
+
if (fileContent.match(/from.* ['"]ee_else_ce\//)) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
99
115
|
return EE_REGEX.test(fileContent);
|
|
100
116
|
} catch (e) {
|
|
101
117
|
return false;
|
|
@@ -192,7 +208,7 @@ module.exports = ({
|
|
|
192
208
|
resolve: {
|
|
193
209
|
alias,
|
|
194
210
|
symlinks: false,
|
|
195
|
-
extensions: ['.js', '.jsx', '.react.js'],
|
|
211
|
+
extensions: ['.js', '.jsx', '.react.js', '.ts', '.tsx'],
|
|
196
212
|
mainFields: ['browser', 'jsnext:main', 'main'],
|
|
197
213
|
modules: ['node_modules', path.resolve(__dirname, 'node_modules')],
|
|
198
214
|
},
|
|
@@ -200,13 +216,19 @@ module.exports = ({
|
|
|
200
216
|
new HtmlWebpackPlugin({
|
|
201
217
|
inject: true,
|
|
202
218
|
template: path.resolve(__dirname, 'index.html'),
|
|
203
|
-
// FIXME
|
|
204
|
-
// favicon: path.resolve(__dirname, 'admin/src/favicon.ico'),
|
|
205
219
|
}),
|
|
206
220
|
new webpack.DefinePlugin(envVariables),
|
|
207
221
|
|
|
208
222
|
new NodePolyfillPlugin(),
|
|
223
|
+
|
|
224
|
+
new ForkTsCheckerPlugin({
|
|
225
|
+
typescript: {
|
|
226
|
+
configFile: tsConfigFilePath,
|
|
227
|
+
},
|
|
228
|
+
}),
|
|
229
|
+
|
|
209
230
|
!isProduction && process.env.REACT_REFRESH !== 'false' && new ReactRefreshWebpackPlugin(),
|
|
231
|
+
|
|
210
232
|
...webpackPlugins,
|
|
211
233
|
].filter(Boolean),
|
|
212
234
|
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { components } from 'react-select';
|
|
3
|
-
import Cross from '@strapi/icons/Cross';
|
|
4
|
-
import IconBox from './IconBox';
|
|
5
|
-
|
|
6
|
-
const ClearIndicator = props => {
|
|
7
|
-
const Component = components.ClearIndicator;
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<Component {...props}>
|
|
11
|
-
<IconBox as="button" type="button">
|
|
12
|
-
<Cross />
|
|
13
|
-
</IconBox>
|
|
14
|
-
</Component>
|
|
15
|
-
);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export default ClearIndicator;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import styled from 'styled-components';
|
|
3
|
-
import CarretDown from '@strapi/icons/CarretDown';
|
|
4
|
-
import IconBox from './IconBox';
|
|
5
|
-
|
|
6
|
-
export const CarretBox = styled(IconBox)`
|
|
7
|
-
display: flex;
|
|
8
|
-
background: none;
|
|
9
|
-
border: none;
|
|
10
|
-
|
|
11
|
-
svg {
|
|
12
|
-
width: ${6 / 16}rem;
|
|
13
|
-
}
|
|
14
|
-
`;
|
|
15
|
-
|
|
16
|
-
const DropdownIndicator = () => {
|
|
17
|
-
return (
|
|
18
|
-
<CarretBox as="button" type="button" paddingRight={3}>
|
|
19
|
-
<CarretDown />
|
|
20
|
-
</CarretBox>
|
|
21
|
-
);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export default DropdownIndicator;
|