diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.html index a6667c5496c..1e1dffbed40 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.html +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.html @@ -139,17 +139,23 @@

{{ t("confirm") }}

Training the language model

{{ t("confirm_training") }} - +
- + - + - + @@ -165,7 +171,7 @@

@for (book of userSelectedTranslateBooks; track book) { - {{ book.name }} + {{ book.name }} }
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.scss b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.scss index 0a2a03d24d3..7a1ee8707fb 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.scss +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.scss @@ -104,7 +104,7 @@ app-notice { padding-inline-start: 16px; } -.readonly-book { +.confirm-book { padding-block: 4px; font-weight: 500; } diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.ts index 4a80596b4f2..d1ebb7a98b6 100644 --- a/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.ts +++ b/src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-generation-steps/draft-generation-steps.component.ts @@ -10,6 +10,7 @@ import { Subscription, merge } from 'rxjs'; import { filter, tap } from 'rxjs/operators'; import { ActivatedProjectService } from 'xforge-common/activated-project.service'; import { FeatureFlagService } from 'xforge-common/feature-flags/feature-flag.service'; +import { I18nService } from 'xforge-common/i18n.service'; import { RealtimeQuery } from 'xforge-common/models/realtime-query'; import { SubscriptionDisposable } from 'xforge-common/subscription-disposable'; import { UICommonModule } from 'xforge-common/ui-common.module'; @@ -38,7 +39,13 @@ export interface Book { number: number; } -export interface TrainingBook extends Book { +export interface TrainingBook extends Book, TrainingPair {} + +export interface TrainingGroup extends TrainingPair { + ranges: string[]; +} + +interface TrainingPair { source: string; target: string; } @@ -102,10 +109,11 @@ export class DraftGenerationStepsComponent extends SubscriptionDisposable implem constructor( private readonly activatedProject: ActivatedProjectService, private readonly draftSourcesService: DraftSourcesService, - readonly featureFlags: FeatureFlagService, + protected readonly featureFlags: FeatureFlagService, private readonly nllbLanguageService: NllbLanguageService, private readonly trainingDataService: TrainingDataService, - private readonly progressService: ProgressService + private readonly progressService: ProgressService, + protected readonly i18n: I18nService ) { super(); const project = activatedProject.projectDoc!.data!; @@ -249,6 +257,53 @@ export class DraftGenerationStepsComponent extends SubscriptionDisposable implem ); } + selectedTrainingBooksCollapsed(): TrainingGroup[] { + const continguousGroups: TrainingGroup[] = []; + let currentGroup: TrainingBook[] = []; + for (const book of this.userSelectedTrainingBooks) { + const isBookConsecutiveAndMatching = + book.source === currentGroup[0]?.source && + book.target === currentGroup[0]?.target && + book.number === currentGroup[currentGroup.length - 1]?.number + 1; + if (currentGroup.length > 0 && !isBookConsecutiveAndMatching) { + //process and reset current group + addGroup(currentGroup); + currentGroup.length = 0; + } + //add book to current group + currentGroup.push(book); + } + + //add last group + if (currentGroup.length > 0) { + addGroup(currentGroup); + } + + const groupsCollapsed: TrainingGroup[] = []; + for (const group of continguousGroups) { + const matchIndex = groupsCollapsed.findIndex(g => g.source === group.source && g.target === group.target); + if (matchIndex === -1) { + //make a new group for this source/target + groupsCollapsed.push(group); + } else { + //append the current group onto the matching group + groupsCollapsed[matchIndex].ranges.push(group.ranges[0]); + } + } + + return groupsCollapsed; + + function addGroup(group: TrainingBook[]): void { + let range; + if (group.length === 1) { + range = Canon.bookNumberToId(group[0].number); + } else { + range = Canon.bookNumberToId(group[0].number) + '-' + Canon.bookNumberToId(group[group.length - 1].number); + } + continguousGroups.push({ ranges: [range], source: group[0].source, target: group[0].target }); + } + } + onTrainingBookSelect(selectedBooks: number[]): void { this.userSelectedTrainingBooks = selectedBooks.map((bookNum: number) => ({ number: bookNum,

{{ element.name }} + {{ element.ranges.join(", ") }} + {{ trainingSources[0].writingSystem.tag }} + {{ this.i18n.getLanguageDisplayName(trainingSources[0].writingSystem.tag) }} + {{ element.source }} {{ trainingTargets[0].writingSystem.tag }} + {{ this.i18n.getLanguageDisplayName(trainingTargets[0].writingSystem.tag) }} + {{ element.target }}