Skip to content

Commit

Permalink
SF-2986 Add step to confirm language codes before generating draft
Browse files Browse the repository at this point in the history
Co-authored-by: josephmyers <[email protected]>
  • Loading branch information
Nateowami and josephmyers committed Oct 16, 2024
1 parent 79824f5 commit 71f5d4b
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<h1 class="mat-headline-4">Confirm project setup</h1>
<h2>Training the language model</h2>
<div class="training-data">
<div class="source-description">
<h3>References ({{ referenceLanguage }})</h3>
</div>
<span class="gap"></span>
<div class="target-description">
<h3>Translation project ({{ targetLanguage }})</h3>
</div>
<div class="sources">
@for (project of trainingSources; track project.paratextId) {
<div class="project">
<span class="project-name">{{ project.name }}</span>
<span class="language-code">
Language code: <strong>{{ project.writingSystem.tag }}</strong>
</span>
</div>
}
</div>
<span class="arrow mirror-rtl"><mat-icon>arrow_right_alt</mat-icon></span>
<div class="targets">
@for (project of trainingTargets; track project.paratextId) {
<div class="project">
<span class="project-name">{{ project.name }}</span>
<span class="language-code">
Language code: <strong>{{ project.writingSystem.tag }}</strong>
</span>
</div>
}
</div>
</div>

<h2>Drafting from {{ draftingSourceShortNames }} ({{ draftingSourceLanguage }})</h2>
<div class="translation-data">
@for (project of draftingSources; track project.paratextId) {
<div class="project">
<span class="project-name">{{ project.name }}</span>
<span class="language-code">
Language code: <strong>{{ project.writingSystem.tag }}</strong>
</span>
</div>
}
</div>

<app-notice mode="outline">
<strong>Incorrect language codes will dramatically reduce draft quality.</strong>
<p>Language codes can be changed in Paratext by going to Project Settings > Project Properties > Language.</p>
<mat-checkbox (change)="confirmationChanged($event)">All the language codes are correct.</mat-checkbox>
</app-notice>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
.training-data {
display: grid;
grid-template-areas: '. . .' '. . .';
row-gap: 1em;
}

.arrow mat-icon {
scale: 2;
}

.gap,
.arrow {
padding-inline: 2em;
}

.training-data,
.translation-data {
background: #f6f6f6;
border-radius: 4px;
padding: 1em;
}

.sources,
.targets,
.arrow {
display: flex;
flex-direction: column;
justify-content: center;
gap: 1em;
}

.training-data h3 {
margin-block: 0;
}

.training-data p {
margin: 0;
}

h1,
h2,
h3,
h4,
strong {
font-weight: 500;
}

h1 {
margin-top: 1em;
margin-bottom: 0;
}

h2 {
margin-top: 1.5em;
margin-bottom: 0.5em;
}

.project {
display: flex;
flex-direction: column;
row-gap: 0.25em;
}

.project-name {
font-size: 1.1em;
}

.language-code {
font-size: 0.9em;
}

