Skip to content

Commit ecd5ad9

Browse files
authored
SF-3163 Store Draft Sources as Arrays (#3508)
1 parent 6f5815f commit ecd5ad9

34 files changed

+1063
-1779
lines changed
Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
use('xforge')
1+
use("xforge");
22

33
// Query to find what project is using a project as a source (and therefore preventing the specified project from being
44
// deleted). This is a re-implementation of the logic in SFProjectService.IsSourceProject
55

6-
const shortName = '';
6+
const shortName = "";
77

8-
const id = db.sf_projects.findOne({ shortName })._id
8+
const id = db.sf_projects.findOne({ shortName })._id;
99

1010
db.sf_projects.find({
11-
$or: [{
12-
'translateConfig.source.projectRef': id
13-
}, {
14-
'translateConfig.draftConfig.alternateSource.projectRef': id
15-
}, {
16-
'translateConfig.draftConfig.alternateTrainingSource.projectRef': id
17-
}, {
18-
'translateConfig.draftConfig.additionalTrainingSource.projectRef': id
19-
}]
20-
})
11+
$or: [
12+
{
13+
"translateConfig.source.projectRef": id
14+
},
15+
{
16+
"translateConfig.draftConfig.draftingSources.projectRef": id
17+
},
18+
{
19+
"translateConfig.draftConfig.trainingSources.projectRef": id
20+
}
21+
]
22+
});

src/RealtimeServer/scriptureforge/models/sf-project-test-data.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ function testProjectProfile(ordinal: number): SFProjectProfile {
1919
preTranslate: false,
2020
defaultNoteTagId: 1,
2121
draftConfig: {
22-
additionalTrainingSourceEnabled: false,
23-
alternateSourceEnabled: false,
24-
alternateTrainingSourceEnabled: false,
22+
draftingSources: [],
23+
trainingSources: [],
2524
lastSelectedTrainingDataFiles: []
2625
}
2726
},

src/RealtimeServer/scriptureforge/models/sf-project.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ export const SF_PROJECT_INDEX_PATHS: (string | [string, CreateIndexesOptions])[]
2222
obj<SFProject>().pathStr(p => p.shortName),
2323
// Indexes for SFProjectService.IsSourceProject() in .NET
2424
[obj<SFProject>().pathStr(p => p.translateConfig.source!.projectRef), { sparse: true }],
25-
[obj<SFProject>().pathStr(p => p.translateConfig.draftConfig.additionalTrainingSource!.projectRef), { sparse: true }],
26-
[obj<SFProject>().pathStr(p => p.translateConfig.draftConfig.alternateSource!.projectRef), { sparse: true }],
27-
[obj<SFProject>().pathStr(p => p.translateConfig.draftConfig.alternateTrainingSource!.projectRef), { sparse: true }]
25+
['translateConfig.draftConfig.draftingSources.projectRef', { sparse: true }],
26+
['translateConfig.draftConfig.trainingSources.projectRef', { sparse: true }]
2827
];
2928

3029
/** Length of id for a DBL resource. */

src/RealtimeServer/scriptureforge/models/translate-config.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,8 @@ export interface DraftUsfmConfig {
5959
}
6060

