Skip to content

Commit

Permalink
[Issue comixed#20] Add the ConsolidateLibrary component and tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
mcpierce committed Mar 24, 2020
1 parent bc14908 commit 7f86092
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 1 deletion.
@@ -0,0 +1,17 @@
<div class='ui-g'>
<form [formGroup]='consolidationForm'>
<div class='ui-g-12'>
<p-checkbox id='delete-physical-files'
[binary]='true'
formControlName='deletePhysicalFiles'></p-checkbox>
<label for='delete-physical-files'>{{'consolidate-library.label.delete-physical-files'|translate}}</label>
</div>
<div class='ui-g-12 cx-container-centered-text'>
<button pButton
type='button'
class='cx-action-button'
[label]='"consolidate-library.button.start"|translate'
(click)='consolidateLibrary()'></button>
</div>
</form>
</div>
@@ -0,0 +1,3 @@
p-checkbox {
padding-right: 5px;
}
@@ -0,0 +1,177 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2019, 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { ConsolidateLibraryComponent } from './consolidate-library.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CheckboxModule } from 'primeng/checkbox';
import { TranslateModule } from '@ngx-translate/core';
import { LoggerModule } from '@angular-ru/logger';
import { ButtonModule } from 'primeng/button';
import { AppState, LibraryAdaptor } from 'app/library';
import { UserModule } from 'app/user/user.module';
import { Store, StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import {
LIBRARY_FEATURE_KEY,
reducer
} from 'app/library/reducers/library.reducer';
import { LibraryEffects } from 'app/library/effects/library.effects';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { Confirmation, ConfirmationService, MessageService } from 'primeng/api';
import { ComicsModule } from 'app/comics/comics.module';
import { AuthUserLoaded } from 'app/user/actions/authentication.actions';
import { AuthenticationAdaptor, USER_ADMIN } from 'app/user';
import { CONSOLIDATE_DELETE_PHYSICAL_FILES } from 'app/user/models/preferences.constants';

describe('ConsolidateLibraryComponent', () => {
let component: ConsolidateLibraryComponent;
let fixture: ComponentFixture<ConsolidateLibraryComponent>;
let confirmationService: ConfirmationService;
let libraryAdaptor: LibraryAdaptor;
let authenticationAdaptor: AuthenticationAdaptor;
let store: Store<AppState>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
UserModule,
ComicsModule,
HttpClientTestingModule,
FormsModule,
ReactiveFormsModule,
TranslateModule,
StoreModule.forRoot({}),
StoreModule.forFeature(LIBRARY_FEATURE_KEY, reducer),
EffectsModule.forRoot([]),
EffectsModule.forFeature([LibraryEffects]),
LoggerModule.forRoot(),
CheckboxModule,
ButtonModule
],
declarations: [ConsolidateLibraryComponent],
providers: [LibraryAdaptor, MessageService, ConfirmationService]
}).compileComponents();

fixture = TestBed.createComponent(ConsolidateLibraryComponent);
component = fixture.componentInstance;
confirmationService = TestBed.get(ConfirmationService);
libraryAdaptor = TestBed.get(LibraryAdaptor);
authenticationAdaptor = TestBed.get(AuthenticationAdaptor);
store = TestBed.get(Store);
fixture.detectChanges();
}));

it('should create', () => {
expect(component).toBeTruthy();
});

describe('loading user preferences', () => {
it('sets the checkbox if the user did before', () => {
store.dispatch(
new AuthUserLoaded({
user: {
...USER_ADMIN,
preferences: [
{ name: CONSOLIDATE_DELETE_PHYSICAL_FILES, value: '1' }
]
}
})
);
expect(
component.consolidationForm.controls['deletePhysicalFiles'].value
).toBeTruthy();
});

it('unsets the checkbox if the user did before', () => {
store.dispatch(
new AuthUserLoaded({
user: {
...USER_ADMIN,
preferences: [
{ name: CONSOLIDATE_DELETE_PHYSICAL_FILES, value: '0' }
]
}
})
);
expect(
component.consolidationForm.controls['deletePhysicalFiles'].value
).toBeFalsy();
});
});

