Skip to content
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 @@ -202,29 +202,6 @@ <h1>
</a>
</div>
</app-notice>
@if (!featureFlags.newDraftHistory.enabled) {
<section data-test-id="technical-details">
<div>
<p class="error-text">Technical details:</p>
<div>
<div><strong>Message:</strong> {{ draftJob?.message ?? "unknown" }}</div>
<div>
<strong>Translation Engine Id:</strong>
{{ draftJob?.additionalInfo?.translationEngineId ?? "unknown" }}
</div>
<div><strong>Build Id:</strong> {{ draftJob?.additionalInfo?.buildId ?? "unknown" }}</div>
<div>
<strong>Corpora Ids:</strong>
{{ draftJob?.additionalInfo?.corporaIds?.join(", ") ?? "unknown" }}
</div>
<div>
<strong>Parallel Corpora Ids:</strong>
{{ draftJob?.additionalInfo?.parallelCorporaIds?.join(", ") ?? "unknown" }}
</div>
</div>
</div>
</section>
}
}
@if (!isDraftInProgress(draftJob) && !hasAnyCompletedBuild) {
<section class="action-button-strip">
Expand All @@ -250,7 +227,7 @@ <h1>
}
@if (isPreviewSupported) {
@if (draftJob != null) {
@if (isDraftInProgress(draftJob) && featureFlags.newDraftHistory.enabled) {
@if (isDraftInProgress(draftJob)) {
<mat-card class="draft-progress-card">
<mat-card-header>
<mat-card-title>
Expand Down Expand Up @@ -290,86 +267,6 @@ <h1>
}
</mat-card-content>
</mat-card>
} @else if (!featureFlags.newDraftHistory.enabled) {
@if (isDraftQueued(draftJob)) {
<section>
@if (isSyncing()) {
<h3>{{ t("draft_syncing") }}</h3>
<p>{{ t("draft_syncing_detail") }}</p>
} @else {
<h3>{{ t("draft_queued_header") }}</h3>
@if (!hasDraftQueueDepth(draftJob)) {
<p>{{ t("draft_queued_detail") }}</p>
} @else {
<p>
{{ t("draft_queued_detail_multiple", { count: draftJob.queueDepth }) }}
</p>
}
}
<app-working-animated-indicator></app-working-animated-indicator>
<div class="button-strip">
@if (canCancel(draftJob)) {
<button mat-flat-button color="primary" (click)="cancel()">
<mat-icon>close</mat-icon>
{{ t("cancel_generation_button") }}
</button>
}
</div>
</section>
} @else if (isDraftActive(draftJob)) {
<section class="progress-active">
<h3>{{ t("draft_active_header") }}</h3>
<div class="progress-text">
<p>{{ t("draft_active_detail", { count: draftDurationHours | l10nNumber }) }}</p>
</div>
<circle-progress [percent]="draftJob.percentCompleted * 100"></circle-progress>
<div class="button-strip">
@if (canCancel(draftJob)) {
<button mat-flat-button color="primary" (click)="cancel()">
<mat-icon>close</mat-icon>
{{ t("cancel_generation_button") }}
</button>
}
</div>
</section>
} @else if (isDraftFinishing(draftJob)) {
<section>
<h3>{{ t("draft_finishing_header") }}</h3>
<div class="progress-text">
<p>{{ t("draft_finishing_detail") }}</p>
</div>
<app-working-animated-indicator></app-working-animated-indicator>
</section>
}
@if (isDraftComplete(draftJob) || hasAnyCompletedBuild) {
<section class="draft-complete">
<mat-card class="preview-card">
<mat-card-header>
<mat-card-title>
{{ isDraftComplete(draftJob) ? t("draft_is_ready") : t("preview_last_draft_header") }}
</mat-card-title>
</mat-card-header>
<mat-card-content>
@if (isDraftFaulted(draftJob)) {
<p>{{ t("preview_last_draft_detail") }}</p>
}
<p>{{ t("click_book_to_preview") }}</p>
<app-draft-preview-books></app-draft-preview-books>
</mat-card-content>
<mat-card-actions>
@if (hasDraftBooksAvailable) {
<app-draft-download-button [build]="lastCompletedBuild" />
@if (featureFlags.usfmFormat.enabled) {
<button mat-button [routerLink]="draftOptionsService.formattingOptionsPath">
<mat-icon>settings</mat-icon>
{{ t("format_draft") }}
</button>
}
}
</mat-card-actions>
</mat-card>
</section>
}
}
}
}
Expand All @@ -393,12 +290,7 @@ <h3>{{ t("draft_finishing_header") }}</h3>
hasAnyCompletedBuild &&
isSourcesConfigurationComplete
) {
<button
mat-flat-button
color="primary"
type="button"
(click)="generateDraftClicked({ withConfirm: !featureFlags.newDraftHistory.enabled })"
>
<button mat-flat-button color="primary" type="button" (click)="generateDraftClicked()">
<mat-icon>add</mat-icon> {{ t("generate_new_draft") }}
</button>
@if (hasConfigureSourcePermission) {
Expand All @@ -422,11 +314,9 @@ <h3>{{ t("draft_finishing_header") }}</h3>
}
</section>

@if (featureFlags.newDraftHistory.enabled) {
<app-draft-history-list [style.display]="isOnline ? 'flex' : 'none'"></app-draft-history-list>
@if (isOnline && isServalAdmin()) {
<h2>Further information</h2>
}
<app-draft-history-list [style.display]="isOnline ? 'flex' : 'none'"></app-draft-history-list>
@if (isOnline && isServalAdmin()) {
<h2>Further information</h2>
}

@if (canShowAdditionalInfo(draftJob)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,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, Subject, throwError } from 'rxjs';
import { EMPTY, of, Subject, 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 All @@ -25,6 +25,7 @@ import { getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { SFProjectProfileDoc } from '../../core/models/sf-project-profile-doc';
import { TrainingDataDoc } from '../../core/models/training-data-doc';
import { ProjectNotificationService } from '../../core/project-notification.service';
import { SFProjectService } from '../../core/sf-project.service';
import { TextDocService } from '../../core/text-doc.service';
import { BuildDto } from '../../machine-api/build-dto';
Expand All @@ -50,6 +51,7 @@ describe('DraftGenerationComponent', () => {
let mockTrainingDataService: jasmine.SpyObj<TrainingDataService>;
let mockFeatureFlagService: jasmine.SpyObj<FeatureFlagService>;
let mockSFProjectService: jasmine.SpyObj<SFProjectService>;
let mockProjectNotificationService: jasmine.SpyObj<ProjectNotificationService>;

const buildDto: BuildDto = {
id: 'testId',
Expand Down Expand Up @@ -99,7 +101,8 @@ describe('DraftGenerationComponent', () => {
{ provide: OnlineStatusService, useClass: TestOnlineStatusService },
{ provide: TrainingDataService, useValue: mockTrainingDataService },
{ provide: ProgressService, useValue: undefined },
{ provide: FeatureFlagService, useValue: mockFeatureFlagService }
{ provide: FeatureFlagService, useValue: mockFeatureFlagService },
{ provide: ProjectNotificationService, useValue: mockProjectNotificationService }
]
});

Expand Down Expand Up @@ -200,7 +203,7 @@ describe('DraftGenerationComponent', () => {
}
})
} as SFProjectProfileDoc;
mockAuthService = jasmine.createSpyObj<AuthService>(['requestParatextCredentialUpdate'], {
mockAuthService = jasmine.createSpyObj<AuthService>(['requestParatextCredentialUpdate', 'getAccessToken'], {
currentUserId,
currentUserRoles: [SystemRole.User]
});
Expand All @@ -218,6 +221,13 @@ describe('DraftGenerationComponent', () => {
mockSFProjectService = jasmine.createSpyObj<SFProjectService>(['hasDraft']);
mockSFProjectService.hasDraft.withArgs(matchThisProject).and.returnValue(preTranslate);
mockSFProjectService.hasDraft.withArgs(matchThisProject, jasmine.anything()).and.returnValue(preTranslate);
mockProjectNotificationService = jasmine.createSpyObj<ProjectNotificationService>([
'setNotifyBuildProgressHandler',
'start',
'stop',
'removeNotifyBuildProgressHandler',
'subscribeToProject'
]);
}

get configureDraftButton(): HTMLElement | null {
Expand Down Expand Up @@ -1331,15 +1341,6 @@ describe('DraftGenerationComponent', () => {
});

describe('isDraftFaulted', () => {
it('should return true if the draft build is faulted', () => {
const env = new TestEnvironment();
env.component.draftJob = { ...buildDto, state: BuildStates.Faulted };
env.fixture.detectChanges();
expect(env.component.isDraftFaulted({ state: BuildStates.Faulted } as BuildDto)).toBe(true);
expect(env.getElementByTestId('warning-generation-failed')).not.toBeNull();
expect(env.getElementByTestId('technical-details')).not.toBeNull();
});

it('should return false if the draft build is not faulted', () => {
const env = new TestEnvironment();
expect(env.component.isDraftFaulted({ state: BuildStates.Active } as BuildDto)).toBe(false);
Expand Down Expand Up @@ -1368,107 +1369,4 @@ describe('DraftGenerationComponent', () => {
expect(env.component.isDraftInProgress({ state: BuildStates.Faulted } as BuildDto)).toBe(false);
});
});

describe('download draft button', () => {
it('button should display if there are draft books available', () => {
const env = new TestEnvironment();
env.component.draftJob = { ...buildDto, state: BuildStates.Faulted };
env.component.hasDraftBooksAvailable = true;
env.fixture.detectChanges();
expect(env.downloadButton).not.toBeNull();
});

it('button should display if there is a completed build while a build is faulted', () => {
const env = new TestEnvironment();
env.component.draftJob = { ...buildDto, state: BuildStates.Faulted };
env.component.lastCompletedBuild = { ...buildDto, state: BuildStates.Completed };
env.component.hasDraftBooksAvailable = true;
env.fixture.detectChanges();

expect(env.downloadButton).not.toBeNull();
});

it('button should display if there is a completed build while a build is queued', () => {
const env = new TestEnvironment();
env.setup();
env.component.draftJob = { ...buildDto, state: BuildStates.Queued };
env.component.lastCompletedBuild = { ...buildDto, state: BuildStates.Completed };
env.component.hasDraftBooksAvailable = true;
env.fixture.detectChanges();

expect(env.downloadButton).not.toBeNull();
});

it('button should not display if there is no completed build while a build is faulted', () => {
const env = new TestEnvironment();
env.component.draftJob = { ...buildDto, state: BuildStates.Faulted };
env.component.lastCompletedBuild = undefined;
env.component.hasDraftBooksAvailable = true;
env.fixture.detectChanges();

expect(env.downloadButton).toBeNull();
});

it('button should display if the project has a draft complete', fakeAsync(() => {
// Setup the project and subject
const projectDoc: SFProjectProfileDoc = {
data: createTestProjectProfile({
translateConfig: {
preTranslate: true,
projectType: ProjectType.Standard,
source: {
projectRef: 'testSourceProjectId',
writingSystem: {
tag: 'es'
}
}
},
texts: [
{
bookNum: 1,
chapters: [{ number: 1 }],
permissions: { user01: TextInfoPermission.Write }
}
]
})
} as SFProjectProfileDoc;
const projectSubject = new BehaviorSubject<SFProjectProfileDoc>(projectDoc);
const projectObservable = projectSubject.asObservable();
const buildSubject = new BehaviorSubject<BuildDto>(buildDto);
const buildObservable = buildSubject.asObservable();

// Setup the initial environment
const env = new TestEnvironment(() => {
mockActivatedProjectService = jasmine.createSpyObj('ActivatedProjectService', [], {
projectDoc: projectDoc,
projectId: projectId,
projectId$: of(projectId),
projectDoc$: projectObservable,
changes$: projectObservable
});
mockDraftGenerationService.getBuildProgress.and.returnValue(buildObservable);
mockDraftGenerationService.pollBuildProgress.and.returnValue(buildObservable);
mockDraftGenerationService.getLastCompletedBuild.and.returnValue(buildObservable);
mockSFProjectService.hasDraft.and.returnValue(false);
});
tick(500);
env.fixture.detectChanges();

// Verify the button is not visible
expect(env.downloadButton).toBeNull();

// Update the has draft flag for the project
mockSFProjectService.hasDraft.and.returnValue(true);
projectDoc.data!.translateConfig.draftConfig.lastSelectedTranslationScriptureRanges = [
{ projectId: 'testSourceProjectId', scriptureRange: 'GEN' }
];
projectSubject.next(projectDoc);
buildSubject.next({ ...buildDto, state: BuildStates.Completed });
tick(500);
env.fixture.detectChanges();

// Verify the button is visible
expect(env.downloadButton).not.toBeNull();
}));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ export class DraftGenerationComponent extends DataLoadingComponent implements On
);
}

async generateDraftClicked({ withConfirm = false } = {}): Promise<void> {
async generateDraftClicked(): Promise<void> {
if (this.formattingOptionsRequired) {
const dialogRef = this.dialogService.openGenericDialog({
title: this.i18n.translate('draft_generation.choose_formatting_options'),
Expand All @@ -359,24 +359,6 @@ export class DraftGenerationComponent extends DataLoadingComponent implements On
if (await dialogRef.result) await this.router.navigate(this.draftOptionsService.formattingOptionsPath);
return;
}
if (withConfirm) {
const isConfirmed: boolean | undefined = await this.dialogService.openGenericDialog({
title: this.i18n.translate('draft_generation.dialog_confirm_draft_regeneration_title'),
message: this.i18n.translate('draft_generation.dialog_confirm_draft_regeneration_message'),
options: [
{ value: false, label: this.i18n.translate('draft_generation.dialog_confirm_draft_regeneration_no') },
{
value: true,
label: this.i18n.translate('draft_generation.dialog_confirm_draft_regeneration_yes'),
highlight: true
}
]
}).result;

if (!isConfirmed) {
return;
}
}

// Display pre-generation steps
this.currentPage = 'steps';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/te
import { SFProjectProfileDoc } from '../../../core/models/sf-project-profile-doc';
import { SF_TYPE_REGISTRY } from '../../../core/models/sf-type-registry';
import { Revision } from '../../../core/paratext.service';
import { ProjectNotificationService } from '../../../core/project-notification.service';
import { SFProjectService } from '../../../core/sf-project.service';
import { BuildDto } from '../../../machine-api/build-dto';
import { BuildStates } from '../../../machine-api/build-states';
Expand All @@ -47,6 +48,7 @@ const mockNoticeService = mock(NoticeService);
const mockErrorReportingService = mock(ErrorReportingService);
const mockFeatureFlagService = mock(FeatureFlagService);
const mockSFProjectService = mock(SFProjectService);
const mockProjectNotificationService = mock(ProjectNotificationService);

describe('EditorDraftComponent', () => {
let fixture: ComponentFixture<EditorDraftComponent>;
Expand Down Expand Up @@ -78,7 +80,8 @@ describe('EditorDraftComponent', () => {
{ provide: NoticeService, useMock: mockNoticeService },
{ provide: ErrorReportingService, useMock: mockErrorReportingService },
{ provide: FeatureFlagService, useMock: mockFeatureFlagService },
{ provide: SFProjectService, useMock: mockSFProjectService }
{ provide: SFProjectService, useMock: mockSFProjectService },
{ provide: ProjectNotificationService, useMock: mockProjectNotificationService }
]
}));

Expand Down
Loading
Loading