Finalize main frontend functionality
parent
074224f56f
commit
ba95ed0e2d
|
@ -1,12 +1,35 @@
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
import { Button } from '@buffetjs/core';
|
import { Button } from '@buffetjs/core';
|
||||||
|
import ConfirmModal from '../ConfirmModal';
|
||||||
|
import { exportAllConfig, importAllConfig } from '../../state/actions/Config';
|
||||||
|
|
||||||
|
const ActionButtons = ({ diff }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [modalIsOpen, setModalIsOpen] = useState(false);
|
||||||
|
const [actionType, setActionType] = useState('');
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
setActionType('');
|
||||||
|
setModalIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openModal = (type) => {
|
||||||
|
setActionType(type);
|
||||||
|
setModalIsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
const ActionButtons = () => {
|
|
||||||
return (
|
return (
|
||||||
<ActionButtonsStyling>
|
<ActionButtonsStyling>
|
||||||
<Button color="primary" label="Import"/>
|
<Button disabled={!diff} color="primary" label="Import" onClick={() => openModal('import')} />
|
||||||
<Button color="primary" label="Export"/>
|
<Button disabled={!diff} color="primary" label="Export" onClick={() => openModal('export')} />
|
||||||
|
<ConfirmModal
|
||||||
|
isOpen={modalIsOpen}
|
||||||
|
onClose={closeModal}
|
||||||
|
type={actionType}
|
||||||
|
onSubmit={() => actionType === 'import' ? dispatch(importAllConfig()) : dispatch(exportAllConfig())}
|
||||||
|
/>
|
||||||
</ActionButtonsStyling>
|
</ActionButtonsStyling>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Table } from '@buffetjs/core';
|
import { Table } from '@buffetjs/core';
|
||||||
import difference from '../../helpers/getObjectDiff';
|
|
||||||
import ConfigDiff from '../ConfigDiff';
|
import ConfigDiff from '../ConfigDiff';
|
||||||
|
|
||||||
const headers = [
|
const headers = [
|
||||||
{
|
|
||||||
name: 'Id',
|
|
||||||
value: 'id',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Config name',
|
name: 'Config name',
|
||||||
value: 'name',
|
value: 'config_name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Database table',
|
name: 'Database table',
|
||||||
value: 'lastname',
|
value: 'table_name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Change',
|
name: 'Change',
|
||||||
|
@ -22,15 +17,21 @@ const headers = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const ConfigList = ({ fileConfig, databaseConfig }) => {
|
const ConfigList = ({ fileConfig, databaseConfig, isLoading, diff }) => {
|
||||||
const diff = difference(fileConfig.toJS(), databaseConfig.toJS());
|
|
||||||
const [openModal, setOpenModal] = useState(false);
|
const [openModal, setOpenModal] = useState(false);
|
||||||
const [originalConfig, setOriginalConfig] = useState({});
|
const [originalConfig, setOriginalConfig] = useState({});
|
||||||
const [newConfig, setNewConfig] = useState({});
|
const [newConfig, setNewConfig] = useState({});
|
||||||
const [configName, setConfigName] = useState('');
|
const [configName, setConfigName] = useState('');
|
||||||
let rows = [];
|
let rows = [];
|
||||||
|
|
||||||
Object.keys(diff).map((config) => rows.push({ name: config }));
|
Object.keys(diff).map((config) => {
|
||||||
|
// @TODO implement different config types, roles/permissions e.g.
|
||||||
|
rows.push({
|
||||||
|
config_name: config,
|
||||||
|
table_name: 'core_store',
|
||||||
|
change_type: ''
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
setOriginalConfig({});
|
setOriginalConfig({});
|
||||||
|
@ -49,15 +50,17 @@ const ConfigList = ({ fileConfig, databaseConfig }) => {
|
||||||
onToggle={closeModal}
|
onToggle={closeModal}
|
||||||
configName={configName}
|
configName={configName}
|
||||||
/>
|
/>
|
||||||
<Table
|
<Table
|
||||||
headers={headers}
|
headers={headers}
|
||||||
onClickRow={(e, data) => {
|
onClickRow={(e, data) => {
|
||||||
setOriginalConfig(fileConfig.get(data.name));
|
setOriginalConfig(fileConfig.get(data.config_name));
|
||||||
setNewConfig(databaseConfig.get(data.name));
|
setNewConfig(databaseConfig.get(data.config_name));
|
||||||
setConfigName(data.name);
|
setConfigName(data.config_name);
|
||||||
setOpenModal(true);
|
setOpenModal(true);
|
||||||
}}
|
}}
|
||||||
rows={rows}
|
rows={!isLoading ? rows : []}
|
||||||
|
tableEmptyText="No config changes. You are up to date!"
|
||||||
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
ModalConfirm,
|
||||||
|
} from 'strapi-helper-plugin';
|
||||||
|
|
||||||
|
import getTrad from '../../helpers/getTrad';
|
||||||
|
|
||||||
|
const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => {
|
||||||
|
return (
|
||||||
|
<ModalConfirm
|
||||||
|
confirmButtonLabel={{
|
||||||
|
id: getTrad(`popUpWarning.button.${type}`),
|
||||||
|
}}
|
||||||
|
isOpen={isOpen}
|
||||||
|
toggle={onClose}
|
||||||
|
onClosed={onClose}
|
||||||
|
onConfirm={() => {
|
||||||
|
onClose();
|
||||||
|
onSubmit();
|
||||||
|
}}
|
||||||
|
type="success"
|
||||||
|
content={{
|
||||||
|
id: getTrad(`popUpWarning.warning.${type}`),
|
||||||
|
values: {
|
||||||
|
br: () => <br />,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div>Zeker?</div>
|
||||||
|
</ModalConfirm>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConfirmModal;
|
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* HeaderComponent
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React, { memo } from 'react';
|
|
||||||
import { Header } from '@buffetjs/custom';
|
|
||||||
import { useGlobalContext } from 'strapi-helper-plugin';
|
|
||||||
|
|
||||||
const HeaderComponent = (props) => {
|
|
||||||
const globalContext = useGlobalContext();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Header
|
|
||||||
title={{ label: 'Config Sync' }}
|
|
||||||
content="Manage your database config across environments."
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(HeaderComponent);
|
|
|
@ -1,29 +1,30 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { Map } from 'immutable';
|
import { Map } from 'immutable';
|
||||||
|
|
||||||
import { getAllDatabaseConfig, getAllFileConfig } from '../../state/actions/Config';
|
import { getAllDatabaseConfig, getAllFileConfig } from '../../state/actions/Config';
|
||||||
import ConfigList from '../../components/ConfigList';
|
import ConfigList from '../../components/ConfigList';
|
||||||
import ActionButtons from '../../components/ActionButtons';
|
import ActionButtons from '../../components/ActionButtons';
|
||||||
|
import difference from '../../helpers/getObjectDiff';
|
||||||
|
|
||||||
const ConfigPage = () => {
|
const ConfigPage = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const fileConfig = useSelector((state) => state.getIn(['config', 'fileConfig']), Map());
|
const fileConfig = useSelector((state) => state.getIn(['config', 'fileConfig']), Map());
|
||||||
const databaseConfig = useSelector((state) => state.getIn(['config', 'databaseConfig']), Map());
|
const databaseConfig = useSelector((state) => state.getIn(['config', 'databaseConfig']), Map());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(getAllDatabaseConfig());
|
dispatch(getAllDatabaseConfig());
|
||||||
dispatch(getAllFileConfig());
|
dispatch(getAllFileConfig());
|
||||||
|
setIsLoading(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (fileConfig.size === 0 || databaseConfig.size === 0) {
|
const diff = difference(fileConfig.toJS(), databaseConfig.toJS());
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ActionButtons />
|
<ActionButtons diff={diff} />
|
||||||
<ConfigList fileConfig={fileConfig} databaseConfig={databaseConfig} />
|
<ConfigList fileConfig={fileConfig} databaseConfig={databaseConfig} isLoading={isLoading} diff={diff} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import pluginId from './pluginId';
|
||||||
|
|
||||||
|
const getTrad = id => `${pluginId}.${id}`;
|
||||||
|
|
||||||
|
export default getTrad;
|
|
@ -49,4 +49,34 @@ export function setFileConfigInState(config) {
|
||||||
type: SET_FILE_CONFIG_IN_STATE,
|
type: SET_FILE_CONFIG_IN_STATE,
|
||||||
config,
|
config,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exportAllConfig() {
|
||||||
|
return async function(dispatch) {
|
||||||
|
try {
|
||||||
|
const { message } = await request('/config/export', { method: 'GET' });
|
||||||
|
dispatch(getAllFileConfig());
|
||||||
|
dispatch(getAllDatabaseConfig());
|
||||||
|
|
||||||
|
strapi.notification.success(message);
|
||||||
|
} catch(err) {
|
||||||
|
console.log(err);
|
||||||
|
strapi.notification.error('notification.error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function importAllConfig() {
|
||||||
|
return async function(dispatch) {
|
||||||
|
try {
|
||||||
|
const { message } = await request('/config/import', { method: 'GET' });
|
||||||
|
dispatch(getAllFileConfig());
|
||||||
|
dispatch(getAllDatabaseConfig());
|
||||||
|
|
||||||
|
strapi.notification.success(message);
|
||||||
|
} catch(err) {
|
||||||
|
console.log(err);
|
||||||
|
strapi.notification.error('notification.error');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
{
|
{
|
||||||
|
"popUpWarning.warning.import": "If you continue all your local config files<br></br>will be imported into the database.",
|
||||||
|
"popUpWarning.warning.export": "If you continue all your database config<br></br>will be written into config files.",
|
||||||
|
"popUpWarning.button.import": "Yes, import",
|
||||||
|
"popUpWarning.button.export": "Yes, export",
|
||||||
"plugin.name": "Config Sync"
|
"plugin.name": "Config Sync"
|
||||||
}
|
}
|
Loading…
Reference in New Issue