Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task: support multiple collections #2549

Merged
merged 43 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
014816a
add popups context
thewahome Apr 3, 2023
b7666db
utilise context in hook
thewahome Apr 3, 2023
4958e07
define generic popups wrappers
thewahome Apr 3, 2023
a742272
register sample popup
thewahome Apr 3, 2023
1e9621a
utilise provider in app.tsx
thewahome Apr 4, 2023
508d019
add new dialogcomponent for dialog uis
thewahome Apr 5, 2023
6f6d05f
separate share query component from button
thewahome Apr 5, 2023
4f97454
separate theme chooser dialog
thewahome Apr 5, 2023
58a7a28
move preview collections to popup manager
thewahome Apr 11, 2023
074cc4a
change component name to preview collection for clarity
thewahome Apr 11, 2023
490dadd
change path name to collection
thewahome Apr 11, 2023
e1d96df
define width of items in popup
thewahome Apr 11, 2023
c56d0cd
use popups to open permissions
thewahome Apr 11, 2023
080c49c
remove permissions panel code
thewahome Apr 11, 2023
525ae26
break down permissions for better sharing
thewahome Apr 17, 2023
c39358c
rename files to clear intent
thewahome Apr 17, 2023
5f3a8b5
Merge branch 'dev' into chore/popups-manager
thewahome Apr 17, 2023
3706869
remove sonar cloud code smells
thewahome Apr 17, 2023
88eab5b
Merge branch 'dev' into chore/popups-manager
thewahome Apr 24, 2023
2f4b437
Merge branch 'dev' into chore/popups-manager
thewahome Apr 26, 2023
c158800
Merge branch 'dev' into chore/popups-manager
thewahome Apr 26, 2023
2f34fd8
move reducedPopups to their own file
thewahome Apr 26, 2023
a4c0e6e
change size of full permissions
thewahome Apr 26, 2023
3deb1c6
fix popup interfaces imports
thewahome Apr 26, 2023
dcd9538
add new size support
thewahome Apr 26, 2023
533e340
add render footer function to show custom footers
ElinorW Apr 27, 2023
ed3c780
add default collection
thewahome Apr 27, 2023
4cbf217
use show instead of open, reuse interfaces
thewahome May 2, 2023
6a2a0cc
add error boundary
thewahome May 2, 2023
a1b60f5
prevent reload when consent is given
thewahome May 2, 2023
0bdfad0
inject content to default collection
thewahome May 2, 2023
0eb07ed
save paths to default collection
thewahome May 2, 2023
fe81bec
Merge branch 'chore/popups-manager' into feature/multiple-collections
thewahome May 2, 2023
0ca8da9
Merge branch 'dev' into feature/multiple-collections
thewahome May 2, 2023
a5c838c
remove paths from resources
thewahome May 2, 2023
79fc709
move tests to the correct file
thewahome May 2, 2023
0795851
remove paths references
thewahome May 2, 2023
aed75a4
fix failing collections test
thewahome May 2, 2023
0f3c6c4
rename collections reducer test description
thewahome May 2, 2023
b3a1dde
correct collections reducer initialisation
thewahome May 2, 2023
0fb0f73
check for default collection using default flag
thewahome May 2, 2023
6ea9830
use default flag check instead of 0 index
thewahome May 2, 2023
bd91b04
reduce cognitive load
thewahome May 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 24 additions & 29 deletions src/app/middleware/localStorageMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { collectionsCache } from '../../modules/cache/collections.cache';
import { resourcesCache } from '../../modules/cache/resources.cache';
import { samplesCache } from '../../modules/cache/samples.cache';
import { saveTheme } from '../../themes/theme-utils';
import { AppAction } from '../../types/action';
import { IResourceLink } from '../../types/resources';
import { addResourcePaths } from '../services/actions/resource-explorer-action-creators';
import { addResourcePaths } from '../services/actions/collections-action-creators';
import {
CHANGE_THEME_SUCCESS, FETCH_RESOURCES_ERROR, FETCH_RESOURCES_SUCCESS,
CHANGE_THEME_SUCCESS, COLLECTION_CREATE_SUCCESS, FETCH_RESOURCES_ERROR, FETCH_RESOURCES_SUCCESS,
RESOURCEPATHS_ADD_SUCCESS, RESOURCEPATHS_DELETE_SUCCESS, SAMPLES_FETCH_SUCCESS
} from '../services/redux-constants';

