diff --git a/src/app/components/multiple-draft-generator/multiple-draft-generator.component.css b/src/app/components/multiple-draft-generator/multiple-draft-generator.component.css deleted file mode 100644 index 00a27f06..00000000 --- a/src/app/components/multiple-draft-generator/multiple-draft-generator.component.css +++ /dev/null @@ -1,17 +0,0 @@ -.toggle-drafts { - width: 100%; - display: flex; - margin-bottom: 15px; -} - -.toggle-drafts label.btn { - flex: 0 1 50%; -} - -.translation-btn { - display: flex; - justify-content: space-between; - align-items: center; - max-width: 350px; - margin: 0 auto 8px; -} diff --git a/src/app/components/multiple-draft-generator/multiple-draft-generator.component.html b/src/app/components/multiple-draft-generator/multiple-draft-generator.component.html index af2051fc..c4fc4aa5 100644 --- a/src/app/components/multiple-draft-generator/multiple-draft-generator.component.html +++ b/src/app/components/multiple-draft-generator/multiple-draft-generator.component.html @@ -1,92 +1,35 @@ diff --git a/src/app/components/multiple-draft-generator/multiple-draft-generator.component.spec.ts b/src/app/components/multiple-draft-generator/multiple-draft-generator.component.spec.ts index b0f3b4b5..b835168d 100644 --- a/src/app/components/multiple-draft-generator/multiple-draft-generator.component.spec.ts +++ b/src/app/components/multiple-draft-generator/multiple-draft-generator.component.spec.ts @@ -1,10 +1,4 @@ -import { - ComponentFixture, - TestBed, - discardPeriodicTasks, - fakeAsync, - tick, -} from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { NgbActiveModal, NgbAlert, @@ -13,26 +7,20 @@ import { import { MultipleDraftGeneratorComponent } from './multiple-draft-generator.component'; import { FormsModule } from '@angular/forms'; import { DraftService } from '../../service/draft.service'; -import { LanguageService } from '../../service/language.service'; -import { ResourceService } from '../../service/resource/resource.service'; import { Resource } from '../../models/resource'; import { Translation } from '../../models/translation'; import { By } from '@angular/platform-browser'; import { NgbButtonLabel } from '@ng-bootstrap/ng-bootstrap'; import { Language } from '../../models/language'; import { DebugElement } from '@angular/core'; -import { TranslationVersionBadgeComponent } from '../translation/translation-version-badge/translation-version-badge.component'; -import { MessageType } from '../../models/message'; describe('MultipleDraftGeneratorComponent', () => { let comp: MultipleDraftGeneratorComponent; let fixture: ComponentFixture; - let customResourceServiceStub; - let customDraftServiceStub; const buildTranslation = ( isPublished: boolean, - selectedForAction: boolean, + generateDraft: boolean, language: string, ) => { const l = new Language(); @@ -41,57 +29,15 @@ describe('MultipleDraftGeneratorComponent', () => { const t = new Translation(); t.language = l; t.is_published = isPublished; - t['is-published'] = isPublished; - t.selectedForAction = selectedForAction; + t.generateDraft = generateDraft; return t; }; beforeEach(() => { - customResourceServiceStub = { - getResource() {}, - }; - customDraftServiceStub = { - createDraft() {}, - publishDraft() {}, - }; - - spyOn(customResourceServiceStub, 'getResource').and.returnValue( - Promise.resolve({ - 'latest-drafts-translations': [ - { - language: { id: 1 }, - 'publishing-errors': null, - 'is-published': false, - }, - ], - }), - ); - spyOn(customDraftServiceStub, 'createDraft').and.returnValue( - Promise.resolve(), - ); - spyOn(customDraftServiceStub, 'publishDraft').and.returnValue( - Promise.resolve([ - { - 'publishing-errors': null, - 'is-published': false, - }, - ]), - ); - - customResourceServiceStub.getResource(); - TestBed.configureTestingModule({ - declarations: [ - MultipleDraftGeneratorComponent, - TranslationVersionBadgeComponent, - ], + declarations: [MultipleDraftGeneratorComponent], imports: [NgbModule.forRoot(), FormsModule], - providers: [ - { provide: DraftService, useValue: customDraftServiceStub }, - { provide: NgbActiveModal }, - { provide: ResourceService, useValue: customResourceServiceStub }, - { provide: LanguageService }, - ], + providers: [{ provide: DraftService }, { provide: NgbActiveModal }], }).compileComponents(); fixture = TestBed.createComponent(MultipleDraftGeneratorComponent); @@ -107,18 +53,17 @@ describe('MultipleDraftGeneratorComponent', () => { const r = new Resource(); r['latest-drafts-translations'] = translations; comp.resource = r; - comp.actionType = 'publish'; fixture.detectChanges(); }); - it('shows languages with and without drafts', () => { + it('only shows languages without drafts', () => { expect( fixture.debugElement.queryAll(By.directive(NgbButtonLabel)).length, - ).toBe(4); + ).toBe(3); }); - it('shows confirm message to publish selected languages', () => { + it('confirm message lists all languages', () => { comp.showConfirmAlert(); fixture.detectChanges(); @@ -126,78 +71,7 @@ describe('MultipleDraftGeneratorComponent', () => { By.directive(NgbAlert), ); expect(alert.nativeElement.textContent).toContain( - `Are you sure you want to publish these languages: Chinese, French?`, + `${comp.baseConfirmMessage} Chinese, French?`, ); }); - - it('shows confirm message to create a draft for selected languages', () => { - comp.actionType = 'createDrafts'; - comp.showConfirmAlert(); - fixture.detectChanges(); - - const alert: DebugElement = fixture.debugElement.query( - By.directive(NgbAlert), - ); - expect(alert.nativeElement.textContent).toContain( - `Are you sure you want to generate a draft for these languages: Chinese, French?`, - ); - }); - - describe('publishOrCreateDrafts() Publish', () => { - it('should send publish 2 languages, and call isPublished() every 5 seconds ', fakeAsync(() => { - comp.showConfirmAlert(); - fixture.detectChanges(); - spyOn(comp, 'renderMessage'); - spyOn(comp, 'isPublished'); - comp.publishOrCreateDrafts(); - expect(comp.renderMessage).toHaveBeenCalledWith( - MessageType.success, - 'Publishing translations...', - ); - - tick(5500); - fixture.detectChanges(); - discardPeriodicTasks(); - - fixture.whenStable().then(() => { - expect(customDraftServiceStub.publishDraft).toHaveBeenCalledTimes(2); - expect(comp.errorMessage).toEqual([]); - expect(comp.isPublished).toHaveBeenCalledTimes(1); - - tick(5500); - fixture.detectChanges(); - discardPeriodicTasks(); - - expect(comp.isPublished).toHaveBeenCalledTimes(2); - }); - })); - - it('should return publishing errors and warn the user.', fakeAsync(() => { - customDraftServiceStub.publishDraft.and.returnValue( - Promise.resolve([ - { - 'publishing-errors': 'Error publishing...', - 'is-published': false, - }, - ]), - ); - spyOn(comp, 'renderMessage'); - spyOn(comp, 'isPublished'); - - comp.showConfirmAlert(); - fixture.detectChanges(); - comp.publishOrCreateDrafts(); - - tick(5500); - fixture.detectChanges(); - discardPeriodicTasks(); - - fixture.whenStable().then(() => { - expect(comp.errorMessage).toEqual([ - 'Error publishing...', - 'Error publishing...', - ]); - }); - })); - }); }); diff --git a/src/app/components/multiple-draft-generator/multiple-draft-generator.component.ts b/src/app/components/multiple-draft-generator/multiple-draft-generator.component.ts index aea296aa..1947d11e 100644 --- a/src/app/components/multiple-draft-generator/multiple-draft-generator.component.ts +++ b/src/app/components/multiple-draft-generator/multiple-draft-generator.component.ts @@ -1,275 +1,59 @@ -import { Component, OnDestroy } from '@angular/core'; +import { Component } from '@angular/core'; import { Resource } from '../../models/resource'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { DraftService } from '../../service/draft.service'; -import { ResourceService } from '../../service/resource/resource.service'; -import { LanguageService } from '../../service/language.service'; import { Translation } from '../../models/translation'; -import { MessageType } from '../../models/message'; - -enum LanguageTypeEnum { - draft = 'draft', - publish = 'publish', -} - -interface PromisePayload { - success: boolean; - type: LanguageTypeEnum; - value?: Translation; - error?: string; -} -interface APICall { - type: LanguageTypeEnum; - translation: Translation; -} - -type ActionType = 'publish' | 'createDrafts'; @Component({ selector: 'admin-multiple-draft-generator', templateUrl: './multiple-draft-generator.component.html', - styleUrls: ['./multiple-draft-generator.component.css'], }) -export class MultipleDraftGeneratorComponent implements OnDestroy { +export class MultipleDraftGeneratorComponent { resource: Resource; translations: Translation[]; - actionType: ActionType = 'publish'; + confirmMessage: string; - errorMessage: string[]; - sucessfulMessages: string[]; - alertMessage: string; - sucessfulMessage: string; - checkToEnsureTranslationIsPublished: number; - disableButtons: boolean; + saving: boolean; + errorMessage: string; + + readonly baseConfirmMessage = + 'Are you sure you want to generate a draft for these languages:'; constructor( private ngbActiveModal: NgbActiveModal, private draftService: DraftService, - private resourceService: ResourceService, - private languageService: LanguageService, ) {} - ngOnDestroy(): void { - clearInterval(this.checkToEnsureTranslationIsPublished); - } - - renderMessage(type: MessageType, text: string, time?: number) { - if (type === MessageType.error) { - this.errorMessage = [text]; - return; - } else if (type === MessageType.success) { - this.sucessfulMessages = [text]; - } else { - this[`${type}Message`] = text; - if (time) { - setTimeout(() => { - this[`${type}Message`] = ''; - }, time); - } - } - } - - switchActionType(type: ActionType) { - this.actionType = type; - this.translations = []; - this.confirmMessage = ''; - this.sucessfulMessages = []; - this.alertMessage = ''; - this.disableButtons = false; - this.resource['latest-drafts-translations'].forEach((translation) => { - delete translation.selectedForAction; - }); - } - showConfirmAlert(): void { this.translations = this.resource['latest-drafts-translations'].filter( - (translation) => translation.selectedForAction, + (translation) => translation.generateDraft, ); if (this.translations.length === 0) { return; } - const selectedTranslations = this.translations + const message = this.translations .map((translation) => translation.language.name) .join(', '); - if (this.actionType === 'publish') { - this.confirmMessage = `Are you sure you want to publish these languages: ${selectedTranslations}?`; - } else { - this.confirmMessage = `Are you sure you want to generate a draft for these languages: ${selectedTranslations}?`; - } + this.confirmMessage = `${this.baseConfirmMessage} ${message}?`; } - async publishOrCreateDrafts(): Promise { - this.confirmMessage = null; - this.errorMessage = []; - const promises: APICall[] = []; - this.disableButtons = true; + generateDrafts(): void { + this.saving = true; + this.errorMessage = null; - // Define what promises we will call - this.translations.forEach((translation) => { - if (this.actionType === 'publish') { - promises.push({ - type: LanguageTypeEnum.publish, - translation, - }); - } else { - promises.push({ - type: LanguageTypeEnum.draft, - translation, - }); - } - }); - - // Call promises - if (promises.length) { - if (this.actionType === 'publish') { - this.renderMessage(MessageType.success, 'Publishing translations...'); - } else { - this.renderMessage(MessageType.alert, 'Creating drafts...'); - } - - const results: PromisePayload[] = await Promise.all( - promises.map(({ type, translation }) => { - if (type === LanguageTypeEnum.draft) { - return this.draftService - .createDraft(translation) - .then( - () => - ({ - success: true, - type, - } as PromisePayload), - ) - .catch( - (error) => - ({ - success: false, - type, - error, - } as PromisePayload), - ); - } else { - return this.draftService - .publishDraft(this.resource, translation) - .then( - (value) => - ({ - success: true, - type, - value, - } as PromisePayload), - ) - .catch( - (error) => - ({ - success: false, - type, - error, - } as PromisePayload), - ); + this.translations.forEach((translation, index) => { + this.draftService + .createDraft(translation) + .then(() => { + if (index === this.translations.length - 1) { + this.ngbActiveModal.close(); } - }), - ); - - // Determine results - const invalidResults = results.filter((result) => !result.success); - if (invalidResults.length) { - invalidResults.forEach((invalidResult) => { - this.errorMessage = [...this.errorMessage, invalidResult.error]; - }); - this.disableButtons = false; - } else { - if (this.actionType === 'publish') { - const publishingErrors = results - .filter((result) => result.value[0]['publishing-errors']) - .map((result) => result.value[0]['publishing-errors']); - if (publishingErrors.length) { - publishingErrors.forEach((publishingError) => { - this.errorMessage = [...this.errorMessage, publishingError]; - }); - } - this.checkToEnsureTranslationIsPublished = window.setInterval(() => { - this.isPublished(); - }, 5000); - } else { - this.renderMessage(MessageType.alert, ''); - this.renderMessage( - MessageType.success, - 'Drafts created. Ready for you to publish.', - ); - this.disableButtons = false; - // Update languages - this.resourceService - .getResources('latest-drafts-translations') - .then((resources) => { - const resource = resources.find((r) => r.id === this.resource.id); - this.setResourceAndLoadTranslations(resource); - }); - setTimeout(() => { - this.renderMessage(MessageType.success, ''); - }, 5000); - } - } - } - } - - isPublished() { - this.renderMessage(MessageType.success, 'Publishing translations...'); - this.resourceService - .getResource(this.resource.id, 'latest-drafts-translations') - .then((resource) => { - let numberpublished = 0; - this.translations.forEach((translation) => { - const updatedTranslation = resource[ - 'latest-drafts-translations' - ].find( - (draftTranslation) => - draftTranslation.language.id === translation.language.id, - ); - if (updatedTranslation['is-published']) { - numberpublished++; - this.sucessfulMessages = [ - ...this.sucessfulMessages, - `${translation.language.name} version ${updatedTranslation.version} has been published`, - ]; - } - if (updatedTranslation['publishing-errors']) { - clearInterval(this.checkToEnsureTranslationIsPublished); - this.errorMessage = [ - ...this.errorMessage, - updatedTranslation['publishing-errors'], - ]; - this.disableButtons = false; - } - }); - - if (numberpublished === this.translations.length) { - clearInterval(this.checkToEnsureTranslationIsPublished); - this.renderMessage( - MessageType.success, - 'All Languages are successfully published.', - ); - this.disableButtons = false; - this.setResourceAndLoadTranslations(resource); - } - }) - .catch((err) => { - console.log('ERROR', err); - clearInterval(this.checkToEnsureTranslationIsPublished); - this.errorMessage = [...this.errorMessage, err]; - this.disableButtons = false; - }); - } - - private setResourceAndLoadTranslations(resource: Resource): void { - this.resource = resource; - this.resource['latest-drafts-translations'].forEach((translation) => { - this.languageService - .getLanguage(translation.language.id, 'custom_pages,custom_tips') - .then((language) => { - translation.language = language; - translation.is_published = translation['is-published']; + }) + .catch((message) => { + this.saving = false; + this.errorMessage = message; }); }); } diff --git a/src/app/components/resource/resource.component.html b/src/app/components/resource/resource.component.html index 0674456d..f2a020de 100644 --- a/src/app/components/resource/resource.component.html +++ b/src/app/components/resource/resource.component.html @@ -32,7 +32,7 @@ class="btn btn-secondary" *ngIf="!isMetaTool()" > - Bulk Actions + Generate multiple drafts diff --git a/src/app/components/translation/translation-version-badge/translation-version-badge.component.html b/src/app/components/translation/translation-version-badge/translation-version-badge.component.html index 7cd84fa2..b315a268 100644 --- a/src/app/components/translation/translation-version-badge/translation-version-badge.component.html +++ b/src/app/components/translation/translation-version-badge/translation-version-badge.component.html @@ -1,16 +1,9 @@ {{ translation.version }} | Draft {{ translation.version }} | Live -{{ translation.version }} | Error None diff --git a/src/app/components/translation/translation.component.html b/src/app/components/translation/translation.component.html index 0d00c9be..34bcdb90 100644 --- a/src/app/components/translation/translation.component.html +++ b/src/app/components/translation/translation.component.html @@ -38,7 +38,7 @@

-
+
@@ -49,20 +49,30 @@

> Download -

-
- +
- - {{ sucessfulMessage }} + + Publishing... - - {{ alertMessage }} + + Saving... {{ errorMessage }} diff --git a/src/app/components/translation/translation.component.spec.ts b/src/app/components/translation/translation.component.spec.ts index c2377003..24c9f8f5 100644 --- a/src/app/components/translation/translation.component.spec.ts +++ b/src/app/components/translation/translation.component.spec.ts @@ -1,11 +1,4 @@ -import { - async, - ComponentFixture, - discardPeriodicTasks, - fakeAsync, - TestBed, - tick, -} from '@angular/core/testing'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { TranslationComponent } from './translation.component'; import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { DraftService } from '../../service/draft.service'; @@ -19,12 +12,10 @@ import { Page } from '../../models/page'; import { CustomPage } from '../../models/custom-page'; import { ResourceComponent } from '../resource/resource.component'; import anything = jasmine.anything; -import { ResourceService } from '../../service/resource/resource.service'; import { CustomPageService } from '../../service/custom-page.service'; import { CustomManifestService } from '../../service/custom-manifest.service'; -import { CustomTipService } from '../../service/custom-tip.service'; import { CustomManifest } from '../../models/custom-manifest'; -import { MessageType } from '../../models/message'; +import { CustomTipService } from '../../service/custom-tip.service'; import { TranslationVersionBadgeComponent } from './translation-version-badge/translation-version-badge.component'; describe('TranslationComponent', () => { @@ -35,8 +26,6 @@ describe('TranslationComponent', () => { let customTipsServiceStub; let modalServiceStub; let customManifestServiceStub; - let customDraftServiceStub; - let customResourceServiceStub; let resourceComponent: ResourceComponent; let language: Language; @@ -84,12 +73,6 @@ describe('TranslationComponent', () => { modalServiceStub = { open() {}, }; - customDraftServiceStub = { - publishDraft() {}, - }; - customResourceServiceStub = { - getResource() {}, - }; const modalRef = { componentInstance: {}, result: Promise.resolve(), @@ -104,41 +87,20 @@ describe('TranslationComponent', () => { spyOn(customManifestServiceStub, 'delete').and.returnValue( Promise.resolve(), ); - spyOn(customDraftServiceStub, 'publishDraft').and.returnValue( - Promise.resolve([ - { - 'publishing-errors': null, - }, - ]), - ); - spyOn(customResourceServiceStub, 'getResource').and.returnValue( - Promise.resolve({ - 'latest-drafts-translations': [ - { - language: { id: 1 }, - 'publishing-errors': null, - 'is-published': false, - }, - ], - }), - ); customPageServiceStub.delete(); modalServiceStub.open(); customManifestServiceStub.delete(); - customDraftServiceStub.publishDraft(); - customResourceServiceStub.getResource(); TestBed.configureTestingModule({ declarations: [TranslationComponent, TranslationVersionBadgeComponent], imports: [NgbModule.forRoot()], providers: [ - { provide: DraftService, useValue: customDraftServiceStub }, + { provide: DraftService }, { provide: CustomPageService, useValue: customPageServiceStub }, { provide: CustomTipService, useValue: customTipsServiceStub }, { provide: CustomManifestService, useValue: customManifestServiceStub }, { provide: NgbModal, useValue: modalServiceStub }, - { provide: ResourceService, useValue: customResourceServiceStub }, ], }).compileComponents(); })); @@ -149,9 +111,6 @@ describe('TranslationComponent', () => { resourceComponent = new ResourceComponent(null, null); comp.translationLoaded = resourceComponent.translationLoaded$; - comp.errorMessage = ''; - comp.alertMessage = ''; - comp.sucessfulMessage = ''; const pageWithCustomPage = buildPage(2); @@ -165,7 +124,6 @@ describe('TranslationComponent', () => { comp.language = language; const resource = new Resource(); - resource.id = 15; resource.pages = [buildPage(1), pageWithCustomPage]; resource.tips = []; resource['custom-manifests'] = [ @@ -181,11 +139,11 @@ describe('TranslationComponent', () => { fixture.detectChanges(); }); - it(`should show action button with 'Publish'`, () => { + it(`should show action button with 'New Draft'`, () => { const element: DebugElement = fixture.debugElement - .queryAll(By.css('.btn.btn-success')) + .queryAll(By.css('.btn.btn-secondary')) .pop(); - expect(element.nativeElement.textContent.trim()).toBe('Publish'); + expect(element.nativeElement.textContent.trim()).toBe('New Draft'); }); it(`should show status badge with 'None'`, () => { @@ -194,140 +152,6 @@ describe('TranslationComponent', () => { ); expect(element.nativeElement.textContent).toBe('None'); }); - - describe('publish a new translation (Server creates draft)', () => { - let translation: Translation; - - beforeEach(() => { - translation = new Translation(); - translation.none = true; - translation.language = language; - translation.resource = comp.resource; - - comp.resource['latest-drafts-translations'] = [translation]; - comp.reloadTranslation(); - fixture.detectChanges(); - }); - - it('should git resource endpoint', fakeAsync(() => { - spyOn(comp, 'renderMessage'); - spyOn(comp, 'isPublished'); - comp.publish(); - - expect(comp.renderMessage).toHaveBeenCalledWith(MessageType.error, ''); - expect(comp.renderMessage).toHaveBeenCalledWith( - MessageType.success, - 'Publishing...', - ); - - tick(5500); - fixture.detectChanges(); - - discardPeriodicTasks(); - fixture.whenStable().then(() => { - expect(comp.isPublished).toHaveBeenCalled(); - }); - })); - - it('should clear the interval on destroy', fakeAsync(() => { - spyOn(comp, 'renderMessage'); - spyOn(comp, 'isPublished'); - spyOn(global, 'clearInterval'); - comp.publish(); - tick(5500); - fixture.detectChanges(); - discardPeriodicTasks(); - - comp.ngOnDestroy(); - fixture.whenStable().then(() => { - expect(global.clearInterval).toHaveBeenCalled(); - }); - })); - }); - }); - - describe('isPublished()', () => { - let translation: Translation; - - beforeEach(() => { - translation = new Translation(); - translation.language = language; - translation.none = true; - translation.resource = comp.resource; - comp.translation = translation; - comp.resource['latest-drafts-translations'] = [translation]; - comp.reloadTranslation(); - fixture.detectChanges(); - }); - - it('should not run clearInterval as it is not published and had no errors', () => { - spyOn(global, 'clearInterval'); - comp.isPublished(); - - expect(customResourceServiceStub.getResource).toHaveBeenCalledWith( - 15, - 'latest-drafts-translations', - ); - expect(global.clearInterval).not.toHaveBeenCalled(); - }); - - it('should run clearInterval and report pubslishing error to user', () => { - customResourceServiceStub.getResource.and.returnValue( - Promise.resolve({ - 'latest-drafts-translations': [ - { - language: { id: 1 }, - 'publishing-errors': 'Error while saving', - 'is-published': false, - }, - ], - }), - ); - spyOn(global, 'clearInterval'); - spyOn(comp, 'renderMessage'); - comp.isPublished(); - - fixture.whenStable().then(() => { - expect(global.clearInterval).toHaveBeenCalled(); - expect(comp.renderMessage).toHaveBeenCalledWith( - MessageType.success, - null, - ); - expect(comp.renderMessage).toHaveBeenCalledWith( - MessageType.error, - 'Error while saving', - ); - }); - }); - - it('should run clearInterval and report success to user', () => { - customResourceServiceStub.getResource.and.returnValue( - Promise.resolve({ - 'latest-drafts-translations': [ - { - language: { id: 1 }, - 'publishing-errors': null, - 'is-published': true, - }, - ], - }), - ); - spyOn(global, 'clearInterval'); - spyOn(comp, 'renderMessage'); - comp.isPublished(); - - fixture.whenStable().then(() => { - expect(global.clearInterval).toHaveBeenCalled(); - expect(comp.renderMessage).toHaveBeenCalledWith( - MessageType.error, - null, - ); - expect(comp.renderMessage).toHaveBeenCalledWith( - MessageType.success, - comp.successfullyPublishedMessage, - ); - }); - }); }); describe('language has existing translation(s)', () => { @@ -462,15 +286,15 @@ describe('TranslationComponent', () => { }); describe('action button', () => { - it(`should say 'Publish' for published translations`, () => { + it(`should say 'New Draft' for published translations`, () => { translation.is_published = true; fixture.detectChanges(); const element: DebugElement = fixture.debugElement - .queryAll(By.css('.btn.btn-success')) + .queryAll(By.css('.btn.btn-secondary')) .pop(); - expect(element.nativeElement.textContent.trim()).toBe('Publish'); + expect(element.nativeElement.textContent.trim()).toBe('New Draft'); }); it(`should say 'Publish' for drafts`, () => { diff --git a/src/app/components/translation/translation.component.ts b/src/app/components/translation/translation.component.ts index 72b3f261..46b3cb6c 100644 --- a/src/app/components/translation/translation.component.ts +++ b/src/app/components/translation/translation.component.ts @@ -6,7 +6,6 @@ import { OnChanges, Output, EventEmitter, - OnDestroy, } from '@angular/core'; import { Translation } from '../../models/translation'; import { DraftService } from '../../service/draft.service'; @@ -30,14 +29,12 @@ import { Resource } from '../../models/resource'; import { Observable } from 'rxjs'; import { getLatestTranslation } from './utilities'; import { environment } from '../../../environments/environment'; -import { MessageType } from '../../models/message'; -import { ResourceService } from '../../service/resource/resource.service'; @Component({ selector: 'admin-translation', templateUrl: './translation.component.html', }) -export class TranslationComponent implements OnInit, OnChanges, OnDestroy { +export class TranslationComponent implements OnInit, OnChanges { @Input() language: Language; @Input() resource: Resource; @Input() translationLoaded: Observable; @@ -46,11 +43,10 @@ export class TranslationComponent implements OnInit, OnChanges, OnDestroy { translation: Translation; customManifest: CustomManifest; baseDownloadUrl = environment.base_url + 'translations/'; + + saving = false; + publishing = false; errorMessage: string; - alertMessage: string; - sucessfulMessage: string; - checkToEnsureDraftIsPublished: number; - successfullyPublishedMessage = 'Language has been successfully published.'; constructor( private customPageService: CustomPageService, @@ -58,7 +54,6 @@ export class TranslationComponent implements OnInit, OnChanges, OnDestroy { private draftService: DraftService, private customManifestService: CustomManifestService, private modalService: NgbModal, - private resourceService: ResourceService, ) {} ngOnInit(): void { @@ -81,10 +76,6 @@ export class TranslationComponent implements OnInit, OnChanges, OnDestroy { } } - ngOnDestroy() { - clearInterval(this.checkToEnsureDraftIsPublished); - } - getPages(): AbstractPage[] { const _tPages = this.translation.resource.pages.map((page) => { const customPage: CustomPage = this.translation.language[ @@ -147,65 +138,29 @@ export class TranslationComponent implements OnInit, OnChanges, OnDestroy { return tip as Tip; } - renderMessage(type: MessageType, text: string, time?: number) { - this[`${type}Message`] = text; - if (time) { - setTimeout(() => { - this[`${type}Message`] = ''; - }, time); - } - } + publishDraft(): void { + this.publishing = true; + this.errorMessage = null; + + const t = Translation.copy(this.translation); + t.is_published = true; - async publish(): Promise { - this.renderMessage(MessageType.error, ''); - this.renderMessage(MessageType.success, 'Publishing...'); this.draftService - .publishDraft(this.resource, this.translation) - .then((data) => { - const publishingError = data[0]['publishing-errors']; - if (publishingError) { - this.renderMessage(MessageType.success, publishingError); - } - this.checkToEnsureDraftIsPublished = window.setInterval(() => { - this.isPublished(); - }, 5000); - }) - .catch(this.handleError.bind(this)); + .updateDraft(t) + .then(() => this.loadAllResources()) + .catch(this.handleError.bind(this)) + .then(() => (this.publishing = false)); } - isPublished() { - try { - this.resourceService - .getResource(this.resource.id, 'latest-drafts-translations') - .then((resource) => { - const translation = resource['latest-drafts-translations'].find( - (draftTranslation) => - draftTranslation.language.id === this.translation.language.id, - ); - if (translation['publishing-errors']) { - clearInterval(this.checkToEnsureDraftIsPublished); - this.renderMessage(MessageType.success, null); - this.renderMessage( - MessageType.error, - translation['publishing-errors'], - ); - } - if (translation['is-published']) { - clearInterval(this.checkToEnsureDraftIsPublished); - this.renderMessage(MessageType.error, null); - this.renderMessage( - MessageType.success, - this.successfullyPublishedMessage, - ); - this.loadAllResources(); - } - }); - } catch (err) { - console.log('ERROR', err); - clearInterval(this.checkToEnsureDraftIsPublished); - this.renderMessage(MessageType.success, null); - this.renderMessage(MessageType.error, err.message); - } + createDraft(): void { + this.saving = true; + this.errorMessage = null; + + this.draftService + .createDraft(this.translation) + .then(() => this.loadAllResources()) + .catch(this.handleError.bind(this)) + .then(() => (this.saving = false)); } createCustomPage(page: Page): void { diff --git a/src/app/models/message.ts b/src/app/models/message.ts deleted file mode 100644 index 1726c44e..00000000 --- a/src/app/models/message.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum MessageType { - success = 'sucessful', - alert = 'alert', - error = 'error', -} diff --git a/src/app/models/translation.ts b/src/app/models/translation.ts index 736ae170..5d12769a 100644 --- a/src/app/models/translation.ts +++ b/src/app/models/translation.ts @@ -9,7 +9,7 @@ export class Translation { resource: Resource; version: number; - selectedForAction: boolean; + generateDraft: boolean; none: boolean; static copy(translation: Translation): Translation { diff --git a/src/app/service/draft.service.ts b/src/app/service/draft.service.ts index f97f4e2b..807a0a3c 100644 --- a/src/app/service/draft.service.ts +++ b/src/app/service/draft.service.ts @@ -7,12 +7,10 @@ import { Page } from '../models/page'; import { Tip } from '../models/tip'; import { environment } from '../../environments/environment'; import { AbstractService } from './abstract.service'; -import { Resource } from '../models/resource'; @Injectable() export class DraftService extends AbstractService { private readonly draftsUrl = environment.base_url + 'drafts'; - private readonly resourcesUrl = environment.base_url + 'resources'; constructor(private http: Http, private authService: AuthService) { super(); @@ -61,29 +59,19 @@ export class DraftService extends AbstractService { .catch(this.handleError); } - publishDraft( - resource: Resource, - translation: Translation, - ): Promise { + updateDraft(translation: Translation): Promise { const payload = { data: { - type: 'publish-translations', - relationships: { - languages: { - data: [ - { - id: translation.language.id, - type: 'language', - }, - ], - }, + type: 'translation', + attributes: { + is_published: translation.is_published, }, }, }; return this.http - .post( - `${this.resourcesUrl}/${resource.id}/translations/publish`, + .put( + `${this.draftsUrl}/${translation.id}`, payload, this.authService.getAuthorizationAndOptions(), ) diff --git a/src/app/service/resource/resource.service.spec.ts b/src/app/service/resource/resource.service.spec.ts index bc2d26a0..f1cb5c06 100644 --- a/src/app/service/resource/resource.service.spec.ts +++ b/src/app/service/resource/resource.service.spec.ts @@ -4,8 +4,6 @@ import { Http, RequestOptionsArgs } from '@angular/http'; import { AuthService } from '../auth/auth.service'; import { Resource } from '../../models/resource'; import { Observable } from 'rxjs/Observable'; -import { environment } from '../../../environments/environment'; - import anything = jasmine.anything; const headers: RequestOptionsArgs = {}; @@ -24,7 +22,6 @@ describe('ResourceService', () => { const service = new ResourceService(mockHttp, mockAuthService); const resource = new Resource(); - resource.id = 13; beforeEach(() => { spyOn(mockHttp, 'post').and.returnValue( @@ -41,10 +38,6 @@ describe('ResourceService', () => { spyOn(mockHttp, 'put').and.returnValue( new Observable((observer) => observer.complete()), ); - - spyOn(mockHttp, 'get').and.returnValue( - new Observable((observer) => observer.complete()), - ); }); it('creating uses authorization code', () => { @@ -58,36 +51,4 @@ describe('ResourceService', () => { expect(mockHttp.put).toHaveBeenCalledWith(anything(), anything(), headers); }); - - describe('GetResources()', () => { - it('should include "include"', () => { - service.getResources('test-data'); - expect(mockHttp.get).toHaveBeenCalledWith( - `${environment.base_url}resources?include=test-data`, - ); - }); - - it('should not include "include"', () => { - service.getResource(resource.id); - expect(mockHttp.get).toHaveBeenCalledWith( - `${environment.base_url}resources/${resource.id}`, - ); - }); - }); - - describe('GetResource()', () => { - it('should include "include"', () => { - service.getResource(resource.id, 'test-data'); - expect(mockHttp.get).toHaveBeenCalledWith( - `${environment.base_url}resources/${resource.id}?include=test-data`, - ); - }); - - it('should not include "include"', () => { - service.getResource(resource.id); - expect(mockHttp.get).toHaveBeenCalledWith( - `${environment.base_url}resources/${resource.id}`, - ); - }); - }); }); diff --git a/src/app/service/resource/resource.service.ts b/src/app/service/resource/resource.service.ts index 22efc690..9f4ec616 100644 --- a/src/app/service/resource/resource.service.ts +++ b/src/app/service/resource/resource.service.ts @@ -27,20 +27,6 @@ export class ResourceService extends AbstractService { .catch(this.handleError); } - getResource(resourceId: number, include?: string): Promise { - return this.http - .get( - include - ? `${this.resourcesUrl}/${resourceId}?include=${include}` - : `${this.resourcesUrl}/${resourceId}`, - ) - .toPromise() - .then((response) => { - return new JsonApiDataStore().sync(response.json()); - }) - .catch(this.handleError); - } - create(resource: Resource): Promise { return this.http .post(