diff --git a/src/RealtimeServer/scriptureforge/models/translate-config.ts b/src/RealtimeServer/scriptureforge/models/translate-config.ts index de00bfa0ac..3fddf4836c 100644 --- a/src/RealtimeServer/scriptureforge/models/translate-config.ts +++ b/src/RealtimeServer/scriptureforge/models/translate-config.ts @@ -35,6 +35,11 @@ export enum ParagraphBreakFormat { MoveToEnd = 'move_to_end' } +export enum QuoteFormat { + Automatic = 'automatic', + Straight = 'straight' +} + export interface BaseProject { paratextId: string; shortName: string; diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-history-list/draft-history-entry/draft-history-entry.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-history-list/draft-history-entry/draft-history-entry.component.html index 3d22dcf2be..0740b6497a 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-history-list/draft-history-entry/draft-history-entry.component.html +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-history-list/draft-history-entry/draft-history-entry.component.html @@ -27,8 +27,7 @@ @if (featureFlags.usfmFormat.enabled && isLatestBuild) { } diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.html index e4d3fdc6d7..d8c61f2bb1 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.html +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.html @@ -6,26 +6,24 @@

{{ t("draft_format_options") }}

-

- {{ t("draft_format_description") }} -

+

{{ t("draft_format_description") }}

{{ t("paragraph_break_title") }}{{ t("line_breaks_title") }} - {{ t("paragraph_break_description") }} + {{ t("line_breaks_description") }} {{ t("option_best_guess") }} - new + {{ t("new") }} - {{ t("option_best_guess_description") }} Recommended for most projects. + {{ t("option_best_guess_description") }} {{ t("option_remove") }} - new + {{ t("new") }} {{ t("option_remove_description") }} @@ -43,14 +41,14 @@

{{ t("draft_format_options") }}

Choose how quotes should appear in the draft. - - - Automatic quote style new + + + Automatic quote style {{ t("new") }} - Attempt to use the same quote style as the rest of the project. Recommended for most projects. + Use the same quote style as the rest of the project, if possible. Recommended for most projects. - + Straight quotes Use only straight quotes in the draft. @@ -64,6 +62,9 @@

{{ t("draft_format_options") }}

check {{ t("save_changes") }} +
+ +
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.scss b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.scss index 8f370cbbf3..0e77c38448 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.scss +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.scss @@ -85,7 +85,16 @@ form { .actions { display: flex; - justify-content: space-between; + column-gap: 8px; + align-items: center; + justify-content: flex-end; + + .progress { + visibility: hidden; + &.saving { + visibility: visible; + } + } } .new { diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.spec.ts index 9686f9a588..ac1c194c23 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.spec.ts +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.spec.ts @@ -5,7 +5,11 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { Router } from '@angular/router'; import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data'; import { TextInfo } from 'realtime-server/lib/esm/scriptureforge/models/text-info'; -import { DraftUsfmConfig, ParagraphBreakFormat } from 'realtime-server/lib/esm/scriptureforge/models/translate-config'; +import { + DraftUsfmConfig, + ParagraphBreakFormat, + QuoteFormat +} from 'realtime-server/lib/esm/scriptureforge/models/translate-config'; import { of } from 'rxjs'; import { anything, deepEqual, mock, verify, when } from 'ts-mockito'; import { ActivatedProjectService } from 'xforge-common/activated-project.service'; @@ -94,9 +98,10 @@ describe('DraftUsfmFormatComponent', () => { verify(mockedDraftHandlingService.getDraft(anything(), anything())).thrice(); })); - it('should initialize and default to best guess', fakeAsync(async () => { + it('should initialize and default to best guess and automatic quotes', fakeAsync(async () => { const env = new TestEnvironment(); expect(env.component.paragraphFormat.value).toBe(ParagraphBreakFormat.BestGuess); + expect(env.component.quoteFormat.value).toBe(QuoteFormat.Automatic); expect(await env.component.confirmLeave()).toBe(true); })); @@ -143,7 +148,8 @@ describe('DraftUsfmFormatComponent', () => { env.fixture.detectChanges(); verify(mockedProjectService.onlineSetUsfmConfig(env.projectId, deepEqual(config))).once(); verify(mockedServalAdministration.onlineRetrievePreTranslationStatus(env.projectId)).once(); - verify(mockedRouter.navigate(deepEqual(['projects', env.projectId, 'draft-generation']))).never(); + verify(mockedNoticeService.show(anything())).once(); + verify(mockedRouter.navigate(deepEqual(['projects', env.projectId, 'draft-generation']))).once(); })); it('should not save if format is empty', fakeAsync(() => { @@ -183,6 +189,7 @@ class TestEnvironment { this.onlineStatusService.setIsOnline(true); when(mockedNoticeService.show(anything())).thenResolve(); when(mockedDialogService.confirm(anything(), anything(), anything())).thenResolve(true); + when(mockedServalAdministration.onlineRetrievePreTranslationStatus(anything())).thenResolve(); this.setupProject(args.config); this.fixture = TestBed.createComponent(DraftUsfmFormatComponent); this.component = this.fixture.componentInstance; diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.ts index a366c70b7d..819a406268 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.ts +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-usfm-format/draft-usfm-format.component.ts @@ -13,7 +13,11 @@ import { Router } from '@angular/router'; import { translate, TranslocoModule } from '@ngneat/transloco'; import { Delta } from 'quill'; import { TextInfo } from 'realtime-server/lib/esm/scriptureforge/models/text-info'; -import { DraftUsfmConfig, ParagraphBreakFormat } from 'realtime-server/lib/esm/scriptureforge/models/translate-config'; +import { + DraftUsfmConfig, + ParagraphBreakFormat, + QuoteFormat +} from 'realtime-server/lib/esm/scriptureforge/models/translate-config'; import { combineLatest, first, Subject, switchMap } from 'rxjs'; import { ActivatedProjectService } from 'xforge-common/activated-project.service'; import { DataLoadingComponent } from 'xforge-common/data-loading-component'; @@ -59,12 +63,17 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af chapters: number[] = []; isInitializing: boolean = true; paragraphBreakFormat = ParagraphBreakFormat; + quoteStyleFormat = QuoteFormat; paragraphFormat = new FormControl(ParagraphBreakFormat.BestGuess); + quoteFormat = new FormControl(QuoteFormat.Automatic); usfmFormatForm: FormGroup = new FormGroup({ - paragraphFormat: this.paragraphFormat + paragraphFormat: this.paragraphFormat, + quoteFormat: this.quoteFormat }); + protected saving = false; + private updateDraftConfig$: Subject = new Subject(); private lastSavedState?: DraftUsfmConfig; @@ -167,14 +176,18 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af if (this.projectId == null || !this.isOnline || this.currentFormat == null) return; try { + this.saving = true; await this.projectService.onlineSetUsfmConfig(this.projectId, this.currentFormat); this.lastSavedState = this.currentFormat; // not awaited so that the user is directed to the draft generation page this.servalAdministration.onlineRetrievePreTranslationStatus(this.projectId).then(() => { + this.router.navigate(['projects', this.projectId, 'draft-generation']); this.noticeService.show(translate('draft_usfm_format.changes_have_been_saved')); }); } catch { this.noticeService.showError(translate('draft_usfm-format.failed_to_save')); + } finally { + this.saving = false; } } @@ -189,7 +202,8 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af private setUsfmConfig(config?: DraftUsfmConfig): void { this.usfmFormatForm.setValue({ - paragraphFormat: config?.paragraphFormat ?? ParagraphBreakFormat.BestGuess + paragraphFormat: config?.paragraphFormat ?? ParagraphBreakFormat.BestGuess, + quoteFormat: QuoteFormat.Automatic }); this.lastSavedState = this.currentFormat; 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 c7c8fddec7..d912281c5c 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 @@ -335,17 +335,18 @@ "changes_have_been_saved": "Changes have been saved", "cancel": "Cancel", "connect_to_the_internet": "Please connect to the internet to change the USFM format for your draft", - "draft_format_description": "Your draft has completed. However, there are some formatting options that you can choose before using your draft.", + "draft_format_description": "The draft has been created. Here are some formatting options for the text. You can try each option to see the difference it makes.", "draft_format_options": "Format draft", "failed_to_save": "Failed to save changes. Try again later.", + "new": "New", "option_best_guess": "Best guess", - "option_best_guess_description": "Mid-verse paragraph breaks in the source will be placed at the best guess of where they should be in the draft.", + "option_best_guess_description": "Line breaks in the source will be placed at the best guess of where they should be in the draft. Recommended for most projects.", "option_end": "Move to end", - "option_end_description": "Mid-verse paragraph breaks in the source will be moved to the end of the verse in the draft.", + "option_end_description": "Line breaks in the source will be moved to the end of the verse.", "option_remove": "Remove", - "option_remove_description": "Mid-verse paragraph breaks in the source will be omitted in the draft.", - "paragraph_break_description": "Scripture Forge translates each verse as a whole for best text quality. Choose how the paragraph breaks from the source verses are placed.", - "paragraph_break_title": "Mid-verse paragraph breaks", + "option_remove_description": "Line breaks in the source will be omitted from the draft.", + "line_breaks_description": "Scripture Forge translates complete verses, without line breaks, because this gives the best draft. Choose where to place the line breaks from the source.", + "line_breaks_title": "Line breaks", "save_changes": "Save" }, "editor": {