From 5116804155364d6a87718e2368ed1348360d8b9b Mon Sep 17 00:00:00 2001 From: Mercy Date: Sun, 21 Jan 2024 20:02:58 -0500 Subject: [PATCH] 6364 update settings after menu changes (#6372) * update redux from recoil * remove old navlinks actions * e2e for menu updates --- app/react/Settings/actions/navlinksActions.js | 69 ------------ .../actions/specs/navlinksActions.spec.js | 106 ------------------ .../Routes/Settings/MenuConfig/MenuConfig.tsx | 6 +- app/react/V2/atoms/settingsAtom.ts | 9 ++ cypress/e2e/settings/menu.cy.ts | 10 ++ 5 files changed, 23 insertions(+), 177 deletions(-) delete mode 100644 app/react/Settings/actions/navlinksActions.js delete mode 100644 app/react/Settings/actions/specs/navlinksActions.spec.js diff --git a/app/react/Settings/actions/navlinksActions.js b/app/react/Settings/actions/navlinksActions.js deleted file mode 100644 index 122405b84d..0000000000 --- a/app/react/Settings/actions/navlinksActions.js +++ /dev/null @@ -1,69 +0,0 @@ -import { actions as formActions } from 'react-redux-form'; -import { RequestParams } from 'app/utils/RequestParams'; -import { t } from 'app/I18N'; - -import { actions } from 'app/BasicReducer'; -import { editLink } from 'app/Settings/actions/uiActions'; -import { notificationActions } from 'app/Notifications'; - -import ID from 'shared/uniqueID'; -import api from 'app/Settings/SettingsAPI'; -import * as types from 'app/Settings/actions/actionTypes'; - -export function loadLinks(links) { - return formActions.load('settings.navlinksData', { links }); -} - -export function addLink(links, type = 'link') { - const itemPrefix = t('System', 'Item', null, false); - const link = { title: `${itemPrefix} ${links.length + 1}`, localID: ID(), type, sublinks: [] }; - return dispatch => { - dispatch(formActions.push('settings.navlinksData.links', link)); - dispatch(editLink(link.localID)); - }; -} - -export function addGroupLink(links, index) { - const itemPrefix = t('System', 'Item', null, false); - const link = { - title: `${itemPrefix} ${index + 1} - ${links[index].sublinks.length + 1}`, - localID: ID(), - }; - return dispatch => { - dispatch(formActions.push(`settings.navlinksData.links[${index}].sublinks`, link)); - dispatch(editLink(link.localID)); - }; -} - -export function sortLink(originIndex, targetIndex) { - return formActions.move('settings.navlinksData.links', originIndex, targetIndex); -} - -export function removeLink(index) { - return formActions.remove('settings.navlinksData.links', index); -} - -export function removeGroupLink(groupLinkIndex, sublinkIndex) { - return formActions.remove( - `settings.navlinksData.links[${groupLinkIndex}].sublinks`, - sublinkIndex - ); -} - -export function saveLinks(data) { - return dispatch => { - dispatch({ type: types.SAVING_NAVLINKS }); - return api - .save(new RequestParams(data)) - .then(response => { - dispatch({ type: types.NAVLINKS_SAVED, data: response }); - dispatch(actions.set('settings/collection', response)); - dispatch( - notificationActions.notify(t('System', 'Saved successfully.', null, false), 'success') - ); - }) - .catch(() => { - dispatch({ type: types.NAVLINKS_SAVED, data }); - }); - }; -} diff --git a/app/react/Settings/actions/specs/navlinksActions.spec.js b/app/react/Settings/actions/specs/navlinksActions.spec.js deleted file mode 100644 index cc39c35d85..0000000000 --- a/app/react/Settings/actions/specs/navlinksActions.spec.js +++ /dev/null @@ -1,106 +0,0 @@ -import { actions as formActions } from 'react-redux-form'; -import { RequestParams } from 'app/utils/RequestParams'; - -import { actions as basicActions } from 'app/BasicReducer'; -import { mockID } from 'shared/uniqueID'; - -import { notificationActions } from 'app/Notifications'; - -import api from 'app/Settings/SettingsAPI'; -import * as uiActions from 'app/Settings/actions/uiActions'; - -import * as actions from '../navlinksActions'; - -describe('Settings/Navlinks actions', () => { - let dispatch; - - beforeEach(() => { - mockID(); - dispatch = jasmine.createSpy('dispatch'); - spyOn(api, 'save').and.callFake(async () => Promise.resolve({ _id: 'newId', _rev: 'newRev' })); - spyOn(formActions, 'load').and.returnValue('ITEMS LOADED'); - spyOn(uiActions, 'editLink').and.returnValue('ITEM EDITED'); - spyOn(formActions, 'push').and.returnValue('ITEM PUSHED'); - spyOn(formActions, 'move').and.returnValue('ITEMS REORDERED'); - spyOn(formActions, 'remove').and.returnValue('ITEM REMOVED'); - spyOn(basicActions, 'set').and.returnValue('DATA SET'); - spyOn(notificationActions, 'notify').and.returnValue('NOTIFIED'); - }); - - describe('loadLinks', () => { - it('should load sent links into navlinksData', () => { - expect(actions.loadLinks('links')).toBe('ITEMS LOADED'); - expect(formActions.load).toHaveBeenCalledWith('settings.navlinksData', { links: 'links' }); - }); - }); - - describe('addLink', () => { - it('should push a new item with default naming', () => { - const expected = { title: 'Item 2', localID: 'unique_id', type: 'link', sublinks: [] }; - actions.addLink([{ _id: 'existing link' }])(dispatch); - expect(formActions.push).toHaveBeenCalledWith('settings.navlinksData.links', expected); - expect(uiActions.editLink).toHaveBeenCalledWith('unique_id'); - }); - }); - - describe('sortLink', () => { - it('should reorder links', () => { - expect(actions.sortLink(3, 2)).toBe('ITEMS REORDERED'); - expect(formActions.move).toHaveBeenCalledWith('settings.navlinksData.links', 3, 2); - }); - }); - - describe('removeLink', () => { - it('should remove an existing item from the links', () => { - expect(actions.removeLink(3)).toBe('ITEM REMOVED'); - expect(formActions.remove).toHaveBeenCalledWith('settings.navlinksData.links', 3); - }); - }); - - describe('saveLinks', () => { - it('should dispatch a SAVING_NAVLINKS and save the data', () => { - actions.saveLinks('data')(dispatch); - expect(dispatch.calls.count()).toBe(1); - expect(dispatch).toHaveBeenCalledWith({ type: 'SAVING_NAVLINKS' }); - expect(api.save).toHaveBeenCalledWith(new RequestParams('data')); - }); - - describe('on error', () => { - it('should dispatch NAVLINKS_SAVED', async () => { - api.save.and.callFake(() => Promise.reject(new Error())); - await actions.saveLinks('data')(dispatch); - expect(dispatch).toHaveBeenCalledWith({ type: 'NAVLINKS_SAVED', data: 'data' }); - }); - }); - - describe('upon success', () => { - beforeEach(done => { - actions - .saveLinks('data')(dispatch) - .then(() => { - done(); - }); - }); - - it('should dispatch a NAVLINKS_SAVED with response', () => { - expect(dispatch).toHaveBeenCalledWith({ - type: 'NAVLINKS_SAVED', - data: { _id: 'newId', _rev: 'newRev' }, - }); - }); - - it('should set settings/collection to response', () => { - expect(basicActions.set).toHaveBeenCalledWith('settings/collection', { - _id: 'newId', - _rev: 'newRev', - }); - expect(dispatch).toHaveBeenCalledWith('DATA SET'); - }); - - it('should notify saved successfully', () => { - expect(notificationActions.notify).toHaveBeenCalledWith('Saved successfully.', 'success'); - expect(dispatch).toHaveBeenCalledWith('NOTIFIED'); - }); - }); - }); -}); diff --git a/app/react/V2/Routes/Settings/MenuConfig/MenuConfig.tsx b/app/react/V2/Routes/Settings/MenuConfig/MenuConfig.tsx index 5b93589d13..e6df7f95d9 100644 --- a/app/react/V2/Routes/Settings/MenuConfig/MenuConfig.tsx +++ b/app/react/V2/Routes/Settings/MenuConfig/MenuConfig.tsx @@ -14,7 +14,7 @@ import { ConfirmNavigationModal } from 'app/V2/Components/Forms'; import { ClientSettingsLinkSchema } from 'app/apiResponseTypes'; import { notificationAtom } from 'app/V2/atoms'; - +import { settingsAtom } from 'app/V2/atoms/settingsAtom'; import { Button, Table, Sidepanel } from 'app/V2/Components/UI'; import { SettingsContent } from 'app/V2/Components/Layouts/SettingsContent'; import uniqueID from 'shared/uniqueID'; @@ -38,6 +38,7 @@ const MenuConfig = () => { ); const [linkChanges, setLinkChanges] = useState([]); const [showModal, setShowModal] = useState(false); + const setSettings = useSetRecoilState(settingsAtom); useEffect(() => { const linksWIthid = links?.map(link => { @@ -98,7 +99,8 @@ const MenuConfig = () => { }; const save = async () => { - await SettingsAPI.saveLinks(linkChanges.map(sanitizeIds)); + const settings = await SettingsAPI.saveLinks(linkChanges.map(sanitizeIds)); + setSettings(settings); revalidator.revalidate(); setNotifications({ type: 'success', diff --git a/app/react/V2/atoms/settingsAtom.ts b/app/react/V2/atoms/settingsAtom.ts index 5b205843ef..d929583975 100644 --- a/app/react/V2/atoms/settingsAtom.ts +++ b/app/react/V2/atoms/settingsAtom.ts @@ -1,9 +1,18 @@ import { atom } from 'recoil'; import { ClientSettings } from 'app/apiResponseTypes'; +import { store } from 'app/store'; const settingsAtom = atom({ key: 'settings', default: {} as ClientSettings, + //sync deprecated redux store + effects: [ + ({ onSet }) => { + onSet(newValue => { + store?.dispatch({ type: 'settings/collection/SET', value: newValue }); + }); + }, + ], }); export { settingsAtom }; diff --git a/cypress/e2e/settings/menu.cy.ts b/cypress/e2e/settings/menu.cy.ts index 7902348832..9ca3e1759a 100644 --- a/cypress/e2e/settings/menu.cy.ts +++ b/cypress/e2e/settings/menu.cy.ts @@ -91,6 +91,16 @@ describe('Menu configuration', () => { cy.wait('@fetchLinks'); }); + it('should update the navigation bar with the changes', () => { + cy.get('.menuItems > .menuNav-list > .menuNav-item') + .should('have.length', 3) + .then($els => Cypress.$.makeArray($els).map(el => el.innerText)) + .should('deep.equal', ['Link 2', 'Group 1  ', 'Group 2  ']); + + cy.get('.menuItems > .menuNav-list > .menuNav-item').eq(2).click(); + cy.get('.dropdown-menu.expanded').contains('Link 1 edited'); + }); + it('tests delete', () => { cy.get('tbody tr:nth-of-type(1) input').click();