From efa579ce0ff764130e529e23c8d938182b180734 Mon Sep 17 00:00:00 2001 From: josephmyers <43733878+josephmyers@users.noreply.github.com> Date: Tue, 28 Jan 2025 14:40:57 +0700 Subject: [PATCH] SF-3126 Combine Add Draft dialogs (#2954) --- .../project-select.component.ts | 1 + .../draft-apply-dialog.component.html | 30 +++---- .../draft-apply-dialog.component.ts | 37 +++++--- .../draft-preview-books.component.html | 4 +- .../draft-preview-books.component.spec.ts | 84 ++++++++++--------- .../draft-preview-books.component.ts | 39 +++------ .../src/assets/i18n/non_checking_en.json | 8 -- 7 files changed, 101 insertions(+), 102 deletions(-) diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.ts index 4556a102e7..6c3d05c817 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.ts +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.ts @@ -94,6 +94,7 @@ export class ProjectSelectComponent extends SubscriptionDisposable implements Co } @Input() set value(id: string) { + if (this.paratextIdControl?.value.paratextId === id) return; const project = this.projects?.find(p => p.paratextId === id) || this.resources?.find(r => r.paratextId === id) || diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-apply-dialog/draft-apply-dialog.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-apply-dialog/draft-apply-dialog.component.html index e018dfdcf9..d344e1b1de 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-apply-dialog/draft-apply-dialog.component.html +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-apply-dialog/draft-apply-dialog.component.html @@ -6,35 +6,35 @@

{{ t("select_alternate_project") }}

- + @if (!isLoading) { + + } @if (!isAppOnline) { {{ t("connect_to_the_internet") }} } - @if (targetProject$ | async; as project) { + @if (isValid) {
@if (targetChapters$ | async; as chapters) { {{ i18n.getPluralRule(chapters) !== "one" - ? t("project_has_text_in_chapters", { bookName, numChapters: chapters, projectName: project.name }) - : t("project_has_text_in_one_chapter", { bookName, projectName: project.name }) + ? t("project_has_text_in_chapters", { bookName, numChapters: chapters, projectName }) + : t("project_has_text_in_one_chapter", { bookName, projectName }) }} } @else { - {{ - t("book_is_empty", { bookName, projectName: project.name }) - }} + {{ t("book_is_empty", { bookName, projectName }) }} }
{{ - t("i_understand_overwrite_book", { projectName: project.name, bookName }) + t("i_understand_overwrite_book", { projectName, bookName }) }} {{ t("confirm_overwrite") diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-apply-dialog/draft-apply-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-apply-dialog/draft-apply-dialog.component.ts index 1f7492d2f3..93f1985fa4 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-apply-dialog/draft-apply-dialog.component.ts +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-apply-dialog/draft-apply-dialog.component.ts @@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common'; import { Component, Inject, OnInit, ViewChild } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { TranslocoModule, translate } from '@ngneat/transloco'; +import { translate, TranslocoModule } from '@ngneat/transloco'; import { SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project'; import { Chapter, TextInfo } from 'realtime-server/lib/esm/scriptureforge/models/text-info'; import { TextInfoPermission } from 'realtime-server/lib/esm/scriptureforge/models/text-info-permission'; @@ -29,6 +29,7 @@ export interface DraftApplyDialogResult { } export interface DraftApplyDialogConfig { + initialParatextId?: string; bookNum: number; chapters: number[]; } @@ -41,12 +42,12 @@ export interface DraftApplyDialogConfig { styleUrl: './draft-apply-dialog.component.scss' }) export class DraftApplyDialogComponent implements OnInit { - @ViewChild(ProjectSelectComponent) projectSelect!: ProjectSelectComponent; + @ViewChild(ProjectSelectComponent) projectSelect?: ProjectSelectComponent; _projects?: SFProjectProfile[]; - isLoading: boolean = false; + protected isLoading: boolean = true; addToProjectForm = new FormGroup({ - targetParatextId: new FormControl('', Validators.required), + targetParatextId: new FormControl(this.data.initialParatextId, Validators.required), overwrite: new FormControl(false, Validators.requiredTrue) }); /** An observable that emits the number of chapters in the target project that have some text. */ @@ -69,6 +70,7 @@ export class DraftApplyDialogComponent implements OnInit { // the project id to add the draft to private targetProjectId?: string; private paratextIdToProjectId: Map = new Map(); + isValid: boolean = false; constructor( @Inject(MAT_DIALOG_DATA) private data: DraftApplyDialogConfig, @@ -106,6 +108,10 @@ export class DraftApplyDialogComponent implements OnInit { return this.addToProjectForm.controls.targetParatextId.valid; } + get projectName(): string { + return this.targetProject$.value?.name ?? ''; + } + get isAppOnline(): boolean { return this.onlineStatusService.isOnline; } @@ -128,12 +134,15 @@ export class DraftApplyDialogComponent implements OnInit { return projects.sort(compareProjectsForSorting); }) ) - .subscribe(projects => (this._projects = projects)); + .subscribe(projects => { + this._projects = projects; + this.isLoading = false; + }); } addToProject(): void { this.addToProjectClicked = true; - this.projectSelect.customValidate(SFValidators.customValidator(this.getCustomErrorState())); + this.validateProject(); if (!this.isAppOnline || !this.isFormValid || this.targetProjectId == null || !this.canEditProject) { return; } @@ -150,7 +159,7 @@ export class DraftApplyDialogComponent implements OnInit { this.canEditProject = false; this.targetBookExists = false; this.targetProject$.next(undefined); - this.projectSelect.customValidate(SFValidators.customValidator(this.getCustomErrorState())); + this.validateProject(); return; } @@ -172,13 +181,21 @@ export class DraftApplyDialogComponent implements OnInit { } else { this.targetProject$.next(undefined); } - this.projectSelect.customValidate(SFValidators.customValidator(this.getCustomErrorState(paratextId))); + this.validateProject(); } close(): void { this.dialogRef.close(); } + private validateProject(): void { + // setTimeout prevents a "changed after checked" exception (may be removable after SF-3014) + setTimeout(() => { + this.isValid = this.getCustomErrorState() === CustomErrorState.None; + this.projectSelect?.customValidate(SFValidators.customValidator(this.getCustomErrorState())); + }); + } + private async chaptersWithTextAsync(project: SFProjectProfile): Promise { if (this.targetProjectId == null) return 0; const chapters: Chapter[] | undefined = project.texts.find(t => t.bookNum === this.data.bookNum)?.chapters; @@ -196,8 +213,8 @@ export class DraftApplyDialogComponent implements OnInit { return textDoc.getNonEmptyVerses().length > 0; } - private getCustomErrorState(paratextId?: string): CustomErrorState { - if (!this.projectSelectValid && paratextId == null) { + private getCustomErrorState(): CustomErrorState { + if (!this.projectSelectValid) { return CustomErrorState.InvalidProject; } if (!this.targetBookExists) { diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.html index c0fef5dce9..6f28ce1f38 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.html +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.html @@ -9,11 +9,11 @@ - @if ((isProjectAdmin$ | async) === true) { - } diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.spec.ts index 6166738203..65034a80a3 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.spec.ts +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.spec.ts @@ -89,75 +89,79 @@ describe('DraftPreviewBooks', () => { it('does not apply draft if user cancels', fakeAsync(() => { env = new TestEnvironment(); const bookWithDraft: BookWithDraft = env.booksWithDrafts[0]; - when(mockedDialogService.confirmWithOptions(anything())).thenResolve(false); + setupDialog(); expect(env.getBookButtonAtIndex(0).querySelector('.book-more')).toBeTruthy(); - env.component.confirmAndAddToProjectAsync(bookWithDraft); + env.component.chooseProjectToAddDraft(bookWithDraft); tick(); env.fixture.detectChanges(); - verify(mockedDialogService.confirmWithOptions(anything())).once(); + verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); verify(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).never(); })); it('notifies user if applying a draft failed due to an error', fakeAsync(() => { env = new TestEnvironment(); const bookWithDraft: BookWithDraft = env.booksWithDrafts[0]; - when(mockedDialogService.confirmWithOptions(anything())).thenResolve(true); + setupDialog('project01'); when(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())) .thenReject(new Error('Draft error')) .thenResolve(true) .thenResolve(false); expect(env.getBookButtonAtIndex(0).querySelector('.book-more')).toBeTruthy(); - env.component.confirmAndAddToProjectAsync(bookWithDraft); + env.component.chooseProjectToAddDraft(bookWithDraft); tick(); env.fixture.detectChanges(); expect(env.draftApplyProgress!.chaptersApplied).toEqual([2]); expect(env.draftApplyProgress!.completed).toBe(true); - verify(mockedDialogService.confirmWithOptions(anything())).once(); + verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); verify(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).times(3); verify(mockedErrorReportingService.silentError(anything(), anything())).once(); })); - it('notifies user if they do not have permission to edit a book when applying a draft', fakeAsync(() => { - env = new TestEnvironment(); - const bookWithDraft: BookWithDraft = env.booksWithDrafts[2]; - when(mockedDialogService.message(anything())).thenResolve(); - expect(env.getBookButtonAtIndex(2).querySelector('.book-more')).toBeTruthy(); - env.component.confirmAndAddToProjectAsync(bookWithDraft); - tick(); - env.fixture.detectChanges(); - verify(mockedDialogService.confirmWithOptions(anything())).never(); - verify(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).never(); - verify(mockedErrorReportingService.silentError(anything(), anything())).never(); - })); - it('can apply all chapters of a draft to a book', fakeAsync(() => { env = new TestEnvironment(); const bookWithDraft: BookWithDraft = env.booksWithDrafts[0]; - when(mockedDialogService.confirmWithOptions(anything())).thenResolve(true); + setupDialog('project01'); when(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).thenResolve(true); expect(env.getBookButtonAtIndex(0).querySelector('.book-more')).toBeTruthy(); - env.component.confirmAndAddToProjectAsync(bookWithDraft); + env.component.chooseProjectToAddDraft(bookWithDraft); tick(); env.fixture.detectChanges(); expect(env.draftApplyProgress!.chaptersApplied).toEqual([1, 2, 3]); expect(env.draftApplyProgress!.completed).toBe(true); - verify(mockedDialogService.confirmWithOptions(anything())).once(); + verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); verify(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).times(3); })); it('can apply chapters with drafts and skips chapters without drafts', fakeAsync(() => { env = new TestEnvironment(); const bookWithDraft: BookWithDraft = env.booksWithDrafts[1]; - when(mockedDialogService.confirmWithOptions(anything())).thenResolve(true); + setupDialog('project01'); when(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).thenResolve(true); expect(env.getBookButtonAtIndex(1).querySelector('.book-more')).toBeTruthy(); - env.component.confirmAndAddToProjectAsync(bookWithDraft); + env.component.chooseProjectToAddDraft(bookWithDraft); tick(); env.fixture.detectChanges(); - verify(mockedDialogService.confirmWithOptions(anything())).once(); + verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); verify(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).times(1); })); + it('can open dialog with the current project', fakeAsync(() => { + env = new TestEnvironment(); + expect(env.getBookButtonAtIndex(0).querySelector('.book-more')).toBeTruthy(); + const mockedDialogRef: MatDialogRef = mock(MatDialogRef); + when(mockedDialogRef.afterClosed()).thenReturn(of({ projectId: 'project01' })); + when(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).thenReturn( + instance(mockedDialogRef) + ); + env.component.chooseProjectToAddDraft(env.booksWithDrafts[0], 'project01'); + tick(); + env.fixture.detectChanges(); + verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); + verify(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).times( + env.booksWithDrafts[0].chaptersWithDrafts.length + ); + })); + it('can open dialog to apply draft to a different project', fakeAsync(() => { env = new TestEnvironment(); expect(env.getBookButtonAtIndex(0).querySelector('.book-more')).toBeTruthy(); @@ -166,7 +170,7 @@ describe('DraftPreviewBooks', () => { when(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).thenReturn( instance(mockedDialogRef) ); - env.component.chooseAlternateProjectToAddDraft(env.booksWithDrafts[0]); + env.component.chooseProjectToAddDraft(env.booksWithDrafts[0]); tick(); env.fixture.detectChanges(); verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); @@ -192,12 +196,8 @@ describe('DraftPreviewBooks', () => { it('does not apply draft if user cancels applying to a different project', fakeAsync(() => { env = new TestEnvironment(); - const mockedDialogRef: MatDialogRef = mock(MatDialogRef); - when(mockedDialogRef.afterClosed()).thenReturn(of(undefined)); - when(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).thenReturn( - instance(mockedDialogRef) - ); - env.component.chooseAlternateProjectToAddDraft(env.booksWithDrafts[0]); + setupDialog(); + env.component.chooseProjectToAddDraft(env.booksWithDrafts[0]); tick(); env.fixture.detectChanges(); verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); @@ -208,20 +208,20 @@ describe('DraftPreviewBooks', () => { it('shows message to generate a new draft if legacy USFM draft', fakeAsync(() => { env = new TestEnvironment(); const bookWithDraft: BookWithDraft = env.booksWithDrafts[0]; - when(mockedDialogService.confirmWithOptions(anything())).thenResolve(true); + setupDialog('project01'); when(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).thenResolve(false); expect(env.getBookButtonAtIndex(0).querySelector('.book-more')).toBeTruthy(); - env.component.confirmAndAddToProjectAsync(bookWithDraft); + env.component.chooseProjectToAddDraft(bookWithDraft); tick(); env.fixture.detectChanges(); - verify(mockedDialogService.confirmWithOptions(anything())).once(); + verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); verify(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).times(3); })); it('can track progress of chapters applied', fakeAsync(() => { env = new TestEnvironment(); const bookWithDraft: BookWithDraft = env.booksWithDrafts[0]; - when(mockedDialogService.confirmWithOptions(anything())).thenResolve(true); + setupDialog('project01'); const resolveSubject$: BehaviorSubject = new BehaviorSubject(false); const promise: Promise = new Promise(resolve => { resolveSubject$.pipe(filter(value => value)).subscribe(() => resolve(true)); @@ -230,10 +230,10 @@ describe('DraftPreviewBooks', () => { .thenReturn(Promise.resolve(true)) .thenReturn(promise); expect(env.getBookButtonAtIndex(0).querySelector('.book-more')).toBeTruthy(); - env.component.confirmAndAddToProjectAsync(bookWithDraft); + env.component.chooseProjectToAddDraft(bookWithDraft); tick(); env.fixture.detectChanges(); - verify(mockedDialogService.confirmWithOptions(anything())).once(); + verify(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).once(); verify(mockedDraftHandlingService.getAndApplyDraftAsync(anything(), anything(), anything())).times(3); expect(env.component.numChaptersApplied).toEqual(1); resolveSubject$.next(true); @@ -242,6 +242,14 @@ describe('DraftPreviewBooks', () => { env.fixture.detectChanges(); expect(env.component.numChaptersApplied).toEqual(3); })); + + function setupDialog(projectId?: string): void { + const mockedDialogRef: MatDialogRef = mock(MatDialogRef); + when(mockedDialogRef.afterClosed()).thenReturn(of(projectId ? { projectId } : undefined)); + when(mockedDialogService.openMatDialog(DraftApplyDialogComponent, anything())).thenReturn( + instance(mockedDialogRef) + ); + } }); class TestEnvironment { diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.ts index 2ff98d9267..83026c08dc 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.ts +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-preview-books/draft-preview-books.component.ts @@ -2,12 +2,12 @@ import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { MatDialogRef } from '@angular/material/dialog'; import { Router, RouterModule } from '@angular/router'; -import { TranslocoModule, translate } from '@ngneat/transloco'; +import { TranslocoModule } from '@ngneat/transloco'; import { Canon } from '@sillsdev/scripture'; import { SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project'; import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-role'; import { TextInfoPermission } from 'realtime-server/lib/esm/scriptureforge/models/text-info-permission'; -import { BehaviorSubject, Observable, firstValueFrom, map } from 'rxjs'; +import { BehaviorSubject, firstValueFrom, map, Observable, tap } from 'rxjs'; import { ActivatedProjectService } from 'xforge-common/activated-project.service'; import { DialogService } from 'xforge-common/dialog.service'; import { ErrorReportingService } from 'xforge-common/error-reporting.service'; @@ -64,6 +64,8 @@ export class DraftPreviewBooksComponent { DraftApplyProgress | undefined >(undefined); + protected projectParatextId?: string; + private applyChapters: number[] = []; private draftApplyBookNum: number = 0; private chaptersApplied: number[] = []; @@ -81,6 +83,7 @@ export class DraftPreviewBooksComponent { get isProjectAdmin$(): Observable { return this.activatedProjectService.changes$.pipe( filterNullish(), + tap(p => (this.projectParatextId = p.data?.paratextId)), map(p => p.data?.userRoles[this.userService.currentUserId] === SFProjectRole.ParatextAdministrator) ); } @@ -107,8 +110,9 @@ export class DraftPreviewBooksComponent { return this.i18n.localizeBook(bookNumber); } - async chooseAlternateProjectToAddDraft(bookWithDraft: BookWithDraft): Promise { + async chooseProjectToAddDraft(bookWithDraft: BookWithDraft, paratextId?: string): Promise { const dialogData: DraftApplyDialogData = { + initialParatextId: paratextId, bookNum: bookWithDraft.bookNumber, chapters: bookWithDraft.chaptersWithDrafts }; @@ -120,30 +124,11 @@ export class DraftPreviewBooksComponent { if (result == null || result.projectId == null) { return; } - await this.applyBookDraftAsync(bookWithDraft, result.projectId); - } - - async confirmAndAddToProjectAsync(bookWithDraft: BookWithDraft): Promise { - if (!bookWithDraft.canEdit) { - await this.dialogService.message(translate('draft_preview_books.no_permission_to_edit_book')); - return; - } - const bookName: string = this.bookNumberToName(bookWithDraft.bookNumber); - const confirmed = await this.dialogService.confirmWithOptions({ - title: bookWithDraft.draftApplied - ? this.i18n.translate('draft_add_dialog.readd_book_to_project', { bookName }) - : this.i18n.translate('draft_add_dialog.add_book_to_project', { bookName }), - message: this.i18n.translate('draft_add_dialog.book_contents_will_be_overwritten', { bookName }), - affirmative: bookWithDraft.draftApplied ? 'draft_add_dialog.readd_to_project' : 'draft_add_dialog.add_to_project' - }); - - if (!confirmed) return; - - await this.applyBookDraftAsync(bookWithDraft); + await this.applyBookDraftAsync(bookWithDraft, result.projectId); } - private async applyBookDraftAsync(bookWithDraft: BookWithDraft, alternateProjectId?: string): Promise { + private async applyBookDraftAsync(bookWithDraft: BookWithDraft, projectId: string): Promise { this.applyChapters = bookWithDraft.chaptersWithDrafts; this.draftApplyBookNum = bookWithDraft.bookNumber; this.chaptersApplied = []; @@ -153,11 +138,7 @@ export class DraftPreviewBooksComponent { const project: SFProjectProfile = this.activatedProjectService.projectDoc!.data!; for (const chapter of bookWithDraft.chaptersWithDrafts) { const draftTextDocId = new TextDocId(this.activatedProjectService.projectId!, bookWithDraft.bookNumber, chapter); - const targetTextDocId = new TextDocId( - alternateProjectId ?? this.activatedProjectService.projectId!, - bookWithDraft.bookNumber, - chapter - ); + const targetTextDocId = new TextDocId(projectId, bookWithDraft.bookNumber, chapter); promises.push(this.applyAndReportChapter(project, draftTextDocId, targetTextDocId)); } diff --git a/src/SIL.XForge.Scripture/ClientApp/src/assets/i18n/non_checking_en.json b/src/SIL.XForge.Scripture/ClientApp/src/assets/i18n/non_checking_en.json index 6818b17f1f..a1827a2485 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/assets/i18n/non_checking_en.json +++ b/src/SIL.XForge.Scripture/ClientApp/src/assets/i18n/non_checking_en.json @@ -143,14 +143,6 @@ "please_type_project_name": "Please type in the name of the project to confirm.", "project_name": "Project Name" }, - "draft_add_dialog": { - "add_book_to_project": "Add {{ bookName }} to project", - "add_to_project": "Add to project", - "book_contents_will_be_overwritten": "Warning, this will overwrite any data in your project for the book of {{ bookName }}.", - "cancel": "Cancel", - "readd_book_to_project": "Re-add {{ bookName }} to project", - "readd_to_project": "Re-add to project" - }, "draft_apply_dialog": { "add_to_project": "Add to project", "book_does_not_exist": "{{ bookName }} on the selected project does not exist",