describe('consolidating the library', () => {
beforeEach(() => {
spyOn(
confirmationService,
'confirm'
).and.callFake((confirm: Confirmation) => confirm.accept());
spyOn(libraryAdaptor, 'consolidate');
spyOn(authenticationAdaptor, 'setPreference');
});

describe('and deletes the physical files', () => {
beforeEach(() => {
component.consolidationForm.controls['deletePhysicalFiles'].setValue(
true
);
component.consolidateLibrary();
});

it('prompts the user', () => {
expect(confirmationService.confirm).toHaveBeenCalled();
});

it('calls the library adaptor', () => {
expect(libraryAdaptor.consolidate).toHaveBeenCalledWith(true);
});

it('saves the delete physical files flag as a preference', () => {
expect(authenticationAdaptor.setPreference).toHaveBeenCalledWith(
CONSOLIDATE_DELETE_PHYSICAL_FILES,
'1'
);
});
});

describe('and does not delete the physical file', () => {
beforeEach(() => {
component.consolidationForm.controls['deletePhysicalFiles'].setValue(
false
);
component.consolidateLibrary();
});

it('prompts the user', () => {
expect(confirmationService.confirm).toHaveBeenCalled();
});

it('calls the library adaptor', () => {
expect(libraryAdaptor.consolidate).toHaveBeenCalledWith(false);
});

it('saves the delete physical files flag as a preference', () => {
expect(authenticationAdaptor.setPreference).toHaveBeenCalledWith(
CONSOLIDATE_DELETE_PHYSICAL_FILES,
'0'
);
});
});
});
});
@@ -0,0 +1,93 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2019, 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 { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { LoggerService } from '@angular-ru/logger';
import { LibraryAdaptor } from 'app/library';
import { Subscription } from 'rxjs';
import { CONSOLIDATE_DELETE_PHYSICAL_FILES } from 'app/user/models/preferences.constants';
import { AuthenticationAdaptor } from 'app/user';
import { ConfirmationService } from 'primeng/api';
import { TranslateService } from '@ngx-translate/core';

@Component({
selector: 'app-consolidate-library',
templateUrl: './consolidate-library.component.html',
styleUrls: ['./consolidate-library.component.scss']
})
export class ConsolidateLibraryComponent implements OnInit, OnDestroy {
consolidationForm: FormGroup;
consolidatingSubscription: Subscription;
consolidating = false;
userSubscription: Subscription;
user = null;

constructor(
private logger: LoggerService,
private formBuilder: FormBuilder,
private libraryAdaptor: LibraryAdaptor,
private authenticationAdaptor: AuthenticationAdaptor,
private confirmationService: ConfirmationService,
private translateService: TranslateService
) {
this.consolidationForm = this.formBuilder.group({
deletePhysicalFiles: ['']
});
this.consolidatingSubscription = this.libraryAdaptor.consolidating$.subscribe(
consolidating => (this.consolidating = consolidating)
);
this.userSubscription = this.authenticationAdaptor.user$.subscribe(() => {
this.consolidationForm.controls['deletePhysicalFiles'].setValue(
this.authenticationAdaptor.getPreference(
CONSOLIDATE_DELETE_PHYSICAL_FILES
) === '1'
);
});
}

ngOnInit() {}

ngOnDestroy() {
this.consolidatingSubscription.unsubscribe();
}

consolidateLibrary() {
this.confirmationService.confirm({
header: this.translateService.instant(
'consolidate-library.confirm.header'
),
message: this.translateService.instant(
'consolidate-library.confirm.message',
{
deletePhysicalFiles: this.consolidationForm.controls['deletePhysicalFiles'].value
}
),
accept: () => {
const deletePhysicalFiles = this.consolidationForm.controls[
'deletePhysicalFiles'
].value;
this.authenticationAdaptor.setPreference(
CONSOLIDATE_DELETE_PHYSICAL_FILES,
deletePhysicalFiles ? '1' : '0'
);
this.libraryAdaptor.consolidate(deletePhysicalFiles);
}
});
}
}
4 changes: 3 additions & 1 deletion comixed-frontend/src/app/library/library.module.ts
Expand Up @@ -75,6 +75,7 @@ import { ConvertComicsSettingsComponent } from './components/convert-comics-sett
import * as fromPublisher from 'app/library/reducers/publisher.reducer';
import { PublisherEffects } from 'app/library/effects/publisher.effects';
import { PublisherAdaptor } from 'app/library/adaptors/publisher.adaptor';
import { ConsolidateLibraryComponent } from './components/consolidate-library/consolidate-library.component';

@NgModule({
imports: [
Expand Down Expand Up @@ -138,7 +139,8 @@ import { PublisherAdaptor } from 'app/library/adaptors/publisher.adaptor';
DuplicatePageListItemComponent,
CollectionDetailsPageComponent,
CollectionPageComponent,
ConvertComicsSettingsComponent
ConvertComicsSettingsComponent,
ConsolidateLibraryComponent
],
providers: [
LibraryService,
Expand Down
2 changes: 2 additions & 0 deletions comixed-frontend/src/app/user/models/preferences.constants.ts
Expand Up @@ -20,6 +20,8 @@ export const LIBRARY_SORT = 'library.sort-by';
export const LIBRARY_ROWS = 'library.rows';
export const LIBRARY_COVER_SIZE = 'library.cover-size';
export const LIBRARY_CURRENT_TAB = 'library.current-tab';
export const CONSOLIDATE_DELETE_PHYSICAL_FILES =
'library.consolidate.delete-physical-file';

export const IMPORT_SORT = 'import.sort-by';
export const IMPORT_ROWS = 'import.rows';
Expand Down
12 changes: 12 additions & 0 deletions comixed-frontend/src/assets/i18n/library-en.json
Expand Up @@ -400,6 +400,18 @@
}
}
},
"consolidate-library": {
"label": {
"delete-physical-files": "Delete The Physical Comic Files."
},
"button": {
"start": "Start Consolidation"
},
"confirm": {
"header": "Consolidate Library",
"message": "Are you sure you want to consolidate the library and {deletePhysicalFiles, select, true{delete} other{not delete}} the comic files?"
}
},
"breadcrumb": {
"collections": {
"root": "Collections",
Expand Down

0 comments on commit 7f86092

Please sign in to comment.