6161
export interface DraftConfig {
62-
additionalTrainingSourceEnabled: boolean;
63-
additionalTrainingSource?: TranslateSource;
64-
alternateSourceEnabled: boolean;
65-
alternateSource?: TranslateSource;
66-
alternateTrainingSourceEnabled: boolean;
67-
alternateTrainingSource?: TranslateSource;
62+
draftingSources: TranslateSource[];
63+
trainingSources: TranslateSource[];
6864
lastSelectedTrainingDataFiles: string[];
6965
lastSelectedTrainingScriptureRanges?: ProjectScriptureRange[];
7066
lastSelectedTranslationScriptureRanges?: ProjectScriptureRange[];

src/RealtimeServer/scriptureforge/services/sf-project-migrations.spec.ts

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,153 @@ describe('SFProjectMigrations', () => {
905905
]);
906906
});
907907
});
908+
909+
describe('version 27', () => {
910+
it('adds empty arrays if preTranslate is false', async () => {
911+
const env = new TestEnvironment(26);
912+
const conn = env.server.connect();
913+
await createDoc(conn, SF_PROJECTS_COLLECTION, 'project01', {
914+
translateConfig: { preTranslate: false, draftConfig: {} }
915+
});
916+
let projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
917+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toBeUndefined();
918+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toBeUndefined();
919+
920+
await env.server.migrateIfNecessary();
921+
922+
projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
923+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toEqual([]);
924+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toEqual([]);
925+
});
926+
927+
it('adds empty arrays if preTranslate is true but sources were disabled', async () => {
928+
const env = new TestEnvironment(26);
929+
const conn = env.server.connect();
930+
await createDoc(conn, SF_PROJECTS_COLLECTION, 'project01', {
931+
translateConfig: {
932+
preTranslate: true,
933+
draftConfig: {
934+
alternateTrainingSource: { projectRef: 'project02' },
935+
alternateTrainingSourceEnabled: false,
936+
alternateSource: { projectRef: 'project03' },
937+
alternateSourceEnabled: false,
938+
additionalTrainingSource: { projectRef: 'project04' },
939+
additionalTrainingSourceEnabled: false
940+
}
941+
}
942+
});
943+
let projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
944+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toBeUndefined();
945+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toBeUndefined();
946+
947+
await env.server.migrateIfNecessary();
948+
949+
projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
950+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toEqual([]);
951+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toEqual([]);
952+
expect(projectDoc.data.translateConfig.draftConfig.alternateTrainingSource).toBeUndefined();
953+
expect(projectDoc.data.translateConfig.draftConfig.alternateTrainingSourceEnabled).toBeUndefined();
954+
expect(projectDoc.data.translateConfig.draftConfig.alternateSource).toBeUndefined();
955+
expect(projectDoc.data.translateConfig.draftConfig.alternateSourceEnabled).toBeUndefined();
956+
expect(projectDoc.data.translateConfig.draftConfig.additionalTrainingSource).toBeUndefined();
957+
expect(projectDoc.data.translateConfig.draftConfig.additionalTrainingSourceEnabled).toBeUndefined();
958+
});
959+
960+
it('adds empty arrays if preTranslate is true and sources are enabled but undefined', async () => {
961+
const env = new TestEnvironment(26);
962+
const conn = env.server.connect();
963+
await createDoc(conn, SF_PROJECTS_COLLECTION, 'project01', {
964+
translateConfig: {
965+
preTranslate: true,
966+
draftConfig: {
967+
alternateTrainingSourceEnabled: true,
968+
alternateSourceEnabled: true,
969+
additionalTrainingSourceEnabled: true
970+
}
971+
}
972+
});
973+
let projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
974+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toBeUndefined();
975+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toBeUndefined();
976+
977+
await env.server.migrateIfNecessary();
978+
979+
projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
980+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toEqual([]);
981+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toEqual([]);
982+
});
983+
984+
it('adds source to both arrays if preTranslate is true but sources were disabled', async () => {
985+
const env = new TestEnvironment(26);
986+
const conn = env.server.connect();
987+
await createDoc(conn, SF_PROJECTS_COLLECTION, 'project01', {
988+
translateConfig: {
989+
preTranslate: true,
990+
draftConfig: {
991+
alternateTrainingSource: { projectRef: 'project02' },
992+
alternateTrainingSourceEnabled: false,
993+
alternateSource: { projectRef: 'project03' },
994+
alternateSourceEnabled: false,
995+
additionalTrainingSource: { projectRef: 'project04' },
996+
additionalTrainingSourceEnabled: false
997+
},
998+
source: { projectRef: 'project05' }
999+
}
1000+
});
1001+
let projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
1002+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toBeUndefined();
1003+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toBeUndefined();
1004+
1005+
await env.server.migrateIfNecessary();
1006+
1007+
projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
1008+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toEqual([{ projectRef: 'project05' }]);
1009+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toEqual([{ projectRef: 'project05' }]);
1010+
expect(projectDoc.data.translateConfig.draftConfig.alternateTrainingSource).toBeUndefined();
1011+
expect(projectDoc.data.translateConfig.draftConfig.alternateTrainingSourceEnabled).toBeUndefined();
1012+
expect(projectDoc.data.translateConfig.draftConfig.alternateSource).toBeUndefined();
1013+
expect(projectDoc.data.translateConfig.draftConfig.alternateSourceEnabled).toBeUndefined();
1014+
expect(projectDoc.data.translateConfig.draftConfig.additionalTrainingSource).toBeUndefined();
1015+
expect(projectDoc.data.translateConfig.draftConfig.additionalTrainingSourceEnabled).toBeUndefined();
1016+
});
1017+
1018+
it('adds sources to the appropriate arrays if preTranslate is true and sources are configured', async () => {
1019+
const env = new TestEnvironment(26);
1020+
const conn = env.server.connect();
1021+
await createDoc(conn, SF_PROJECTS_COLLECTION, 'project01', {
1022+
translateConfig: {
1023+
preTranslate: true,
1024+
draftConfig: {
1025+
alternateTrainingSource: { projectRef: 'project02' },
1026+
alternateTrainingSourceEnabled: true,
1027+
alternateSource: { projectRef: 'project03' },
1028+
alternateSourceEnabled: true,
1029+
additionalTrainingSource: { projectRef: 'project04' },
1030+
additionalTrainingSourceEnabled: true
1031+
},
1032+
source: { projectRef: 'project05' }
1033+
}
1034+
});
1035+
let projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
1036+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toBeUndefined();
1037+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toBeUndefined();
1038+
1039+
await env.server.migrateIfNecessary();
1040+
1041+
projectDoc = await fetchDoc(conn, SF_PROJECTS_COLLECTION, 'project01');
1042+
expect(projectDoc.data.translateConfig.draftConfig.draftingSources).toEqual([{ projectRef: 'project03' }]);
1043+
expect(projectDoc.data.translateConfig.draftConfig.trainingSources).toEqual([
1044+
{ projectRef: 'project02' },
1045+
{ projectRef: 'project04' }
1046+
]);
1047+
expect(projectDoc.data.translateConfig.draftConfig.alternateTrainingSource).toBeUndefined();
1048+
expect(projectDoc.data.translateConfig.draftConfig.alternateTrainingSourceEnabled).toBeUndefined();
1049+
expect(projectDoc.data.translateConfig.draftConfig.alternateSource).toBeUndefined();
1050+
expect(projectDoc.data.translateConfig.draftConfig.alternateSourceEnabled).toBeUndefined();
1051+
expect(projectDoc.data.translateConfig.draftConfig.additionalTrainingSource).toBeUndefined();
1052+
expect(projectDoc.data.translateConfig.draftConfig.additionalTrainingSourceEnabled).toBeUndefined();
1053+
});
1054+
});
9081055
});
9091056

