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 15f2a029be..ea9e6aa5b8 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
@@ -21,7 +21,7 @@
- @if (formattingOptionsSupported && !formattingOptionsSelected && isLatestBuild && draftIsAvailable) {
+ @if (formattingOptionsSupported && !formattingOptionsSelected && draftIsAvailable) {
{{ t("select_formatting_options") }}
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 4c224958b9..9cb61866a2 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
@@ -70,14 +70,20 @@
{{ t("formatting_options") }}
-
+ @if (!canPreviewDraft) {
+
+ {{ t("new_draft_required") }}
+
+ } @else {
+
+ }
{
const env = new TestEnvironment({ canDenormalizeQuotes: false });
expect(env.quoteFormatWarning).not.toBeNull();
}));
+
+ it('shows a notice if we are configuring for a build that is not the latest', fakeAsync(async () => {
+ const env = new TestEnvironment({ hasDraft: false });
+ verify(mockedDraftHandlingService.getDraft(anything(), anything())).never();
+ expect(env.harnesses?.length).toEqual(5);
+ await env.harnesses![0].check();
+ tick();
+ expect(env.component.canPreviewDraft).toBe(false);
+ expect(env.cannotPreviewDraftWarning).not.toBeNull();
+ env.fixture.detectChanges();
+ const config: DraftUsfmConfig = {
+ paragraphFormat: ParagraphBreakFormat.BestGuess,
+ quoteFormat: QuoteFormat.Denormalized
+ };
+ verify(mockedProjectService.onlineSetUsfmConfig(env.projectId, anything())).never();
+ verify(mockedDraftHandlingService.getDraft(anything(), anything())).never();
+
+ // redirect to generate draft
+ env.saveButton.click();
+ tick();
+ env.fixture.detectChanges();
+ verify(mockedProjectService.onlineSetUsfmConfig(env.projectId, deepEqual(config))).once();
+ verify(mockedServalAdministration.onlineRetrievePreTranslationStatus(env.projectId)).never();
+ verify(mockedLocation.back()).once();
+ }));
});
class TestEnvironment {
@@ -322,7 +347,7 @@ class TestEnvironment {
readonly projectId = 'project01';
onlineStatusService: TestOnlineStatusService;
- constructor(args: { project?: Partial; canDenormalizeQuotes?: boolean } = {}) {
+ constructor(args: { project?: Partial; canDenormalizeQuotes?: boolean; hasDraft?: boolean } = {}) {
const userDoc = mock(UserDoc);
this.onlineStatusService = TestBed.inject(OnlineStatusService) as TestOnlineStatusService;
when(mockedDraftGenerationService.getLastCompletedBuild(anything())).thenReturn(
@@ -342,7 +367,7 @@ class TestEnvironment {
when(mockedNoticeService.show(anything())).thenResolve();
when(mockedDialogService.confirm(anything(), anything(), anything())).thenResolve(true);
when(mockedServalAdministration.onlineRetrievePreTranslationStatus(anything())).thenResolve();
- when(mockedProjectService.hasDraft(anything(), anything(), anything())).thenReturn(true);
+ when(mockedProjectService.hasDraft(anything(), anything(), anything())).thenReturn(args.hasDraft ?? true);
this.setupProject(args.project);
this.fixture = TestBed.createComponent(DraftUsfmFormatComponent);
this.component = this.fixture.componentInstance;
@@ -368,6 +393,10 @@ class TestEnvironment {
return this.fixture.nativeElement.querySelector('.quote-format-warning');
}
+ get cannotPreviewDraftWarning(): HTMLElement | null {
+ return this.fixture.nativeElement.querySelector('.preview-draft-warning');
+ }
+
setupProject(project?: Partial): void {
const texts: TextInfo[] = [
{
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 6091a63a34..d31152ab28 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
@@ -77,6 +77,7 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af
isInitializing: boolean = true;
paragraphBreakFormat = ParagraphBreakFormat;
quoteStyle = QuoteFormat;
+ canPreviewDraft: boolean = true;
paragraphFormat = new FormControl(ParagraphBreakFormat.BestGuess);
quoteFormat = new FormControl(QuoteFormat.Denormalized);
@@ -158,6 +159,7 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af
const projectDoc = this.activatedProjectService.projectDoc;
if (projectDoc?.data == null) return;
this.setUsfmConfig(projectDoc.data.translateConfig.draftConfig.usfmConfig);
+ this.canPreviewDraft = this.projectService.hasDraft(projectDoc.data, undefined, true);
const texts: TextInfo[] = projectDoc.data.texts;
this.booksWithDrafts = texts
.filter(t => this.projectService.hasDraft(projectDoc.data, t.bookNum, true))
@@ -218,8 +220,10 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af
}
reloadText(): void {
- this.loadingStarted();
- this.updateDraftConfig$.next(this.currentFormat);
+ if (this.canPreviewDraft) {
+ this.loadingStarted();
+ this.updateDraftConfig$.next(this.currentFormat);
+ }
}
async saveChanges(): Promise {
@@ -229,8 +233,11 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af
this.saving = true;
await this.projectService.onlineSetUsfmConfig(this.projectId, this.currentFormat);
this.lastSavedState = this.currentFormat;
+ // If the user could not preview the draft, we should not update it, as a blank draft will result
+ if (this.canPreviewDraft) {
+ await this.servalAdministration.onlineRetrievePreTranslationStatus(this.projectId);
+ }
// The user is redirected to the draft generation page if the format is saved.
- await this.servalAdministration.onlineRetrievePreTranslationStatus(this.projectId);
this.close();
} catch (err) {
console.error('Error occurred while saving draft format', err);
@@ -267,7 +274,7 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af
quietTakeUntilDestroyed(this.destroyRef)
)
.subscribe(isOnline => {
- if (isOnline) this.reloadText();
+ if (isOnline && this.canPreviewDraft) this.reloadText();
});
}
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 b32c469766..1425c04280 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
@@ -369,6 +369,7 @@
"paragraph_breaks_description": "Scripture Forge translates complete verses, without paragraph breaks, because this gives the best translation. Choose where to place the paragraph breaks from the source.",
"paragraph_breaks_title": "Paragraph breaks",
"new": "new",
+ "new_draft_required": "You must generate a new draft to preview the formatting options. Changing these options will not update any existing drafts you may have.",
"no_quote_convention_detected": "No quote convention could be detected for your project. Straight quotes will be used in the draft regardless of which option you choose.",
"option_best_guess": "Best guess",
"option_best_guess_description": "Paragraph breaks in the source will be placed at the best guess of where they should be in the draft. Recommended for most projects.",