Skip to content

Commit 3fa81e3

Browse files
committed
Add project date cut off calculation and code review fixes
1 parent 1a4307e commit 3fa81e3

File tree

4 files changed

+66
-16
lines changed

4 files changed

+66
-16
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ <h2>{{ t("previously_generated_drafts") }}</h2>
1414
<app-draft-history-entry [entry]="entry" />
1515
}
1616
}
17-
@if (nonActiveBuilds.length > 0) {
17+
@if (showOlderDraftsNotSupportedWarning && nonActiveBuilds.length > 0) {
1818
<app-notice [icon]="'summarize'" class="older-drafts">{{
19-
t("older_drafts_not_available", { date: draftHistoryCutoffDate })
19+
t("older_drafts_not_available", { date: draftHistoryCutOffDateFormatted })
2020
}}</app-notice>
2121
}
2222
</ng-container>

src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-history-list/draft-history-list.component.spec.ts

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ describe('DraftHistoryListComponent', () => {
6868
const activeBuild = { state: BuildStates.Active } as BuildDto;
6969
const completedBuild = {
7070
state: BuildStates.Completed,
71-
additionalInfo: { dateGenerated: '2025-08-01T12:00:00.000Z' }
71+
additionalInfo: { dateRequested: '2025-08-01T12:00:00.000Z' }
7272
} as BuildDto;
7373
const env = new TestEnvironment([completedBuild, activeBuild]);
7474
expect(env.component.history).toEqual([activeBuild, completedBuild]);
@@ -148,13 +148,18 @@ describe('DraftHistoryListComponent', () => {
148148
it('should filter draft history and hide builds that are not saved to the database', fakeAsync(() => {
149149
const build = {
150150
state: BuildStates.Completed,
151-
additionalInfo: { dateGenerated: '2025-08-01T12:00:00.000Z' }
151+
additionalInfo: { dateRequested: '2025-08-01T12:00:00.000Z' }
152152
} as BuildDto;
153153
const olderBuild = {
154154
state: BuildStates.Completed
155155
} as BuildDto;
156156
const buildHistory = [olderBuild, build];
157157
const env = new TestEnvironment(buildHistory);
158+
159+
// Ensure that the warning shows, even though the project ID is invalid.
160+
env.component.showOlderDraftsNotSupportedWarning = true;
161+
env.fixture.detectChanges();
162+
158163
expect(env.component.history).toEqual(buildHistory);
159164
expect(env.component.savedHistoricalBuilds).toEqual([]);
160165
expect(env.component.isBuildActive).toBe(false);
@@ -168,15 +173,17 @@ describe('DraftHistoryListComponent', () => {
168173
const build = {
169174
id: 'completed',
170175
state: BuildStates.Completed,
171-
additionalInfo: { dateGenerated: '2025-08-01T12:00:00.000Z' }
176+
additionalInfo: { dateRequested: '2025-08-01T12:00:00.000Z' }
172177
} as BuildDto;
173178
const canceled = {
174179
id: 'canceled',
175-
state: BuildStates.Canceled
180+
state: BuildStates.Canceled,
181+
additionalInfo: { dateRequested: '2025-07-02T12:00:00.000Z' }
176182
} as BuildDto;
177183
const faulted = {
178184
id: 'faulted',
179-
state: BuildStates.Faulted
185+
state: BuildStates.Faulted,
186+
additionalInfo: { dateRequested: '2025-07-01T12:00:00.000Z' }
180187
} as BuildDto;
181188
const buildHistory = [faulted, canceled, build];
182189
const env = new TestEnvironment(buildHistory);
@@ -188,14 +195,48 @@ describe('DraftHistoryListComponent', () => {
188195
expect(env.component.nonActiveBuilds).toEqual(buildHistory);
189196
}));
190197

198+
it('should not show the drafts not supported warning for projects created after 4 June 2025', fakeAsync(() => {
199+
const build = {
200+
state: BuildStates.Completed,
201+
additionalInfo: { dateRequested: '2025-08-01T12:00:00.000Z' }
202+
} as BuildDto;
203+
const olderBuild = {
204+
state: BuildStates.Completed,
205+
additionalInfo: { dateRequested: '2025-08-01T12:00:00.000Z' }
206+
} as BuildDto;
207+
const buildHistory = [olderBuild, build];
208+
// ObjectID was created at 2025-06-03T00:00:00.000Z
209+
const env = new TestEnvironment(buildHistory, '683e3b000000000000000000');
210+
expect(env.component.history).toEqual(buildHistory);
211+
expect(env.component.nonActiveBuilds).toEqual(buildHistory);
212+
expect(env.olderDraftsMessage).not.toBeNull();
213+
}));
214+
215+
it('should show the drafts not supported warning for projects created before 4 June 2025', fakeAsync(() => {
216+
const build = {
217+
state: BuildStates.Completed,
218+
additionalInfo: { dateRequested: '2025-08-01T12:00:00.000Z' }
219+
} as BuildDto;
220+
const olderBuild = {
221+
state: BuildStates.Completed,
222+
additionalInfo: { dateRequested: '2025-08-01T12:00:00.000Z' }
223+
} as BuildDto;
224+
const buildHistory = [olderBuild, build];
225+
// ObjectID was created at 2025-06-05T00:00:00.000Z
226+
const env = new TestEnvironment(buildHistory, '6840de000000000000000000');
227+
expect(env.component.history).toEqual(buildHistory);
228+
expect(env.component.nonActiveBuilds).toEqual(buildHistory);
229+
expect(env.olderDraftsMessage).toBeNull();
230+
}));
231+
191232
class TestEnvironment {
192233
component: DraftHistoryListComponent;
193234
fixture: ComponentFixture<DraftHistoryListComponent>;
194235

195-
constructor(buildHistory: BuildDto[] | undefined) {
196-
when(mockedActivatedProjectService.projectId$).thenReturn(of('project01'));
236+
constructor(buildHistory: BuildDto[] | undefined, projectId: string = 'project01') {
237+
when(mockedActivatedProjectService.projectId$).thenReturn(of(projectId));
197238
when(mockedActivatedProjectService.changes$).thenReturn(of(undefined)); // Required for DraftPreviewBooksComponent
198-
when(mockedDraftGenerationService.getBuildHistory('project01')).thenReturn(new BehaviorSubject(buildHistory));
239+
when(mockedDraftGenerationService.getBuildHistory(projectId)).thenReturn(new BehaviorSubject(buildHistory));
199240
when(mockedFeatureFlagsService.usfmFormat).thenReturn(createTestFeatureFlag(true));
200241

201242
this.fixture = TestBed.createComponent(DraftHistoryListComponent);

src/SIL.XForge.Scripture/ClientApp/src/app/translate/draft-generation/draft-history-list/draft-history-list.component.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { Component, DestroyRef } from '@angular/core';
22
import { MatIconModule } from '@angular/material/icon';
33
import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
4+
import ObjectID from 'bson-objectid';
45
import { take } from 'rxjs';
5-
import { NoticeComponent } from 'src/app/shared/notice/notice.component';
66
import { ActivatedProjectService } from 'xforge-common/activated-project.service';
7+
import { I18nService } from 'xforge-common/i18n.service';
78
import { filterNullish, quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
8-
import { I18nService } from '../../../../xforge-common/i18n.service';
99
import { ProjectNotificationService } from '../../../core/project-notification.service';
1010
import { BuildDto } from '../../../machine-api/build-dto';
1111
import { BuildStates } from '../../../machine-api/build-states';
12+
import { NoticeComponent } from '../../../shared/notice/notice.component';
1213
import { activeBuildStates } from '../draft-generation';
1314
import { DraftGenerationService } from '../draft-generation.service';
1415
import { DraftHistoryEntryComponent } from './draft-history-entry/draft-history-entry.component';
@@ -21,8 +22,11 @@ import { DraftHistoryEntryComponent } from './draft-history-entry/draft-history-
2122
styleUrl: './draft-history-list.component.scss'
2223
})
2324
export class DraftHistoryListComponent {
25+
showOlderDraftsNotSupportedWarning: boolean = false;
2426
history: BuildDto[] = [];
25-
readonly draftHistoryCutoffDate: string = this.i18n.formatDate(new Date('2024-12-03T12:00:00.000Z'));
27+
// This is just after SFv5.33.0 was released
28+
readonly draftHistoryCutOffDate: Date = new Date('2025-06-03T21:00:00Z');
29+
readonly draftHistoryCutOffDateFormatted: string = this.i18n.formatDate(this.draftHistoryCutOffDate);
2630

2731
constructor(
2832
activatedProject: ActivatedProjectService,
@@ -35,6 +39,9 @@ export class DraftHistoryListComponent {
3539
activatedProject.projectId$
3640
.pipe(quietTakeUntilDestroyed(destroyRef), filterNullish(), take(1))
3741
.subscribe(async projectId => {
42+
// Determine whether to show or hide the older drafts warning
43+
this.showOlderDraftsNotSupportedWarning =
44+
ObjectID.isValid(projectId) && new ObjectID(projectId).getTimestamp() < this.draftHistoryCutOffDate;
3845
// Initially load the history
3946
this.loadHistory(projectId);
4047
// Start the connection to SignalR
@@ -84,9 +91,11 @@ export class DraftHistoryListComponent {
8491
}
8592

8693
get savedHistoricalBuilds(): BuildDto[] {
87-
// The date generated is available if the draft has been stored in the realtime database.
94+
// The requested date, if not set for the build in MongoDB, will be set based on the build id in the Machine API
8895
return this.historicalBuilds.filter(
89-
entry => entry.state !== BuildStates.Completed || entry.additionalInfo?.dateGenerated != null
96+
entry =>
97+
entry.additionalInfo?.dateRequested != null &&
98+
new Date(entry.additionalInfo.dateRequested) > this.draftHistoryCutOffDate
9099
);
91100
}
92101

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@
294294
"draft_canceled": "The draft was canceled",
295295
"draft_completed": "The draft is ready",
296296
"draft_faulted": "The draft failed",
297-
"older_drafts_not_available": "Older drafts generated before {{ date }} are not available.",
297+
"older_drafts_not_available": "Older drafts requested before {{ date }} are not available.",
298298
"previously_generated_drafts": "Previously generated drafts"
299299
},
300300
"draft_preview_books": {

0 commit comments

Comments
 (0)