Skip to content

Commit cc7da36

Browse files
authored
Merge pull request #1 from boazpoolman/develop
Develop
2 parents c85fa56 + cce963e commit cc7da36

File tree

17 files changed

+554
-201
lines changed

17 files changed

+554
-201
lines changed

README.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ That's where this plugin comes in to play. It allows you to export these configs
66

77
Importing, exporting and keeping track of config changes is done in the admin page of the plugin.
88

9-
*Currently only the core_store changes are being tracked.*
10-
11-
**THIS PLUGIN IS STILL IN DEVELOPMENT**
9+
**THIS PLUGIN IS NOT STABLE**
1210

1311
**PLEASE USE WITH CARE**
1412

@@ -45,20 +43,40 @@ PLEASE USE WITH CARE.
4543

4644
> `required:` NO | `type:` bool | `default:` false
4745
46+
#### `include`
47+
48+
Configs you want to include. Allowed values: `core-store`, `role-permissions`, `webhooks`. By default these are all enabled.
49+
50+
> `required:` NO | `type:` array | `default:` ["core-store", "role-permissions", "webhooks"]
51+
4852
#### `exclude`
4953

5054
You might not want all your database config exported and managed in git. This settings allows you to add an array of config names which should not be tracked by the config-sync plugin.
5155

52-
For now only the `core_store` table is being tracked. Add the `key` value of a `core_store` item to the array to exclude it from being tracked.
56+
*Currently not working*
5357

5458
> `required:` NO | `type:` array | `default:` []
5559
60+
## Naming convention
61+
All the config files written in the file destination have the same naming convention. It goes as follows:
62+
63+
[config-type].[config-name].json
64+
65+
- `config-type` - Corresponds to the value in from the config.include setting.
66+
- `config-name` - The unique identifier of the config.
67+
- For `core-store` config this is the `key` value.
68+
- For `role-permissions` config this is the `type` value.
69+
- For `webhooks` config this is the `id` value
70+
71+
5672
## TODOs
57-
- Exporting of user roles & permissions
58-
- Exporting of webhooks
59-
- Specify which tables you want to track in the plugin configurations
73+
- ~~Exporting of user roles & permissions~~
74+
- ~~Exporting of webhooks~~
75+
- ~~Specify which tables you want to track in the plugin configurations~~
76+
- Exporting of EE roles & permissions
6077
- Add partial import/export functionality
6178
- Add CLI commands for importing/exporting
79+
- Track config deletions
6280

6381
## Resources
6482