Expand All @@ -20,16 +21,32 @@ const localStorageMiddleware = (store: any) => (next: any) => async (action: App
break;

case RESOURCEPATHS_ADD_SUCCESS: {
const navigationEntry = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;
if(navigationEntry && navigationEntry.loadEventEnd > 0) {
await saveResourcesCollection(action.response);
}
const collections = await collectionsCache.read();
const item = collections.find(k => k.isDefault)!;
item.paths = action.response;
await collectionsCache.update(item.id, item);
break;
}

case RESOURCEPATHS_DELETE_SUCCESS: {
updateResourcesCollection(action.response)
const paths = action.response;
const collections = await collectionsCache.read();
const collection = collections.find(k => k.isDefault)!;
paths.forEach((path: IResourceLink) => {
const index = collection.paths.findIndex(k => k.key === path.key);
if (index > -1) {
collection.paths.splice(index, 1);
}
})
await collectionsCache.update(collection.id, collection);
break;
}

case COLLECTION_CREATE_SUCCESS: {
await collectionsCache.create(action.response);
break;
}

case FETCH_RESOURCES_SUCCESS:
case FETCH_RESOURCES_ERROR: {
resourcesCache.readCollection().then((data: IResourceLink[]) => {
Expand All @@ -46,26 +63,4 @@ const localStorageMiddleware = (store: any) => (next: any) => async (action: App
return next(action);
};

async function saveResourcesCollection(collection: IResourceLink[]){
const cachedCollection = await resourcesCache.readCollection();
let newCollection: IResourceLink[] = collection;
if(cachedCollection && cachedCollection.length > 0 ){
newCollection = [...cachedCollection, ...collection]
}
await resourcesCache.saveCollection(newCollection);
}

async function updateResourcesCollection(collection: IResourceLink[]){
const cachedCollection = await resourcesCache.readCollection();
if(cachedCollection && cachedCollection.length > 0){
collection.forEach((path: IResourceLink) => {
const index = cachedCollection.findIndex(k => k.key === path.key);
if(index > -1){
cachedCollection.splice(index, 1);
}
})
await resourcesCache.saveCollection(cachedCollection);
}
}

export default localStorageMiddleware;
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ const mockState: ApplicationState = {
labels: [],
children: []
},
error: null,
paths: []
error: null
},
policies: {
pending: false,
Expand Down
87 changes: 87 additions & 0 deletions src/app/services/actions/collections-action-creators.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

import {
RESOURCEPATHS_ADD_SUCCESS, RESOURCEPATHS_DELETE_SUCCESS
} from '../redux-constants';
import { addResourcePaths, removeResourcePaths } from './collections-action-creators';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

const paths = [
{
key: '5-{serviceHealth-id}-issues',
url: '/admin/serviceAnnouncement/healthOverviews/{serviceHealth-id}/issues',
name: 'issues (1)',
labels: [
{ name: 'v1.0', methods: ['Get', 'Post'] },
{ name: 'beta', methods: ['Get', 'Post'] }
],
isExpanded: true,
parent: '{serviceHealth-id}',
level: 5,
paths: ['/', 'admin', 'serviceAnnouncement', 'healthOverviews', '{serviceHealth-id}'],
type: 'path',
links: []
}, {
key: '6-issues-{serviceHealthIssue-id}',
url: '/admin/serviceAnnouncement/healthOverviews/{serviceHealth-id}/issues/{serviceHealthIssue-id}',
name: '{serviceHealthIssue-id} (1)',
labels: [
{ name: 'v1.0', methods: ['Get', 'Patch', 'Delete'] },
{ name: 'beta', methods: ['Get', 'Patch', 'Delete'] }
],
isExpanded: true,
parent: 'issues',
level: 6,
paths: ['/', 'admin', 'serviceAnnouncement', 'healthOverviews', '{serviceHealth-id}', 'issues'],
type: 'path',
links: []
}
];

describe('Collections actions', () => {
beforeEach(() => {
fetchMock.resetMocks();
});

it('should dispatch RESOURCEPATHS_ADD_SUCCESS when addResourcePaths() is called with valid paths', () => {

const expectedActions = [
{
type: RESOURCEPATHS_ADD_SUCCESS,
response: paths
}
];

const store_ = mockStore({
resources: {
paths: []
}
});

store_.dispatch(addResourcePaths(paths));
expect(store_.getActions()).toEqual(expectedActions);
});

it('should dispatch RESOURCEPATHS_DELETE_SUCCESS when removeResourcePaths() is dispatched', () => {

const expectedActions = [
{
type: RESOURCEPATHS_DELETE_SUCCESS,
response: paths
}
];

const store_ = mockStore({
resources: {
paths
}
});

store_.dispatch(removeResourcePaths(paths));
expect(store_.getActions()).toEqual(expectedActions);
})

});
26 changes: 26 additions & 0 deletions src/app/services/actions/collections-action-creators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { AppAction } from '../../../types/action';
import {
COLLECTION_CREATE_SUCCESS,
RESOURCEPATHS_ADD_SUCCESS, RESOURCEPATHS_DELETE_SUCCESS
} from '../redux-constants';

export function addResourcePaths(response: object): AppAction {
return {
type: RESOURCEPATHS_ADD_SUCCESS,
response
};
}

export function createCollection(response: object): AppAction {
return {
type: COLLECTION_CREATE_SUCCESS,
response
};
}

export function removeResourcePaths(response: object): AppAction {
return {
type: RESOURCEPATHS_DELETE_SUCCESS,
response
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,7 @@ const mockState: ApplicationState = {
labels: [],
children: []
},
error: null,
paths: []
error: null
},
policies: {
pending: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import {
addResourcePaths, fetchResources, fetchResourcesError,
fetchResourcesPending, fetchResourcesSuccess, removeResourcePaths
fetchResources, fetchResourcesError,
fetchResourcesPending, fetchResourcesSuccess
} from '../../../app/services/actions/resource-explorer-action-creators';
import {
FETCH_RESOURCES_ERROR,
FETCH_RESOURCES_PENDING, FETCH_RESOURCES_SUCCESS, RESOURCEPATHS_ADD_SUCCESS, RESOURCEPATHS_DELETE_SUCCESS
FETCH_RESOURCES_PENDING, FETCH_RESOURCES_SUCCESS
} from '../../../app/services/redux-constants';
import { AppAction } from '../../../types/action';
import { Mode } from '../../../types/enums';
Expand Down Expand Up @@ -98,8 +98,7 @@ const mockState: ApplicationState = {
labels: [],
children: []
},
error: null,
paths: []
error: null
},
policies: {
pending: false,
Expand Down Expand Up @@ -157,44 +156,6 @@ describe('Resource Explorer actions', () => {
expect(action).toEqual(expectedAction);
});

it('should dispatch RESOURCEPATHS_ADD_SUCCESS when addResourcePaths() is called with valid paths', () => {

const expectedActions = [
{
type: RESOURCEPATHS_ADD_SUCCESS,
response: paths
}
];

const store_ = mockStore({
resources: {
paths: []
}
});

store_.dispatch(addResourcePaths(paths));
expect(store_.getActions()).toEqual(expectedActions);
});

it('should dispatch RESOURCEPATHS_DELETE_SUCCESS when removeResourcePaths() is dispatched', () => {

const expectedActions = [
{
type: RESOURCEPATHS_DELETE_SUCCESS,
response: paths
}
];

const store_ = mockStore({
resources: {
paths
}
});

store_.dispatch(removeResourcePaths(paths));
expect(store_.getActions()).toEqual(expectedActions);
})

it('should dispatch FETCH_RESOURCES_ERROR when fetchResourcesError() is called', () => {
// Arrange
const response = {};
Expand Down
27 changes: 7 additions & 20 deletions src/app/services/actions/resource-explorer-action-creators.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { resourcesCache } from '../../../modules/cache/resources.cache';
import { AppAction } from '../../../types/action';
import {
FETCH_RESOURCES_SUCCESS, FETCH_RESOURCES_PENDING,
FETCH_RESOURCES_ERROR, RESOURCEPATHS_ADD_SUCCESS, RESOURCEPATHS_DELETE_SUCCESS
} from '../redux-constants';
import { IRequestOptions } from '../../../types/request';
import { IResource } from '../../../types/resources';
import { ApplicationState } from '../../../types/root';
import { IRequestOptions } from '../../../types/request';
import { resourcesCache } from '../../../modules/cache/resources.cache';
import {
FETCH_RESOURCES_ERROR,
FETCH_RESOURCES_PENDING,
FETCH_RESOURCES_SUCCESS
} from '../redux-constants';

export function fetchResourcesSuccess(response: object): AppAction {
return {
Expand All @@ -29,20 +30,6 @@ export function fetchResourcesError(response: object): AppAction {
};
}

export function addResourcePaths(response: object): AppAction {
return {
type: RESOURCEPATHS_ADD_SUCCESS,
response
};
}

export function removeResourcePaths(response: object): AppAction {
return {
type: RESOURCEPATHS_DELETE_SUCCESS,
response
};
}

export function fetchResources() {
return async (dispatch: Function, getState: Function) => {
const { devxApi }: ApplicationState = getState();
Expand Down
Loading