Skip to content

Commit

Permalink
[Issue #260] Modify the frontend to include reading lists in the libr…
Browse files Browse the repository at this point in the history
…ary updates.
  • Loading branch information
mcpierce committed Jun 21, 2020
1 parent cb7a1ab commit 0949fb3
Show file tree
Hide file tree
Showing 15 changed files with 257 additions and 93 deletions.
Expand Up @@ -138,7 +138,8 @@ describe('ImportPageComponent', () => {
mostRecentUpdate: null,
moreUpdates: false,
lastReadDates: [],
processingCount: 0
processingCount: 0,
readingLists: []
})
);
fixture.detectChanges();
Expand Down Expand Up @@ -166,7 +167,8 @@ describe('ImportPageComponent', () => {
mostRecentUpdate: null,
moreUpdates: false,
lastReadDates: [],
processingCount: 17
processingCount: 17,
readingLists: []
})
);
fixture.detectChanges();
Expand Down
33 changes: 33 additions & 0 deletions comixed-frontend/src/app/comics/models/reading-list.fixtures.ts
@@ -0,0 +1,33 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2020, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

import { ReadingList } from 'app/comics/models/reading-list';

export const READING_LIST_1: ReadingList = {
id: 1,
name: 'First Reading List',
summary: 'My First Reading List',
lastUpdated: new Date()
};

export const READING_LIST_2: ReadingList = {
id: 2,
name: 'Second Reading List',
summary: 'My Second Reading List',
lastUpdated: new Date()
};
5 changes: 4 additions & 1 deletion comixed-frontend/src/app/comics/models/reading-list.ts
Expand Up @@ -16,9 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

import { Comic } from 'app/comics';

export interface ReadingList {
id: number;
name: string;
summary: string;
createdDate: Date;
lastUpdated: Date;
comics?: Comic[];
}
2 changes: 2 additions & 0 deletions comixed-frontend/src/app/library/actions/library.actions.ts
Expand Up @@ -19,6 +19,7 @@
import { Action } from '@ngrx/store';
import { Comic } from '../../comics/models/comic';
import { LastReadDate } from 'app/library/models/last-read-date';
import { ReadingList } from 'app/comics/models/reading-list';

export enum LibraryActionTypes {
Reset = '[LIBRARY] Reset the library',
Expand Down Expand Up @@ -70,6 +71,7 @@ export class LibraryUpdatesReceived implements Action {
moreUpdates: boolean;
lastReadDates: LastReadDate[];
processingCount: number;
readingLists: ReadingList[];
}
) {}
}
Expand Down
23 changes: 19 additions & 4 deletions comixed-frontend/src/app/library/adaptors/library.adaptor.spec.ts
Expand Up @@ -55,6 +55,10 @@ import {
} from '../actions/library.actions';
import { LibraryAdaptor } from './library.adaptor';
import { CollectionType } from 'app/library/models/collection-type.enum';
import {
READING_LIST_1,
READING_LIST_2
} from 'app/comics/models/reading-list.fixtures';

describe('LibraryAdaptor', () => {
const ASCENDING = false;
Expand All @@ -68,6 +72,7 @@ describe('LibraryAdaptor', () => {
const IDS = [7, 17, 65, 1, 29, 71];
const ARCHIVE_TYPE = 'CBZ';
const RENAME_PAGES = true;
const READING_LISTS = [READING_LIST_1, READING_LIST_2];

let adaptor: LibraryAdaptor;
let store: Store<AppState>;
Expand Down Expand Up @@ -106,7 +111,8 @@ describe('LibraryAdaptor', () => {
moreUpdates: MORE_UPDATES,
processingCount: PROCESSING_COUNT,
comics: [],
lastReadDates: []
lastReadDates: [],
readingLists: []
})
);
adaptor.getLibraryUpdates();
Expand Down Expand Up @@ -146,7 +152,8 @@ describe('LibraryAdaptor', () => {
mostRecentUpdate: MOST_RECENT_UPDATE,
moreUpdates: MORE_UPDATES,
lastReadDates: LAST_READ_DATES,
processingCount: PROCESSING_COUNT
processingCount: PROCESSING_COUNT,
readingLists: READING_LISTS
})
);
});
Expand Down Expand Up @@ -202,6 +209,12 @@ describe('LibraryAdaptor', () => {
it('provides updates on story arcs', () => {
adaptor.stories$.subscribe(result => expect(result).toEqual(STORIES));
});

it('provides updates on the reading lists', () => {
adaptor.readingLists$.subscribe(result =>
expect(result).not.toEqual([])
);
});
});

