diff --git a/admin/src/components/ConfigDiff/index.jsx b/admin/src/components/ConfigDiff/index.jsx index 2599ac9..abdf266 100644 --- a/admin/src/components/ConfigDiff/index.jsx +++ b/admin/src/components/ConfigDiff/index.jsx @@ -1,6 +1,8 @@ import React from 'react'; +import { useDispatch } from 'react-redux'; import RDV, { DiffMethod } from 'react-diff-viewer-continued'; import { useIntl } from 'react-intl'; +import { getFetchClient, useNotification } from '@strapi/strapi/admin'; /** * An issue with the diff-viewer library causes a difference in the way the library is exported. @@ -19,13 +21,20 @@ if (typeof RDV.default !== 'undefined') { } import { + Button, Modal, Grid, Typography, } from '@strapi/design-system'; +import ConfirmModal from '../ConfirmModal'; +import { exportAllConfig, importAllConfig } from '../../state/actions/Config'; const ConfigDiff = ({ oldValue, newValue, configName, trigger }) => { const { formatMessage } = useIntl(); + const dispatch = useDispatch(); + const { toggleNotification } = useNotification(); + const { post, get } = getFetchClient(); + const commonHeadingStyle = { paddingRight: '2rem' }; return ( @@ -40,11 +49,24 @@ const ConfigDiff = ({ oldValue, newValue, configName, trigger }) => { - - {formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })} + + {formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })} + + Import} + onSubmit={(force) => dispatch(importAllConfig([configName], force, toggleNotification, formatMessage, post, get))} + /> - - {formatMessage({ id: 'config-sync.ConfigDiff.Database' })} + + + {formatMessage({ id: 'config-sync.ConfigDiff.Database' })} + + Export} + onSubmit={() => dispatch(exportAllConfig([configName], toggleNotification, formatMessage, post, get))} + /> diff --git a/playground/__tests__/cli.test.js b/playground/__tests__/cli.test.js index 8ace6c6..1006267 100644 --- a/playground/__tests__/cli.test.js +++ b/playground/__tests__/cli.test.js @@ -1,10 +1,16 @@ 'use strict'; +const fs = require('fs'); const util = require('util'); const exec = util.promisify(require('child_process').exec); jest.setTimeout(20000); +const selectedConfig = 'admin-role.strapi-editor'; +const otherConfig = 'admin-role.strapi-author'; +const selectedConfigPath = `config/sync/${selectedConfig}.json`; +const otherConfigPath = `config/sync/${otherConfig}.json`; + describe('Test the config-sync CLI', () => { afterAll(async () => { // Remove the generated files and the DB. @@ -19,6 +25,46 @@ describe('Test the config-sync CLI', () => { expect(diffOutput).toContain('No differences between DB and sync directory'); }); + test('Partial export only exports the selected config', async () => { + const selectedConfigBefore = fs.readFileSync(selectedConfigPath, 'utf8'); + const otherConfigBefore = fs.readFileSync(otherConfigPath, 'utf8'); + const selectedConfigData = JSON.parse(selectedConfigBefore); + selectedConfigData.description = `${selectedConfigData.description} (partial export test)`; + fs.writeFileSync(selectedConfigPath, JSON.stringify(selectedConfigData)); + + try { + const { stdout: exportOutput } = await exec(`yarn cs export --partial ${selectedConfig} -y`); + + expect(exportOutput).toContain(`Exported ${selectedConfig}`); + expect(exportOutput).not.toContain(`Exported ${otherConfig}`); + expect(JSON.parse(fs.readFileSync(selectedConfigPath, 'utf8'))).toEqual(JSON.parse(selectedConfigBefore)); + expect(fs.readFileSync(otherConfigPath, 'utf8')).toBe(otherConfigBefore); + } finally { + fs.writeFileSync(selectedConfigPath, selectedConfigBefore); + } + }); + + test('Partial import only imports the selected config', async () => { + const selectedConfigBefore = fs.readFileSync(selectedConfigPath, 'utf8'); + const otherConfigBefore = fs.readFileSync(otherConfigPath, 'utf8'); + const selectedConfigData = JSON.parse(selectedConfigBefore); + selectedConfigData.description = `${selectedConfigData.description} (partial import test)`; + fs.writeFileSync(selectedConfigPath, JSON.stringify(selectedConfigData)); + + try { + const { stdout: importOutput } = await exec(`yarn cs import --partial ${selectedConfig} -y`); + const { stdout: diffOutput } = await exec('yarn cs diff'); + + expect(importOutput).toContain(`Imported ${selectedConfig}`); + expect(importOutput).not.toContain(`Imported ${otherConfig}`); + expect(diffOutput).toContain('No differences between DB and sync directory'); + expect(fs.readFileSync(otherConfigPath, 'utf8')).toBe(otherConfigBefore); + } finally { + fs.writeFileSync(selectedConfigPath, selectedConfigBefore); + await exec(`yarn cs import --partial ${selectedConfig} -y`); + } + }); + test('Import (delete)', async () => { // Remove a file to trigger a delete. await exec('mv config/sync/admin-role.strapi-editor.json .tmp');