Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SF-3081 Show draft queued immediately when job started #2853

Merged
merged 3 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,18 @@ <h4 class="explanation">
}
<div class="button-strip">
<button mat-stroked-button matStepperPrevious>{{ t("back") }}</button>
<button mat-flat-button (click)="tryAdvanceStep()" color="primary">
<button
mat-flat-button
(click)="tryAdvanceStep()"
color="primary"
class="advance-button"
[disabled]="isStepsCompleted"
>
{{ featureFlags.allowFastTraining.enabled || trainingDataFilesAvailable ? t("next") : t("generate_draft") }}
</button>
@if (isStepsCompleted) {
<mat-spinner diameter="24"></mat-spinner>
}
</div>
</mat-step>
@if (trainingDataFilesAvailable) {
Expand All @@ -134,9 +143,18 @@ <h1 class="mat-headline-4">{{ t("choose_additional_training_data_files") }}</h1>
></app-training-data-multi-select>
<div class="button-strip">
<button mat-stroked-button matStepperPrevious>{{ t("back") }}</button>
<button mat-flat-button (click)="tryAdvanceStep()" color="primary">
<button
mat-flat-button
(click)="tryAdvanceStep()"
color="primary"
class="advance-button"
[disabled]="isStepsCompleted"
>
{{ featureFlags.allowFastTraining.enabled ? t("next") : t("generate_draft") }}
</button>
@if (isStepsCompleted) {
<mat-spinner diameter="24"></mat-spinner>
}
</div>
</mat-step>
}
Expand All @@ -154,9 +172,18 @@ <h1 class="mat-headline-4">{{ t("configure_advanced_settings") }}</h1>
}
<div class="button-strip">
<button mat-stroked-button matStepperPrevious>{{ t("back") }}</button>
<button mat-flat-button (click)="tryAdvanceStep()" color="primary">
<button
mat-flat-button
(click)="tryAdvanceStep()"
color="primary"
class="advance-button"
[disabled]="isStepsCompleted"
>
{{ t("generate_draft") }}
</button>
@if (isStepsCompleted) {
<mat-spinner diameter="24"></mat-spinner>
}
</div>
</mat-step>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ h1 {
margin-top: 20px;
display: flex;
justify-content: flex-start;
align-items: center;
gap: 8px;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,19 +227,24 @@ describe('DraftGenerationStepsComponent', () => {
component.selectedTrainingDataIds = trainingDataFiles;

spyOn(component.done, 'emit');

expect(component.isStepsCompleted).toBe(false);
// Advance to the next step when at last step should emit books result
fixture.detectChanges();
component.tryAdvanceStep();
fixture.detectChanges();
const generateDraftButton: HTMLElement = fixture.nativeElement.querySelector('.advance-button');
expect(generateDraftButton['disabled']).toBe(false);
component.tryAdvanceStep();
fixture.detectChanges();

expect(component.done.emit).toHaveBeenCalledWith({
translationBooks,
trainingDataFiles,
trainingBooks: trainingBooks.filter(book => !translationBooks.includes(book)),
fastTraining: false
} as DraftGenerationStepsResult);
expect(component.isStepsCompleted).toBe(true);
expect(generateDraftButton['disabled']).toBe(true);
});

it('should emit the correct selected books when bookSelect is called', fakeAsync(() => {
Expand Down Expand Up @@ -325,14 +330,18 @@ describe('DraftGenerationStepsComponent', () => {

// Click next on the final step to generate the draft
fixture.detectChanges();
const generateDraftButton: HTMLElement = fixture.nativeElement.querySelector('.advance-button');
expect(generateDraftButton['disabled']).toBe(false);
component.tryAdvanceStep();
fixture.detectChanges();

expect(component.done.emit).toHaveBeenCalledWith({
trainingBooks,
trainingDataFiles,
translationBooks,
fastTraining: true
} as DraftGenerationStepsResult);
expect(generateDraftButton['disabled']).toBe(true);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export class DraftGenerationStepsComponent extends SubscriptionDisposable implem

expandUnusableTranslateBooks = false;
expandUnusableTrainingBooks = false;
isStepsCompleted = false;

private trainingDataQuery?: RealtimeQuery<TrainingDataDoc>;
private trainingDataSub?: Subscription;
Expand Down Expand Up @@ -246,6 +247,7 @@ export class DraftGenerationStepsComponent extends SubscriptionDisposable implem
if (this.stepper.selected !== this.stepper.steps.last) {
this.stepper.next();
} else {
this.isStepsCompleted = true;
this.done.emit({
trainingBooks: this.userSelectedTrainingBooks,
trainingDataFiles: this.selectedTrainingDataIds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-
import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data';
import { TextInfoPermission } from 'realtime-server/lib/esm/scriptureforge/models/text-info-permission';
import { ProjectType } from 'realtime-server/lib/esm/scriptureforge/models/translate-config';
import { BehaviorSubject, EMPTY, of, throwError } from 'rxjs';
import { BehaviorSubject, EMPTY, Subject, of, throwError } from 'rxjs';
import { instance, mock, verify, when } from 'ts-mockito';
import { ActivatedProjectService } from 'xforge-common/activated-project.service';
import { AuthService } from 'xforge-common/auth.service';
Expand Down Expand Up @@ -79,6 +79,7 @@ describe('DraftGenerationComponent', () => {

class TestEnvironment {
readonly testOnlineStatusService: TestOnlineStatusService;
readonly startedOrActiveBuild$ = new Subject<BuildDto>();
component!: DraftGenerationComponent;
fixture!: ComponentFixture<DraftGenerationComponent>;

Expand Down Expand Up @@ -155,6 +156,7 @@ describe('DraftGenerationComponent', () => {

mockI18nService.getLanguageDisplayName.and.returnValue('English');
mockPreTranslationSignupUrlService.generateSignupUrl.and.returnValue(Promise.resolve(''));
mockDraftGenerationService.startBuildOrGetActiveBuild.and.returnValue(this.startedOrActiveBuild$);
mockDraftGenerationService.getBuildProgress.and.returnValue(of(buildDto));
mockDraftGenerationService.pollBuildProgress.and.returnValue(of(buildDto));
mockDraftGenerationService.getLastCompletedBuild.and.returnValue(of(buildDto));
Expand Down Expand Up @@ -1742,32 +1744,32 @@ describe('DraftGenerationComponent', () => {

describe('startBuild', () => {
it('should start the draft build', () => {
let env = new TestEnvironment(() => {
mockDraftGenerationService.startBuildOrGetActiveBuild.and.returnValue(of(buildDto));
});
let env = new TestEnvironment();

env.component.currentPage = 'steps';
env.component.startBuild({
trainingBooks: [],
trainingDataFiles: [],
translationBooks: [],
fastTraining: false,
projectId: projectId
});
env.fixture.detectChanges();
expect(env.component.currentPage).toBe('steps');
expect(mockDraftGenerationService.startBuildOrGetActiveBuild).toHaveBeenCalledWith({
projectId: projectId,
trainingBooks: [],
trainingDataFiles: [],
translationBooks: [],
fastTraining: false
});
env.startedOrActiveBuild$.next(buildDto);
env.fixture.detectChanges();
expect(env.component.currentPage).toBe('initial');
});

it('should not attempt "cancel dialog" close for queued build', () => {
let env = new TestEnvironment(() => {
mockDraftGenerationService.startBuildOrGetActiveBuild.and.returnValue(
of({ ...buildDto, state: BuildStates.Queued })
);
});
let env = new TestEnvironment();

const mockDialogRef: MatDialogRef<any> = mock(MatDialogRef);
env.component.cancelDialogRef = instance(mockDialogRef);
Expand All @@ -1779,6 +1781,7 @@ describe('DraftGenerationComponent', () => {
fastTraining: false,
projectId: projectId
});
env.startedOrActiveBuild$.next({ ...buildDto, state: BuildStates.Queued });
expect(mockDraftGenerationService.startBuildOrGetActiveBuild).toHaveBeenCalledWith({
projectId: projectId,
trainingBooks: [],
Expand All @@ -1791,11 +1794,7 @@ describe('DraftGenerationComponent', () => {
});

it('should not attempt "cancel dialog" close for pending build', () => {
let env = new TestEnvironment(() => {
mockDraftGenerationService.startBuildOrGetActiveBuild.and.returnValue(
of({ ...buildDto, state: BuildStates.Pending })
);
});
let env = new TestEnvironment();

const mockDialogRef: MatDialogRef<any> = mock(MatDialogRef);
env.component.cancelDialogRef = instance(mockDialogRef);
Expand All @@ -1807,6 +1806,7 @@ describe('DraftGenerationComponent', () => {
fastTraining: false,
projectId: projectId
});
env.startedOrActiveBuild$.next({ ...buildDto, state: BuildStates.Pending });
expect(mockDraftGenerationService.startBuildOrGetActiveBuild).toHaveBeenCalledWith({
projectId: projectId,
trainingBooks: [],
Expand All @@ -1819,11 +1819,7 @@ describe('DraftGenerationComponent', () => {
});

it('should not attempt "cancel dialog" close for active build', () => {
let env = new TestEnvironment(() => {
mockDraftGenerationService.startBuildOrGetActiveBuild.and.returnValue(
of({ ...buildDto, state: BuildStates.Active })
);
});
let env = new TestEnvironment();

const mockDialogRef: MatDialogRef<any> = mock(MatDialogRef);
env.component.cancelDialogRef = instance(mockDialogRef);
Expand All @@ -1835,6 +1831,7 @@ describe('DraftGenerationComponent', () => {
fastTraining: false,
projectId: projectId
});
env.startedOrActiveBuild$.next({ ...buildDto, state: BuildStates.Active });
expect(mockDraftGenerationService.startBuildOrGetActiveBuild).toHaveBeenCalledWith({
projectId: projectId,
trainingBooks: [],
Expand All @@ -1847,11 +1844,7 @@ describe('DraftGenerationComponent', () => {
});

it('should attempt "cancel dialog" close for cancelled build', () => {
let env = new TestEnvironment(() => {
mockDraftGenerationService.startBuildOrGetActiveBuild.and.returnValue(
of({ ...buildDto, state: BuildStates.Canceled })
);
});
let env = new TestEnvironment();

const mockDialogRef: MatDialogRef<any> = mock(MatDialogRef);
when(mockDialogRef.getState()).thenReturn(MatDialogState.OPEN);
Expand All @@ -1864,6 +1857,7 @@ describe('DraftGenerationComponent', () => {
fastTraining: false,
projectId: projectId
});
env.startedOrActiveBuild$.next({ ...buildDto, state: BuildStates.Canceled });
expect(mockDraftGenerationService.startBuildOrGetActiveBuild).toHaveBeenCalledWith({
projectId: projectId,
trainingBooks: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ export class DraftGenerationComponent extends DataLoadingComponent implements On
}

onPreGenerationStepsComplete(result: DraftGenerationStepsResult): void {
this.currentPage = 'initial';
this.startBuild({
projectId: this.activatedProject.projectId!,
trainingBooks: result.trainingBooks,
Expand Down Expand Up @@ -501,6 +500,7 @@ export class DraftGenerationComponent extends DataLoadingComponent implements On
this.jobSubscription = this.subscribe(
this.draftGenerationService.startBuildOrGetActiveBuild(buildConfig).pipe(
tap((job?: BuildDto) => {
this.currentPage = 'initial';
// Handle automatic closing of dialog if job finishes while cancel dialog is open
if (!this.canCancel(job)) {
if (this.cancelDialogRef?.getState() === MatDialogState.OPEN) {
Expand Down
Loading