admin/src/components/ActionButtons/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ const ActionButtons = ({ diff }) => {
2323

2424
return (
2525
<ActionButtonsStyling>
26-
<Button disabled={isEmpty(diff)} color="primary" label="Import" onClick={() => openModal('import')} />
27-
<Button disabled={isEmpty(diff)} color="primary" label="Export" onClick={() => openModal('export')} />
26+
<Button disabled={isEmpty(diff.diff)} color="primary" label="Import" onClick={() => openModal('import')} />
27+
<Button disabled={isEmpty(diff.diff)} color="primary" label="Export" onClick={() => openModal('export')} />
2828
<ConfirmModal
2929
isOpen={modalIsOpen}
3030
onClose={closeModal}

admin/src/components/ConfigList/index.js

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useState, useEffect } from 'react';
22
import { Table } from '@buffetjs/core';
3+
import { isEmpty } from 'lodash';
34
import ConfigDiff from '../ConfigDiff';
45

56
const headers = [
@@ -8,32 +9,40 @@ const headers = [
89
value: 'config_name',
910
},
1011
{
11-
name: 'Database table',
12-
value: 'table_name',
12+
name: 'Config type',
13+
value: 'config_type',
1314
},
1415
{
1516
name: 'Change',
1617
value: 'change_type',
1718
},
1819
];
1920

20-
const ConfigList = ({ fileConfig, databaseConfig, diff, isLoading }) => {
21+
const ConfigList = ({ diff, isLoading }) => {
2122
const [openModal, setOpenModal] = useState(false);
2223
const [originalConfig, setOriginalConfig] = useState({});
2324
const [newConfig, setNewConfig] = useState({});
2425
const [configName, setConfigName] = useState('');
2526
const [rows, setRows] = useState([]);
2627

2728
useEffect(() => {
29+
if (isEmpty(diff)) {
30+
setRows([]);
31+
return;
32+
}
33+
2834
let formattedRows = [];
29-
Object.keys(diff).map((config) => {
30-
// @TODO implement different config types, roles/permissions e.g.
35+
Object.keys(diff.fileConfig).map((configName) => {
36+
const type = configName.split('.')[0]; // Grab the first part of the filename.
37+
const name = configName.split(/\.(.+)/)[1].split('.')[0] // Grab the rest of the filename minus the file extension.
38+
3139
formattedRows.push({
32-
config_name: config,
33-
table_name: 'core_store',
40+
config_name: name,
41+
config_type: type,
3442
change_type: ''
3543
});
3644
});
45+
3746
setRows(formattedRows);
3847
}, [diff]);
3948

@@ -56,10 +65,10 @@ const ConfigList = ({ fileConfig, databaseConfig, diff, isLoading }) => {
5665
/>
5766
<Table
5867
headers={headers}
59-
onClickRow={(e, data) => {
60-
setOriginalConfig(fileConfig.get(data.config_name));
61-
setNewConfig(databaseConfig.get(data.config_name));
62-
setConfigName(data.config_name);
68+
onClickRow={(e, { config_type, config_name }) => {
69+
setOriginalConfig(diff.fileConfig[`${config_type}.${config_name}`]);
70+
setNewConfig(diff.databaseConfig[`${config_type}.${config_name}`]);
71+
setConfigName(`${config_type}.${config_name}`);
6372
setOpenModal(true);
6473
}}
6574
rows={!isLoading ? rows : []}

admin/src/containers/ConfigPage/index.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,23 @@ import React, { useEffect } from 'react';
22
import { useDispatch, useSelector } from 'react-redux';
33
import { Map } from 'immutable';
44

5-
import { getAllConfig } from '../../state/actions/Config';
5+
import { getAllConfigDiff } from '../../state/actions/Config';
66
import ConfigList from '../../components/ConfigList';
77
import ActionButtons from '../../components/ActionButtons';
8-
import difference from '../../helpers/getObjectDiff';
98

109
const ConfigPage = () => {
1110
const dispatch = useDispatch();
1211
const isLoading = useSelector((state) => state.getIn(['config', 'isLoading']), Map());
13-
const fileConfig = useSelector((state) => state.getIn(['config', 'fileConfig']), Map());
14-
const databaseConfig = useSelector((state) => state.getIn(['config', 'databaseConfig']), Map());
12+
const configDiff = useSelector((state) => state.getIn(['config', 'configDiff']), Map());
1513

1614
useEffect(() => {
17-
dispatch(getAllConfig());
15+
dispatch(getAllConfigDiff());
1816
}, []);
1917

20-
const diff = difference(fileConfig.toJS(), databaseConfig.toJS());
21-
2218
return (
2319
<div>
24-
<ActionButtons diff={diff} />
25-
<ConfigList fileConfig={fileConfig} databaseConfig={databaseConfig} isLoading={isLoading} diff={diff} />
20+
<ActionButtons diff={configDiff.toJS()} />
21+
<ConfigList isLoading={isLoading} diff={configDiff.toJS()} />
2622
</div>
2723
);
2824
}

admin/src/state/actions/Config.js

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@
77
import { request } from 'strapi-helper-plugin';
88
import { Map } from 'immutable';
99

10-
export function getAllConfig() {
10+
export function getAllConfigDiff() {
1111
return async function(dispatch) {
1212
dispatch(setLoadingState(true));
1313
try {
14-
const databaseConfig = await request('/config-sync/all/from-database', { method: 'GET' });
15-
const fileConfig = await request('/config-sync/all/from-files', { method: 'GET' });
16-
dispatch(setFileConfigInState(fileConfig));
17-
dispatch(setDatabaseConfigInState(databaseConfig));
14+
const configDiff = await request('/config-sync/diff', { method: 'GET' });
15+
dispatch(setConfigDiffInState(configDiff));
1816
dispatch(setLoadingState(false));
1917
} catch(err) {
2018
strapi.notification.error('notification.error');
@@ -23,18 +21,10 @@ export function getAllConfig() {
2321
}
2422
}
2523

26-
export const SET_DATABASE_CONFIG_IN_STATE = 'SET_DATABASE_CONFIG_IN_STATE';
27-
export function setDatabaseConfigInState(config) {
24+
export const SET_CONFIG_DIFF_IN_STATE = 'SET_CONFIG_DIFF_IN_STATE';
25+
export function setConfigDiffInState(config) {
2826
return {
29-
type: SET_DATABASE_CONFIG_IN_STATE,
30-
config,
31-
};
32-
}
33-
34-
export const SET_FILE_CONFIG_IN_STATE = 'SET_FILE_CONFIG_IN_STATE';
35-
export function setFileConfigInState(config) {
36-
return {
37-
type: SET_FILE_CONFIG_IN_STATE,
27+
type: SET_CONFIG_DIFF_IN_STATE,
3828
config,
3929
};
4030
}
@@ -44,8 +34,7 @@ export function exportAllConfig() {
4434
dispatch(setLoadingState(true));
4535
try {
4636
const { message } = await request('/config-sync/export', { method: 'GET' });
47-
dispatch(setFileConfigInState(Map({})));
48-
dispatch(setDatabaseConfigInState(Map({})));
37+
dispatch(setConfigDiffInState(Map({})));
4938

5039
strapi.notification.success(message);
5140
dispatch(setLoadingState(false));
@@ -61,8 +50,7 @@ export function importAllConfig() {
6150
dispatch(setLoadingState(true));
6251
try {
6352
const { message } = await request('/config-sync/import', { method: 'GET' });
64-
dispatch(setFileConfigInState(Map({})));
65-
dispatch(setDatabaseConfigInState(Map({})));
53+
dispatch(setConfigDiffInState(Map({})));
6654

6755
strapi.notification.success(message);
6856
dispatch(setLoadingState(false));

admin/src/state/reducers/Config/index.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,18 @@
55
*/
66

77
import { fromJS, Map } from 'immutable';
8-
import { SET_DATABASE_CONFIG_IN_STATE, SET_FILE_CONFIG_IN_STATE, SET_LOADING_STATE } from '../../actions/Config';
8+
import { SET_CONFIG_DIFF_IN_STATE, SET_LOADING_STATE } from '../../actions/Config';
99

1010
const initialState = fromJS({
11-
databaseConfig: Map({}),
12-
fileConfig: Map({}),
11+
configDiff: Map({}),
1312
isLoading: false,
1413
});
1514

1615
export default function configReducer(state = initialState, action) {
1716
switch (action.type) {
18-
case SET_DATABASE_CONFIG_IN_STATE:
17+
case SET_CONFIG_DIFF_IN_STATE:
1918
return state
20-
.update('databaseConfig', () => fromJS(action.config))
21-
case SET_FILE_CONFIG_IN_STATE:
22-
return state
23-
.update('fileConfig', () => fromJS(action.config))
19+
.update('configDiff', () => fromJS(action.config))
2420
case SET_LOADING_STATE:
2521
return state
2622
.update('isLoading', () => fromJS(action.value))

config/config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,10 @@
22
"destination": "extensions/config-sync/files/",
33
"minify": false,
44
"importOnBootstrap": false,
5+
"include": [
6+
"core-store",
7+
"role-permissions",
8+
"webhooks"
9+
],
510
"exclude": []
611
}

config/functions/bootstrap.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,10 @@ const fs = require('fs');
1212
* See more details here: https://strapi.io/documentation/v3.x/concepts/configurations.html#bootstrap
1313
*/
1414

15-
module.exports = () => {
15+
module.exports = async () => {
1616
if (strapi.plugins['config-sync'].config.importOnBootstrap) {
1717
if (fs.existsSync(strapi.plugins['config-sync'].config.destination)) {
18-
const configFiles = fs.readdirSync(strapi.plugins['config-sync'].config.destination);
19-
20-
configFiles.map((file) => {
21-
strapi.plugins['config-sync'].services.config.importFromFile(file.slice(0, -5));
22-
});
18+
await strapi.plugins['config-sync'].services.main.importAllConfig();
2319
}
2420
}
2521
};

config/routes.json

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,23 @@
33
{
44
"method": "GET",
55
"path": "/export",
6-
"handler": "config.export",
6+
"handler": "config.exportAll",
77
"config": {
88
"policies": []
99
}
1010
},
1111
{
1212
"method": "GET",
1313
"path": "/import",
14-
"handler": "config.import",
14+
"handler": "config.importAll",
1515
"config": {
1616
"policies": []
1717
}
1818
},
1919
{
2020
"method": "GET",
21-
"path": "/all/from-files",
22-
"handler": "config.getConfigsFromFiles",
23-
"config": {
24-
"policies": []
25-
}
26-
},
27-
{
28-
"method": "GET",
29-
"path": "/all/from-database",
30-
"handler": "config.getConfigsFromDatabase",
21+
"path": "/diff",
22+
"handler": "config.getDiff",
3123
"config": {
3224
"policies": []
3325
}

0 commit comments

Comments
 (0)