app-notice {
margin-top: 4em;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Component, EventEmitter, Output } from '@angular/core';
import { MatCheckboxChange, MatCheckboxModule } from '@angular/material/checkbox';
import { MatIconModule } from '@angular/material/icon';
import { TranslocoModule } from '@ngneat/transloco';
import { SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
import { TranslateSource } from 'realtime-server/lib/esm/scriptureforge/models/translate-config';
import { ActivatedProjectService } from '../../../../xforge-common/activated-project.service';
import { I18nService } from '../../../../xforge-common/i18n.service';
import { NoticeComponent } from '../../../shared/notice/notice.component';

@Component({
selector: 'app-confirm-sources',
standalone: true,
imports: [TranslocoModule, NoticeComponent, MatCheckboxModule, MatIconModule],
templateUrl: './confirm-sources.component.html',
styleUrl: './confirm-sources.component.scss'
})
export class ConfirmSourcesComponent {
@Output() languageCodesVerified = new EventEmitter<boolean>(false);

trainingSources: TranslateSource[] = [];
trainingTargets: SFProjectProfile[] = [];
draftingSources: TranslateSource[] = [];

constructor(
private readonly i18nService: I18nService,
activatedProjectService: ActivatedProjectService
) {
const project = activatedProjectService.projectDoc!.data!;
this.trainingTargets.push(project);

let trainingSource: TranslateSource | undefined;
if (project.translateConfig.draftConfig.alternateTrainingSourceEnabled) {
trainingSource = project.translateConfig.draftConfig.alternateTrainingSource;
} else {
trainingSource = project.translateConfig.source;
}

if (trainingSource != null) {
this.trainingSources.push(trainingSource);
}

if (project.translateConfig.draftConfig.additionalTrainingSourceEnabled) {
this.trainingSources.push(project.translateConfig.draftConfig.additionalTrainingSource!);
}

let draftingSource: TranslateSource | undefined;
if (project.translateConfig.draftConfig.alternateSourceEnabled) {
draftingSource = project.translateConfig.draftConfig.alternateSource;
} else {
draftingSource = project.translateConfig.source;
}

if (draftingSource != null) {
this.draftingSources.push(draftingSource);
}
}

confirmationChanged(change: MatCheckboxChange): void {
this.languageCodesVerified.emit(change.checked);
}

displayNameForProjectsLanguages(projects: (TranslateSource | SFProjectProfile)[]): string {
return Array.from(new Set(projects.map(p => p.writingSystem.tag)))
.map(tag => this.i18nService.getLanguageDisplayName(tag) ?? tag)
.join(', ');
}

get referenceLanguage(): string {
return this.displayNameForProjectsLanguages(this.trainingSources);
}

get targetLanguage(): string {
return this.displayNameForProjectsLanguages(this.trainingTargets);
}

get draftingSourceLanguage(): string {
return this.displayNameForProjectsLanguages(this.draftingSources);
}

get draftingSourceShortNames(): string {
return this.draftingSources.map(p => p.shortName).join(', ');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { CommonModule } from '@angular/common';
import { TranslocoModule } from '@ngneat/transloco';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
// import { I18nStoryModule } from '../../../../xforge-common/i18n-story.module';
// import { UICommonModule } from '../../../../xforge-common/ui-common.module';
import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data';
import { instance, mock, when } from 'ts-mockito';
import { ActivatedProjectService } from '../../../../xforge-common/activated-project.service';
import { SFProjectProfileDoc } from '../../../core/models/sf-project-profile-doc';
import { ConfirmSourcesComponent } from './confirm-sources.component';

const mockedActivatedProjectService = mock(ActivatedProjectService);

when(mockedActivatedProjectService.projectDoc).thenReturn({
data: createTestProjectProfile({
name: 'Test Project',
translateConfig: {
source: {
projectRef: 'source-project',
shortName: 'SP',
name: 'THIS PROJECT SHOULD NOT BE SHOWN!!!!!****',
paratextId: 'source-project',
writingSystem: { tag: 'es' }
},
draftConfig: {
alternateTrainingSourceEnabled: true,
alternateTrainingSource: {
projectRef: 'alternate-training-source',
shortName: 'ATS',
name: 'Alternate Training Source',
paratextId: 'alternate-training-source',
writingSystem: { tag: 'es' }
},
additionalTrainingSourceEnabled: true,
additionalTrainingSource: {
projectRef: 'additional-training-source',
shortName: 'ATS',
name: 'Additional Training Source',
paratextId: 'additional-training-source',
writingSystem: { tag: 'es' }
},
alternateSourceEnabled: true,
alternateSource: {
projectRef: 'alternate-drafting-source',
shortName: 'ADS',
name: 'Alternate Drafting Source',
paratextId: 'alternate-drafting-source',
writingSystem: { tag: 'es' }
}
}
}
})
} as SFProjectProfileDoc);

const meta: Meta = {
title: 'Translate/ConfirmSources',
component: ConfirmSourcesComponent,
decorators: [
moduleMetadata({
imports: [CommonModule, TranslocoModule],
providers: [{ provide: ActivatedProjectService, useValue: instance(mockedActivatedProjectService) }]
})
]
};

export default meta;

interface StoryState {}

type Story = StoryObj<StoryState>;

export const Default: Story = {
args: {
book: 1,
progress: 0.37,
hues: [0]
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@
<!-- Icon overrides -->
<ng-template matStepperIcon="edit" let-index="index">{{ index + 1 }}</ng-template>

<mat-step [completed]="languagesVerified">
<ng-template matStepLabel> Confirm setup</ng-template>
<app-confirm-sources (languageCodesVerified)="languagesVerified = $event"></app-confirm-sources>
@if (nextClickedOnLanguageVerification && !languagesVerified) {
<app-notice type="error" mode="fill-dark">
Please confirm the language codes are correct before continuing.
</app-notice>
}
<div class="button-strip">
<button mat-stroked-button matStepperPrevious>{{ t("back") }}</button>
<button mat-flat-button (click)="tryAdvanceStep()" color="primary">{{ t("next") }}</button>
</div>
</mat-step>

<mat-step [completed]="userSelectedTranslateBooks.length > 0">
<ng-template matStepLabel>
{{ t("choose_books_to_translate_label") }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
@use 'src/xforge-common/media-breakpoints/breakpoints' as *;

:host {
display: block;
max-width: 80em;
}

.stepper-multi-header {
h2,
h3 {
text-overflow: ellipsis;
overflow: hidden;
}
}

h1 {
margin: 12px 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { BookMultiSelectComponent } from '../../../shared/book-multi-select/book
import { ProgressService } from '../../../shared/progress-service/progress.service';
import { SharedModule } from '../../../shared/shared.module';
import { NllbLanguageService } from '../../nllb-language.service';
import { ConfirmSourcesComponent } from '../confirm-sources/confirm-sources.component';
import { DraftSource, DraftSourcesService } from '../draft-sources.service';
import { TrainingDataMultiSelectComponent } from '../training-data/training-data-multi-select.component';
import { TrainingDataUploadDialogComponent } from '../training-data/training-data-upload-dialog.component';
Expand All @@ -43,14 +44,18 @@ export interface DraftGenerationStepsResult {
TranslocoMarkupModule,
BookMultiSelectComponent,
TrainingDataMultiSelectComponent,
TrainingDataUploadDialogComponent
TrainingDataUploadDialogComponent,
ConfirmSourcesComponent
]
})
export class DraftGenerationStepsComponent extends SubscriptionDisposable implements OnInit {
@Output() readonly done = new EventEmitter<DraftGenerationStepsResult>();
@Output() readonly cancel = new EventEmitter();
@ViewChild(MatStepper) stepper!: MatStepper;

languagesVerified = false;
nextClickedOnLanguageVerification = false;

availableTranslateBooks?: number[] = undefined;
availableTrainingBooks: number[] = [];
availableTrainingData: Readonly<TrainingData>[] = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { ServalProjectComponent } from '../../serval-administration/serval-proje
import { SharedModule } from '../../shared/shared.module';
import { WorkingAnimatedIndicatorComponent } from '../../shared/working-animated-indicator/working-animated-indicator.component';
import { NllbLanguageService } from '../nllb-language.service';
import { ConfirmSourcesComponent } from './confirm-sources/confirm-sources.component';
import { BuildConfig, DraftZipProgress, activeBuildStates } from './draft-generation';
import {
DraftGenerationStepsComponent,
Expand Down Expand Up @@ -61,7 +62,8 @@ import { SupportedBackTranslationLanguagesDialogComponent } from './supported-ba
DraftInformationComponent,
SupportedBackTranslationLanguagesDialogComponent,
ServalProjectComponent,
DraftPreviewBooksComponent
DraftPreviewBooksComponent,
ConfirmSourcesComponent
]
})
export class DraftGenerationComponent extends DataLoadingComponent implements OnInit {
Expand Down

0 comments on commit 71f5d4b

Please sign in to comment.