Skip to content

Commit 78427d7

Browse files
authored
SF-3507 Improve step order on configure sources page (#3370)
1 parent 8dcc297 commit 78427d7

File tree

3 files changed

+58
-72
lines changed

3 files changed

+58
-72
lines changed

src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-sources/draft-sources.component.html

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,64 @@ <h1>{{ t("configure_draft_sources") }}</h1>
55
<div class="step" [class.active]="step === 1">
66
<div class="step-header" matRipple (click)="goToStep(1)">
77
<div class="step-header-description">
8-
<span class="step-title">{{ t("draft_source") }}</span>
9-
<span class="step-subtitle">{{ sourceSubtitle }}</span>
8+
<span class="step-title">{{ t("reference_projects") }}</span>
9+
<span class="step-subtitle">{{ referencesSubtitle }}</span>
1010
</div>
1111
<mat-icon>{{ step === 1 ? "expand_less" : "expand_more" }}</mat-icon>
1212
</div>
1313
<div class="step-body">
14-
<p>{{ t("select_project_to_translate") }}</p>
15-
@for (source of draftingSources; track $index) {
14+
<p>{{ t("select_primary_reference") }}</p>
15+
@for (source of trainingSources; track $index) {
1616
<app-project-select
1717
[isDisabled]="loading || !appOnline"
1818
[projects]="projects"
1919
[resources]="resources"
2020
[nonSelectableProjects]="nonSelectableProjects"
2121
[value]="source?.paratextId"
22-
[hiddenParatextIds]="getHiddenParatextIds(draftingSources, source?.paratextId)"
23-
(valueChange)="sourceSelected(draftingSources, $index, $event)"
22+
[hiddenParatextIds]="getHiddenParatextIds(trainingSources, source?.paratextId)"
23+
(valueChange)="sourceSelected(trainingSources, $index, $event)"
2424
[placeholder]="projectPlaceholder(source)"
2525
></app-project-select>
2626
}
2727

28+
@if (allowAddingATrainingSource) {
29+
<p>{{ t("some_projects_use_back_translation") }}</p>
30+
<button
31+
mat-button
32+
(click)="trainingSources.push(undefined); $event.preventDefault()"
33+
class="add-another-project"
34+
>
35+
<mat-icon>add</mat-icon> {{ t("add_another_reference_project") }}
36+
</button>
37+
}
38+
2839
<ng-container *ngTemplateOutlet="navigationButtons"></ng-container>
2940
</div>
3041
</div>
3142

3243
<div class="step" [class.active]="step === 2">
3344
<div class="step-header" matRipple (click)="goToStep(2)">
3445
<div class="step-header-description">
35-
<span class="step-title">{{ t("reference_projects") }}</span>
36-
<span class="step-subtitle">{{ referencesSubtitle }}</span>
46+
<span class="step-title">{{ t("draft_source") }}</span>
47+
<span class="step-subtitle">{{ sourceSubtitle }}</span>
3748
</div>
3849
<mat-icon>{{ step === 2 ? "expand_less" : "expand_more" }}</mat-icon>
3950
</div>
4051
<div class="step-body">
41-
<p>
42-
{{ t("select_reference_project_considering_back_translation") }}
43-
44-
@if (sourceLanguageDisplayName) {
45-
@for (portion of i18n.interpolateVariables("draft_sources.same_language_as_given_language"); track $index) {
46-
@if (portion.id === "sourceLanguageDisplayName") {
47-
<strong>{{ sourceLanguageDisplayName }}</strong>
48-
}
49-
<!-- prettier-ignore -->
50-
@else {{{ portion.text }}}
51-
}
52-
} @else {
53-
{{ t("same_language_as_source") }}
54-
}
55-
</p>
56-
@for (source of trainingSources; track $index) {
52+
<p>{{ t("select_project_to_translate") }}</p>
53+
@for (source of draftingSources; track $index) {
5754
<app-project-select
5855
[isDisabled]="loading || !appOnline"
5956
[projects]="projects"
6057
[resources]="resources"
6158
[nonSelectableProjects]="nonSelectableProjects"
6259
[value]="source?.paratextId"
63-
[hiddenParatextIds]="getHiddenParatextIds(trainingSources, source?.paratextId)"
64-
(valueChange)="sourceSelected(trainingSources, $index, $event)"
60+
[hiddenParatextIds]="getHiddenParatextIds(draftingSources, source?.paratextId)"
61+
(valueChange)="sourceSelected(draftingSources, $index, $event)"
6562
[placeholder]="projectPlaceholder(source)"
6663
></app-project-select>
6764
}
6865

69-
@if (allowAddingATrainingSource) {
70-
<button
71-
mat-button
72-
(click)="trainingSources.push(undefined); $event.preventDefault()"
73-
class="add-another-project"
74-
>
75-
<mat-icon>add</mat-icon> {{ t("add_another_reference_project") }}
76-
</button>
77-
}
78-
7966
<ng-container *ngTemplateOutlet="navigationButtons"></ng-container>
8067
</div>
8168
</div>
@@ -131,7 +118,7 @@ <h1>{{ t("configure_draft_sources") }}</h1>
131118
<mat-card-title>{{ t("training_language_model") }}</mat-card-title>
132119
</mat-card-header>
133120
<mat-card-content class="training-data">
134-
<div class="sources" (click)="goToStep(2)" [class.active]="step === 2" matRipple>
121+
<div class="sources" (click)="goToStep(1)" [class.active]="step === 1" matRipple>
135122
<h3>{{ t("overview_reference") }} {{ parentheses(referenceLanguageDisplayName) }}</h3>
136123
@for (project of trainingSources; track $index) {
137124
@if (project == null) {
@@ -163,7 +150,7 @@ <h3>{{ t("overview_translated_project") }} {{ parentheses(targetLanguageDisplayN
163150
<mat-card-title>{{ t("generate_draft_from_language_model") }}</mat-card-title>
164151
</mat-card-header>
165152
<mat-card-content>
166-
<div class="translation-data" (click)="goToStep(1)" [class.active]="step === 1" matRipple>
153+
<div class="translation-data" (click)="goToStep(2)" [class.active]="step === 2" matRipple>
167154
<h3>{{ t("overview_source") }} {{ parentheses(sourceLanguageDisplayName) }}</h3>
168155
@for (project of draftingSources; track $index) {
169156
@if (project == null) {

src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-sources/draft-sources.stories.ts

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -226,20 +226,11 @@ export const SelectAllAndSave: Story = {
226226
...Template,
227227
play: async ({ canvasElement }) => {
228228
const canvas = within(canvasElement);
229-
// Step 1: Draft source
230-
// Select an English source and expect to see a warning that source and target languages are the same
229+
230+
// Step 1: Reference projects
231+
// Select an English reference and expect to see a warning that source and target languages are the same
231232
await selectSource(canvasElement, 'P_EN');
232233
expect(await warning(canvasElement)).toContain('Source and target languages are both English');
233-
// Switch to a Chinese source and expect the warning to disappear
234-
await clearSource(canvasElement);
235-
await selectSource(canvasElement, 'P_ZH');
236-
expect(await warning(canvasElement)).toContain('Incorrect language codes will dramatically reduce draft quality.');
237-
238-
// Step 2: Reference projects
239-
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
240-
// Select a English reference project and expect to see an error that sources are in different languages
241-
await selectSource(canvasElement, 'R_EN');
242-
expect(await warning(canvasElement)).toContain('All source and reference projects must be in the same language');
243234
// Switch to a Chinese reference project and expect the error to disappear
244235
await clearSource(canvasElement);
245236
await selectSource(canvasElement, 'R_ZH');
@@ -248,11 +239,21 @@ export const SelectAllAndSave: Story = {
248239
const additionalReferenceButton = canvas.getByRole('button', { name: /Add another reference project/ });
249240
await userEvent.click(additionalReferenceButton);
250241
await selectSource(canvasElement, 'P_ZH', 1);
242+
243+
// Step 2: Draft source
244+
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
245+
// Select an English source project and expect to see an error that sources are in different languages
246+
await selectSource(canvasElement, 'R_EN');
247+
expect(await warning(canvasElement)).toContain('All source and reference projects must be in the same language');
248+
// Switch to a Chinese source project and expect the error to disappear
249+
await clearSource(canvasElement);
250+
await selectSource(canvasElement, 'P_ZH');
251+
expect(await warning(canvasElement)).toContain('Incorrect language codes will dramatically reduce draft quality.');
251252
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
252253

253-
// Verify general information shown is correct
254+
// Verify general information shown is correct
254255
const stepSubTitles = Array.from(canvasElement.querySelectorAll('.step-subtitle')).map(e => e.textContent);
255-
expect(stepSubTitles).toEqual(['P_ZH', 'R_ZH and P_ZH', 'P1']);
256+
expect(stepSubTitles).toEqual(['R_ZH and P_ZH', 'P_ZH', 'P1']);
256257
const overviewHeadings = Array.from(canvasElement.querySelector('.overview')!.querySelectorAll('h3')).map(
257258
e => e.textContent
258259
);
@@ -299,8 +300,8 @@ export const NavigateAllSteps: Story = {
299300
...PreExistingSettings,
300301
play: async ({ canvasElement }) => {
301302
const stepTitles = {
302-
1: { stepper: 'Draft source', overview: 'Source' },
303-
2: { stepper: 'Reference projects', overview: 'Reference' },
303+
1: { stepper: 'Reference projects', overview: 'Reference' },
304+
2: { stepper: 'Draft source', overview: 'Source' },
304305
3: { stepper: 'Target language data', overview: 'Translated project' }
305306
};
306307

@@ -340,28 +341,28 @@ export const NavigateAllSteps: Story = {
340341
}
341342
};
342343

343-
export const CannotSaveWithoutDraftingSource = {
344+
export const CannotSaveWithoutReferenceProject = {
344345
...PreExistingSettings,
345346
play: async ({ canvasElement }) => {
346347
const canvas = within(canvasElement);
348+
expect(canvas.getAllByRole('combobox').length).toBe(2);
347349
await clearSource(canvasElement);
350+
expect(canvas.getAllByRole('combobox').length).toBe(2);
351+
await clearSource(canvasElement, 1);
352+
expect(canvas.getAllByRole('combobox').length).toBe(2);
348353
await userEvent.click(canvas.getByRole('button', { name: /Save & sync/ }));
349-
canvas.getByRole('heading', { name: 'Please select at least one source project before saving.' });
354+
canvas.getByRole('heading', { name: 'Please select at least one reference project before saving.' });
350355
}
351356
};
352357

353-
export const CannotSaveWithoutReferenceProject = {
358+
export const CannotSaveWithoutDraftingSource = {
354359
...PreExistingSettings,
355360
play: async ({ canvasElement }) => {
356361
const canvas = within(canvasElement);
357362
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
358-
expect(canvas.getAllByRole('combobox').length).toBe(2);
359363
await clearSource(canvasElement);
360-
expect(canvas.getAllByRole('combobox').length).toBe(2);
361-
await clearSource(canvasElement, 1);
362-
expect(canvas.getAllByRole('combobox').length).toBe(2);
363364
await userEvent.click(canvas.getByRole('button', { name: /Save & sync/ }));
364-
canvas.getByRole('heading', { name: 'Please select at least one reference project before saving.' });
365+
canvas.getByRole('heading', { name: 'Please select at least one source project before saving.' });
365366
}
366367
};
367368

@@ -371,7 +372,6 @@ export const CannotSelectSameProjectTwiceInOneStep: Story = {
371372
const canvas = within(canvasElement);
372373

373374
// Select English project
374-
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
375375
await selectSource(canvasElement, 'P_EN');
376376
await userEvent.click(canvas.getByRole('button', { name: /Add another reference project/ }));
377377
// Wait for the project select menu to fully close
@@ -395,13 +395,13 @@ export const CannotSelectTargetAsASource: Story = {
395395
play: async ({ canvasElement }) => {
396396
const canvas = within(canvasElement);
397397

398-
await userEvent.click(canvas.getByRole('combobox'));
398+
await userEvent.click(canvas.getAllByRole('combobox')[1]);
399399
// Make sure current target Russian project can't be selected
400400
expect(canvas.queryByRole('option', { name: /P_ES/ })).not.toBeNull();
401401
expect(canvas.queryByRole('option', { name: /P_RU/ })).toBeNull();
402402
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
403403

404-
await userEvent.click(canvas.getAllByRole('combobox')[0]);
404+
await userEvent.click(canvas.getByRole('combobox'));
405405
// Make sure current target Russian project can't be selected
406406
expect(canvas.queryAllByRole('option', { name: /P_ES/ })).not.toBeNull();
407407
expect(canvas.queryByRole('option', { name: /P_RU/ })).toBeNull();
@@ -434,12 +434,12 @@ export const CannotSaveWithMultipleSourceLanguages: Story = {
434434
const canvas = within(canvasElement);
435435

436436
// Select Portuguese along with Spanish on the source side
437-
await selectSource(canvasElement, 'P_PT');
438-
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
439437
await selectSource(canvasElement, 'R_PT');
440438
const additionalReferenceButton = canvas.getByRole('button', { name: /Add another reference project/ });
441439
await userEvent.click(additionalReferenceButton);
442440
await selectSource(canvasElement, 'P_ES', 1);
441+
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
442+
await selectSource(canvasElement, 'P_PT');
443443

444444
// Expect an error with no checkbox to confirm language codes
445445
expect(await warning(canvasElement)).toContain('All source and reference projects must be in the same language');
@@ -461,10 +461,10 @@ export const CanHandleBackTranslationProjectsWithUnknownLanguage: Story = {
461461

462462
// Select a training source that does not have a language code defined
463463
await selectSource(canvasElement, 'P_ES');
464-
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
465-
await selectSource(canvasElement, 'R_ES');
466464
await userEvent.click(canvas.getByRole('button', { name: /Add another reference project/ }));
467465
await selectSource(canvasElement, 'UNK', 1);
466+
await userEvent.click(canvas.getByRole('button', { name: /Next/ }));
467+
await selectSource(canvasElement, 'R_ES');
468468

469469
expect(await warning(canvasElement)).toContain('Incorrect language codes will dramatically reduce draft quality.');
470470
await userEvent.click(await canvas.findByRole('checkbox'));

src/SIL.XForge.Scripture/ClientApp/src/assets/i18n/non_checking_en.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,16 +319,15 @@
319319
"previous": "Previous",
320320
"project_always_used": "Your project ({{ currentProjectShortName }}) will always be used to train the language model.",
321321
"reference_projects": "Reference projects",
322-
"same_language_as_given_language": "All these should be in the same language as the draft source ({{sourceLanguageDisplayName}}).",
323-
"same_language_as_source": "All these should be in the same language as the draft source.",
324322
"save_and_sync": "Save & sync",
325323
"saving_draft_sources": "Saving draft sources",
326324
"saving": "Saving",
327325
"select_at_least_one_reference": "Please select at least one reference project before saving.",
328326
"select_at_least_one_source_and_reference": "Please select at least one source and one reference project before saving.",
329327
"select_at_least_one_source": "Please select at least one source project before saving.",
328+
"select_primary_reference": "Select your primary reference project. This is the project that you refer to most often as you are translating.",
330329
"select_project_to_translate": "Select the project to translate.",
331-
"select_reference_project_considering_back_translation": "Select projects that should be used on the source side when training the language model. Choosing a back translation often improves the model.",
330+
"some_projects_use_back_translation": "Some projects get better results by adding a back translation as another reference.",
332331
"source_side_language_codes_differ": "All source and reference projects must be in the same language. Please select different source or reference projects.",
333332
"state_connecting": "Connecting",
334333
"state_sync_failed": "There was an error syncing",

0 commit comments

Comments
 (0)