describe('when one of the updates is the current comic', () => {
Expand All @@ -219,7 +232,8 @@ describe('LibraryAdaptor', () => {
moreUpdates: MORE_UPDATES,
mostRecentUpdate: MOST_RECENT_UPDATE,
lastReadDates: LAST_READ_DATES,
processingCount: 7
processingCount: 7,
readingLists: READING_LISTS
})
);
});
Expand Down Expand Up @@ -322,7 +336,8 @@ describe('LibraryAdaptor', () => {
moreUpdates: MORE_UPDATES,
processingCount: PROCESSING_COUNT,
comics: COMICS,
lastReadDates: []
lastReadDates: [],
readingLists: []
})
);
store.dispatch(
Expand Down
9 changes: 9 additions & 0 deletions comixed-frontend/src/app/library/adaptors/library.adaptor.ts
Expand Up @@ -42,6 +42,7 @@ import { ComicGetIssue } from 'app/comics/actions/comic.actions';
import { ComicCollectionEntry } from 'app/library/models/comic-collection-entry';
import { LoggerService } from '@angular-ru/logger';
import { CollectionType } from 'app/library/models/collection-type.enum';
import { ReadingList } from 'app/comics/models/reading-list';

@Injectable()
export class LibraryAdaptor {
Expand All @@ -57,6 +58,7 @@ export class LibraryAdaptor {
private _teams$ = new BehaviorSubject<ComicCollectionEntry[]>([]);
private _locations$ = new BehaviorSubject<ComicCollectionEntry[]>([]);
private _stories$ = new BehaviorSubject<ComicCollectionEntry[]>([]);
private _readingLists$ = new BehaviorSubject<ReadingList[]>([]);
private _processingCount$ = new BehaviorSubject<number>(0);
private comicId = -1;
private _timeout = 60;
Expand Down Expand Up @@ -120,6 +122,9 @@ export class LibraryAdaptor {
extractField(state.comics, CollectionType.STORIES)
);
}
if (!_.isEqual(this._readingLists$.getValue(), state.readingLists)) {
this._readingLists$.next(state.readingLists);
}
if (
!!state.lastComicId &&
this._lastComicId$.getValue() !== state.lastComicId
Expand Down Expand Up @@ -192,6 +197,10 @@ export class LibraryAdaptor {
return this._stories$.asObservable();
}

get readingLists$(): Observable<ReadingList[]> {
return this._readingLists$.asObservable();
}

get processingCount$(): Observable<number> {
return this._processingCount$.asObservable();
}
Expand Down
30 changes: 16 additions & 14 deletions comixed-frontend/src/app/library/effects/library.effects.spec.ts
Expand Up @@ -100,13 +100,14 @@ describe('LibraryEffects', () => {

describe('when getting library updates', () => {
it('fires an action on success', () => {
const service_response = {
const serviceResponse = {
comics: COMICS,
lastComicId: LAST_COMIC_ID,
mostRecentUpdate: MOST_RECENT_UPDATE,
moreUpdates: false,
lastReadDates: LAST_READ_DATES,
processingCount: 0
processingCount: 0,
readingLists: []
} as GetLibraryUpdateResponse;
const action = new LibraryGetUpdates({
lastUpdateDate: new Date(),
Expand All @@ -121,18 +122,19 @@ describe('LibraryEffects', () => {
mostRecentUpdate: MOST_RECENT_UPDATE,
lastReadDates: LAST_READ_DATES,
processingCount: 0,
moreUpdates: false
moreUpdates: false,
readingLists: []
});

actions$ = hot('-a', { a: action });
libraryService.getUpdatesSince.and.returnValue(of(service_response));
libraryService.getUpdatesSince.and.returnValue(of(serviceResponse));

const expected = hot('-b', { b: outcome });
expect(effects.getUpdates$).toBeObservable(expected);
});

it('fires an action on service failure', () => {
const service_response = new HttpErrorResponse({});
const serviceResponse = new HttpErrorResponse({});
const action = new LibraryGetUpdates({
lastUpdateDate: new Date(),
timeout: 60,
Expand All @@ -144,7 +146,7 @@ describe('LibraryEffects', () => {

actions$ = hot('-a', { a: action });
libraryService.getUpdatesSince.and.returnValue(
throwError(service_response)
throwError(serviceResponse)
);

const expected = hot('-b', { b: outcome });
Expand Down Expand Up @@ -177,12 +179,12 @@ describe('LibraryEffects', () => {

describe('when starting a rescan', () => {
it('fires an action on success', () => {
const service_response = { count: COUNT } as StartRescanResponse;
const serviceResponse = { count: COUNT } as StartRescanResponse;
const action = new LibraryStartRescan();
const outcome = new LibraryRescanStarted({ count: COUNT });

actions$ = hot('-a', { a: action });
libraryService.startRescan.and.returnValue(of(service_response));
libraryService.startRescan.and.returnValue(of(serviceResponse));

const expected = hot('-b', { b: outcome });
expect(effects.startRescan$).toBeObservable(expected);
Expand All @@ -192,12 +194,12 @@ describe('LibraryEffects', () => {
});

it('fires an action on service failure', () => {
const service_response = new HttpErrorResponse({});
const serviceResponse = new HttpErrorResponse({});
const action = new LibraryStartRescan();
const outcome = new LibraryStartRescanFailed();

actions$ = hot('-a', { a: action });
libraryService.startRescan.and.returnValue(throwError(service_response));
libraryService.startRescan.and.returnValue(throwError(serviceResponse));

const expected = cold('-b', { b: outcome });
expect(effects.startRescan$).toBeObservable(expected);
Expand All @@ -223,7 +225,7 @@ describe('LibraryEffects', () => {

describe('when deleting multiple comics', () => {
it('fires an action on success', () => {
const service_response = { count: COUNT } as DeleteMultipleComicsResponse;
const serviceResponse = { count: COUNT } as DeleteMultipleComicsResponse;
const action = new LibraryDeleteMultipleComics({
ids: [7, 17, 65]
});
Expand All @@ -232,7 +234,7 @@ describe('LibraryEffects', () => {
});

actions$ = hot('-a', { a: action });
libraryService.deleteMultipleComics.and.returnValue(of(service_response));
libraryService.deleteMultipleComics.and.returnValue(of(serviceResponse));

const expected = hot('-b', { b: outcome });
expect(effects.deleteMultipleComics$).toBeObservable(expected);
Expand All @@ -242,15 +244,15 @@ describe('LibraryEffects', () => {
});

it('fires an action on service failure', () => {
const service_response = new HttpErrorResponse({});
const serviceResponse = new HttpErrorResponse({});
const action = new LibraryDeleteMultipleComics({
ids: [7, 17, 65]
});
const outcome = new LibraryDeleteMultipleComicsFailed();

actions$ = hot('-a', { a: action });
libraryService.deleteMultipleComics.and.returnValue(
throwError(service_response)
throwError(serviceResponse)
);

const expected = hot('-b', { b: outcome });
Expand Down
3 changes: 2 additions & 1 deletion comixed-frontend/src/app/library/effects/library.effects.ts
Expand Up @@ -89,7 +89,8 @@ export class LibraryEffects {
: null,
moreUpdates: response.moreUpdates,
lastReadDates: response.lastReadDates,
processingCount: response.processingCount
processingCount: response.processingCount,
readingLists: response.readingLists
})
),
catchError(error => {
Expand Down
Expand Up @@ -18,6 +18,7 @@

import { Comic } from 'app/comics/models/comic';
import { LastReadDate } from 'app/library/models/last-read-date';
import { ReadingList } from 'app/comics/models/reading-list';

export interface GetLibraryUpdateResponse {
comics: Comic[];
Expand All @@ -26,4 +27,5 @@ export interface GetLibraryUpdateResponse {
moreUpdates: boolean;
lastReadDates: LastReadDate[];
processingCount: number;
readingLists: ReadingList[];
}
Expand Up @@ -152,7 +152,8 @@ describe('DuplicateComicsPageComponent', () => {
lastReadDates: [],
moreUpdates: false,
mostRecentUpdate: new Date(),
processingCount: 0
processingCount: 0,
readingLists: []
})
);
});
Expand Down

0 comments on commit 0949fb3

Please sign in to comment.