diff --git a/projects/aca-content/assets/i18n/en.json b/projects/aca-content/assets/i18n/en.json index 7bc908ee2..27f981c36 100644 --- a/projects/aca-content/assets/i18n/en.json +++ b/projects/aca-content/assets/i18n/en.json @@ -421,7 +421,12 @@ } }, "LIBRARY_DELETED": "Library deleted", - "LEFT_LIBRARY": "You have left the library" + "LEFT_LIBRARY": "You have left the library", + "FAVORITE_NODE_ADDED": "Added {{ name }} to favorites", + "FAVORITE_NODES_ADDED": "Added {{ number }} items to favorites", + "FAVORITE_NODE_REMOVED": "Removed {{ name }} from favorites", + "FAVORITE_NODES_REMOVED": "Removed {{ number }} items from favorites", + "FAVORITE_NODE_NOT_FOUND": "{{ name }} is not favorite" } }, "CONTENT_METADATA": { diff --git a/projects/aca-content/src/lib/services/content-management.service.spec.ts b/projects/aca-content/src/lib/services/content-management.service.spec.ts index 53b65a2e3..c98ec9455 100644 --- a/projects/aca-content/src/lib/services/content-management.service.spec.ts +++ b/projects/aca-content/src/lib/services/content-management.service.spec.ts @@ -1882,4 +1882,80 @@ describe('ContentManagementService', () => { }); }); }); + + describe('addFavorite and removeFavorite', () => { + const fakeNode1: NodeEntry = { + entry: { + id: 'folder-node1-id', + name: 'mock-folder1-name', + isFolder: true, + isFile: false, + isFavorite: false + } as Node + }; + + const fakeNode2: NodeEntry = { + entry: { + id: 'folder-node2-id', + name: 'mock-folder2-name', + isFolder: true, + isFile: false, + isFavorite: false + } as Node + }; + + it('should call proper content api and display proper snackbar message if one node is provided for addFavorite', () => { + spyOn(contentApi, 'addFavorite').and.returnValue(of({ entry: { targetGuid: '', target: '' } })); + spyOn(store, 'dispatch'); + + contentManagementService.addFavorite([fakeNode1]); + + expect(contentApi.addFavorite).toHaveBeenCalledWith([fakeNode1]); + expect(store.dispatch).toHaveBeenCalledWith(new SnackbarInfoAction('APP.MESSAGES.INFO.FAVORITE_NODE_ADDED', { name: 'mock-folder1-name' })); + }); + + it('should call proper content api and display proper snackbar message if more than one node is provided for addFavorite', () => { + spyOn(contentApi, 'addFavorite').and.returnValue(of({ entry: { targetGuid: '', target: '' } })); + spyOn(store, 'dispatch'); + + contentManagementService.addFavorite([fakeNode1, fakeNode2]); + + expect(contentApi.addFavorite).toHaveBeenCalledWith([fakeNode1, fakeNode2]); + expect(store.dispatch).toHaveBeenCalledWith(new SnackbarInfoAction('APP.MESSAGES.INFO.FAVORITE_NODES_ADDED', { number: 2 })); + }); + + it('should call proper content api and display proper snackbar message if one node is provided for removeFavorite', () => { + spyOn(contentApi, 'removeFavorite').and.returnValue(of({})); + spyOn(store, 'dispatch'); + + contentManagementService.removeFavorite([fakeNode1]); + + expect(contentApi.removeFavorite).toHaveBeenCalledWith([fakeNode1]); + expect(store.dispatch).toHaveBeenCalledWith(new SnackbarInfoAction('APP.MESSAGES.INFO.FAVORITE_NODE_REMOVED', { name: 'mock-folder1-name' })); + }); + + it('should call proper content api and display proper snackbar message if more than one node is provided for removeFavorite', () => { + spyOn(contentApi, 'removeFavorite').and.returnValue(of({})); + spyOn(store, 'dispatch'); + + contentManagementService.removeFavorite([fakeNode1, fakeNode2]); + + expect(contentApi.removeFavorite).toHaveBeenCalledWith([fakeNode1, fakeNode2]); + expect(store.dispatch).toHaveBeenCalledWith(new SnackbarInfoAction('APP.MESSAGES.INFO.FAVORITE_NODES_REMOVED', { number: 2 })); + }); + + it('should display snackbar error message when removeFavorite api fails', () => { + spyOn(contentApi, 'removeFavorite').and.returnValue( + throwError(() => new Error(JSON.stringify({ error: { statusCode: 404, briefSummary: ' relationship id of folder-node2-id' } }))) + ); + spyOn(store, 'dispatch'); + + contentManagementService.removeFavorite([fakeNode1, fakeNode2]); + + expect(contentApi.removeFavorite).toHaveBeenCalledWith([fakeNode1, fakeNode2]); + expect(store.dispatch).toHaveBeenCalledWith( + new SnackbarErrorAction('APP.MESSAGES.INFO.FAVORITE_NODE_NOT_FOUND', { name: 'mock-folder2-name' }) + ); + }); + }); }); diff --git a/projects/aca-content/src/lib/services/content-management.service.ts b/projects/aca-content/src/lib/services/content-management.service.ts index 4aaf024a3..9b14912d3 100644 --- a/projects/aca-content/src/lib/services/content-management.service.ts +++ b/projects/aca-content/src/lib/services/content-management.service.ts @@ -103,6 +103,11 @@ export class ContentManagementService { return newNode; }); + if (nodes.length > 1) { + this.store.dispatch(new SnackbarInfoAction('APP.MESSAGES.INFO.FAVORITE_NODES_ADDED', { number: nodes.length })); + } else { + this.store.dispatch(new SnackbarInfoAction('APP.MESSAGES.INFO.FAVORITE_NODE_ADDED', { name: nodes[0].entry.name })); + } this.store.dispatch(new SetSelectedNodesAction(favoriteNodes)); }); } @@ -110,14 +115,28 @@ export class ContentManagementService { removeFavorite(nodes: Array) { if (nodes && nodes.length > 0) { - this.contentApi.removeFavorite(nodes).subscribe(() => { - const favoriteNodes = nodes.map((node) => { - const newNode = JSON.parse(JSON.stringify(node)); - newNode.entry.isFavorite = false; - return newNode; - }); + this.contentApi.removeFavorite(nodes).subscribe({ + next: () => { + const favoriteNodes = nodes.map((node) => { + const newNode = JSON.parse(JSON.stringify(node)); + newNode.entry.isFavorite = false; + return newNode; + }); - this.store.dispatch(new SetSelectedNodesAction(favoriteNodes)); + if (nodes.length > 1) { + this.store.dispatch(new SnackbarInfoAction('APP.MESSAGES.INFO.FAVORITE_NODES_REMOVED', { number: nodes.length })); + } else { + this.store.dispatch(new SnackbarInfoAction('APP.MESSAGES.INFO.FAVORITE_NODE_REMOVED', { name: nodes[0].entry.name })); + } + this.store.dispatch(new SetSelectedNodesAction(favoriteNodes)); + }, + error: (error) => { + if (JSON.parse(error.message).error.statusCode === 404) { + const nodeId = JSON.parse(error.message).error.briefSummary.split('relationship id of ')[1]; + const nodeName = nodes.find((node) => node.entry.id === nodeId)?.entry.name; + this.store.dispatch(new SnackbarErrorAction('APP.MESSAGES.INFO.FAVORITE_NODE_NOT_FOUND', { name: nodeName })); + } + } }); } }