Skip to content

Commit

Permalink
Task: support multiple collections (#2549)
Browse files Browse the repository at this point in the history
  • Loading branch information
thewahome authored May 3, 2023
1 parent cfb91a2 commit 4e6b7bb
Show file tree
Hide file tree
Showing 20 changed files with 446 additions and 199 deletions.
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
};
}
3 changes: 1 addition & 2 deletions src/app/services/actions/permissions-action-creator.spec.ts
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
47 changes: 4 additions & 43 deletions src/app/services/actions/resource-explorer-action-creators.spec.ts
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

0 comments on commit 4e6b7bb

Please sign in to comment.