9101057
class TestEnvironment {

src/RealtimeServer/scriptureforge/services/sf-project-migrations.ts

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { NoteTag } from '../models/note-tag';
77
import { SF_PROJECT_RIGHTS, SFProjectDomain } from '../models/sf-project-rights';
88
import { SFProjectRole } from '../models/sf-project-role';
99
import { TextInfoPermission } from '../models/text-info-permission';
10-
import { TranslateShareLevel } from '../models/translate-config';
10+
import { TranslateShareLevel, TranslateSource } from '../models/translate-config';
1111

1212
class SFProjectMigration1 extends DocMigration {
1313
static readonly VERSION = 1;
@@ -553,6 +553,83 @@ class SFProjectMigration26 extends DocMigration {
553553
}
554554
}
555555

556+
class SFProjectMigration27 extends DocMigration {
557+
static readonly VERSION = 27;
558+
559+
async migrateDoc(doc: Doc): Promise<void> {
560+
const ops: Op[] = [];
561+
const draftingSources: TranslateSource[] = [];
562+
const trainingSources: TranslateSource[] = [];
563+
564+
// Migrate the old values to the new structure
565+
if (doc.data.translateConfig.preTranslate === true) {
566+
const translateConfig = doc.data.translateConfig;
567+
const draftConfig = translateConfig.draftConfig;
568+
if (draftConfig.alternateTrainingSourceEnabled && draftConfig.alternateTrainingSource != null) {
569+
trainingSources.push(draftConfig.alternateTrainingSource);
570+
} else if (translateConfig.source != null) {
571+
trainingSources.push(translateConfig.source);
572+
}
573+
if (draftConfig.additionalTrainingSourceEnabled && draftConfig.additionalTrainingSource != null) {
574+
trainingSources.push(draftConfig.additionalTrainingSource);
575+
}
576+
if (draftConfig.alternateSourceEnabled && draftConfig.alternateSource != null) {
577+
draftingSources.push(draftConfig.alternateSource);
578+
} else if (translateConfig.source != null) {
579+
draftingSources.push(translateConfig.source);
580+
}
581+
}
582+
583+
// Create the new structure
584+
if (doc.data.translateConfig.draftConfig.draftingSources == null) {
585+
ops.push({ p: ['translateConfig', 'draftConfig', 'draftingSources'], oi: draftingSources });
586+
}
587+
if (doc.data.translateConfig.draftConfig.trainingSources == null) {
588+
ops.push({ p: ['translateConfig', 'draftConfig', 'trainingSources'], oi: trainingSources });
589+
}
590+
591+
// Remove the old values
592+
if (doc.data.translateConfig.draftConfig.alternateSourceEnabled != null) {
593+
ops.push({
594+
p: ['translateConfig', 'draftConfig', 'alternateSourceEnabled'],
595+
od: doc.data.translateConfig.draftConfig.alternateSourceEnabled
596+
});
597+
}
598+
if (doc.data.translateConfig.draftConfig.alternateSource != null) {
599+
ops.push({
600+
p: ['translateConfig', 'draftConfig', 'alternateSource'],
601+
od: doc.data.translateConfig.draftConfig.alternateSource
602+
});
603+
}
604+
if (doc.data.translateConfig.draftConfig.alternateTrainingSourceEnabled != null) {
605+
ops.push({
606+
p: ['translateConfig', 'draftConfig', 'alternateTrainingSourceEnabled'],
607+
od: doc.data.translateConfig.draftConfig.alternateTrainingSourceEnabled
608+
});
609+
}
610+
if (doc.data.translateConfig.draftConfig.alternateTrainingSource != null) {
611+
ops.push({
612+
p: ['translateConfig', 'draftConfig', 'alternateTrainingSource'],
613+
od: doc.data.translateConfig.draftConfig.alternateTrainingSource
614+
});
615+
}
616+
if (doc.data.translateConfig.draftConfig.additionalTrainingSourceEnabled != null) {
617+
ops.push({
618+
p: ['translateConfig', 'draftConfig', 'additionalTrainingSourceEnabled'],
619+
od: doc.data.translateConfig.draftConfig.additionalTrainingSourceEnabled
620+
});
621+
}
622+
if (doc.data.translateConfig.draftConfig.additionalTrainingSource != null) {
623+
ops.push({
624+
p: ['translateConfig', 'draftConfig', 'additionalTrainingSource'],
625+
od: doc.data.translateConfig.draftConfig.additionalTrainingSource
626+
});
627+
}
628+
629+
await submitMigrationOp(SFProjectMigration27.VERSION, doc, ops);
630+
}
631+
}
632+
556633
export const SF_PROJECT_MIGRATIONS: MigrationConstructor[] = monotonicallyIncreasingMigrationList([
557634
SFProjectMigration1,
558635
SFProjectMigration2,
@@ -579,5 +656,6 @@ export const SF_PROJECT_MIGRATIONS: MigrationConstructor[] = monotonicallyIncrea
579656
SFProjectMigration23,
580657
SFProjectMigration24,
581658
SFProjectMigration25,
582-
SFProjectMigration26
659+
SFProjectMigration26,
660+
SFProjectMigration27
583661
]);

0 commit comments

Comments
 (0)