Skip to content

Commit 7a6c6da

Browse files
committed
Determine paratext users not connected by the ParatextUsers property
1 parent 47920ef commit 7a6c6da

File tree

17 files changed

+183
-174
lines changed

17 files changed

+183
-174
lines changed

src/RealtimeServer/scriptureforge/models/paratext-user-profile.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export interface ParatextUserProfile {
22
username: string;
33
opaqueUserId: string;
44
sfUserId?: string;
5+
role: string;
56
}

src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.spec.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,7 @@ class TestEnvironment {
298298
isConnectable: true,
299299
isConnected: false,
300300
hasUserRoleChanged: false,
301-
hasUpdate: false,
302-
members: []
301+
hasUpdate: false
303302
},
304303
{
305304
paratextId: 'pt02',
@@ -310,8 +309,7 @@ class TestEnvironment {
310309
isConnectable: false,
311310
isConnected: true,
312311
hasUserRoleChanged: false,
313-
hasUpdate: false,
314-
members: []
312+
hasUpdate: false
315313
},
316314
{
317315
paratextId: 'pt04',
@@ -321,8 +319,7 @@ class TestEnvironment {
321319
isConnectable: false,
322320
isConnected: false,
323321
hasUserRoleChanged: false,
324-
hasUpdate: false,
325-
members: []
322+
hasUpdate: false
326323
},
327324
{
328325
paratextId: 'pt03',
@@ -333,8 +330,7 @@ class TestEnvironment {
333330
isConnectable: true,
334331
isConnected: true,
335332
hasUserRoleChanged: false,
336-
hasUpdate: false,
337-
members: []
333+
hasUpdate: false
338334
}
339335
];
340336

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-role';
2-
3-
export interface ParatextMember {
4-
connectedToProject: boolean;
5-
username: string;
6-
role: SFProjectRole;
7-
}
8-
91
/** See documentation in ParatextProject.cs. */
102
export interface ParatextProject {
113
paratextId: string;
@@ -16,7 +8,6 @@ export interface ParatextProject {
168
projectId?: string | null;
179
isConnectable: boolean;
1810
isConnected: boolean;
19-
members: ParatextMember[];
2011
hasUserRoleChanged: boolean;
2112
hasUpdate: boolean;
2213
}

src/SIL.XForge.Scripture/ClientApp/src/app/settings/settings.component.spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,7 @@ describe('SettingsComponent', () => {
299299
isConnectable: true,
300300
isConnected: false,
301301
hasUserRoleChanged: false,
302-
hasUpdate: false,
303-
members: []
302+
hasUpdate: false
304303
}
305304
]);
306305
when(mockedParatextService.getResources()).thenResolve([]);
@@ -793,8 +792,7 @@ class TestEnvironment {
793792
isConnectable: true,
794793
isConnected: false,
795794
hasUserRoleChanged: false,
796-
hasUpdate: false,
797-
members: []
795+
hasUpdate: false
798796
},
799797
{
800798
paratextId: 'paratextId02',
@@ -804,8 +802,7 @@ class TestEnvironment {
804802
isConnectable: true,
805803
isConnected: false,
806804
hasUserRoleChanged: false,
807-
hasUpdate: false,
808-
members: []
805+
hasUpdate: false
809806
}
810807
]);
811808
when(mockedParatextService.getResources()).thenResolve([

src/SIL.XForge.Scripture/ClientApp/src/app/shared/test-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export function getEmptyChapterDoc(id: TextDocId): TextData {
112112
export function paratextUsersFromRoles(userRoles: { [id: string]: string }): ParatextUserProfile[] {
113113
return Object.keys(userRoles)
114114
.filter(u => isParatextRole(userRoles[u]))
115-
.map(u => ({ sfUserId: u, username: `pt${u}`, opaqueUserId: `opaque${u}` }));
115+
.map(u => ({ sfUserId: u, username: `pt${u}`, opaqueUserId: `opaque${u}`, role: userRoles[u] }));
116116
}
117117

118118
// Function to create a mock MediaStream with an audio track

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,7 @@ function setUpMocks(args: DraftSourcesComponentStoryState): void {
131131
isConnectable: true,
132132
isConnected: false,
133133
hasUserRoleChanged: false,
134-
hasUpdate: false,
135-
members: []
134+
hasUpdate: false
136135
});
137136

138137
when(mockedParatextService.getResources()).thenResolve(resources);

src/SIL.XForge.Scripture/ClientApp/src/app/translate/editor/tabs/editor-tab-add-resource-dialog/editor-tab-add-resource-dialog.component.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,6 @@ class TestEnvironment {
285285
isConnected: false,
286286
hasUserRoleChanged: false,
287287
hasUpdate: false,
288-
members: [],
289288
...overrides
290289
};
291290
}

src/SIL.XForge.Scripture/ClientApp/src/app/translate/editor/tabs/editor-tab-add-resource-dialog/editor-tab-add-resource-dialog.stories.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ function createTestParatextProject(index: number, overrides?: Partial<ParatextPr
4040
isConnected: false,
4141
hasUserRoleChanged: false,
4242
hasUpdate: false,
43-
members: [],
4443
...overrides
4544
};
4645
}

src/SIL.XForge.Scripture/ClientApp/src/app/users/collaborators/collaborators.component.spec.ts

Lines changed: 22 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
88
import { UserProfile } from 'realtime-server/lib/esm/common/models/user';
99
import { createTestUserProfile } from 'realtime-server/lib/esm/common/models/user-test-data';
1010
import { CheckingAnswerExport, CheckingConfig } from 'realtime-server/lib/esm/scriptureforge/models/checking-config';
11-
import { SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
11+
import { ParatextUserProfile } from 'realtime-server/lib/esm/scriptureforge/models/paratext-user-profile';
12+
import { SFProject, SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
1213
import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-role';
13-
import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data';
14+
import { createTestProject } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data';
1415
import { of } from 'rxjs';
1516
import { anything, mock, verify, when } from 'ts-mockito';
1617
import { ActivatedProjectService } from 'xforge-common/activated-project.service';
@@ -28,20 +29,18 @@ import { TestRealtimeService } from 'xforge-common/test-realtime.service';
2829
import { configureTestingModule, emptyHammerLoader, TestTranslocoModule } from 'xforge-common/test-utils';
2930
import { UICommonModule } from 'xforge-common/ui-common.module';
3031
import { UserService } from 'xforge-common/user.service';
31-
import { ParatextProject } from '../../core/models/paratext-project';
3232
import { SFProjectDoc } from '../../core/models/sf-project-doc';
3333
import { SFProjectProfileDoc } from '../../core/models/sf-project-profile-doc';
3434
import { SF_PROJECT_ROLES } from '../../core/models/sf-project-role-info';
3535
import { SF_TYPE_REGISTRY } from '../../core/models/sf-type-registry';
36-
import { ParatextService } from '../../core/paratext.service';
3736
import { SFProjectService } from '../../core/sf-project.service';
3837
import { SharedModule } from '../../shared/shared.module';
38+
import { paratextUsersFromRoles } from '../../shared/test-utils';
3939
import { CollaboratorsComponent, UserType } from './collaborators.component';
4040

4141
const mockedActivatedProject = mock(ActivatedProjectService);
4242
const mockedNoticeService = mock(NoticeService);
4343
const mockedProjectService = mock(SFProjectService);
44-
const mockedParatextService = mock(ParatextService);
4544
const mockedUserService = mock(UserService);
4645
const mockedDialogService = mock(DialogService);
4746

@@ -61,7 +60,6 @@ describe('CollaboratorsComponent', () => {
6160
{ provide: ActivatedProjectService, useMock: mockedActivatedProject },
6261
{ provide: NoticeService, useMock: mockedNoticeService },
6362
{ provide: SFProjectService, useMock: mockedProjectService },
64-
{ provide: ParatextService, useMock: mockedParatextService },
6563
{ provide: UserService, useMock: mockedUserService },
6664
{ provide: OnlineStatusService, useClass: TestOnlineStatusService },
6765
{ provide: DialogService, useMock: mockedDialogService },
@@ -86,7 +84,7 @@ describe('CollaboratorsComponent', () => {
8684
env.fixture.detectChanges();
8785
tick();
8886
env.fixture.detectChanges();
89-
const numParatextUsers = 3;
87+
const numParatextUsers = 5;
9088
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
9189
expect(env.noUsersLabel(UserType.Paratext)).toBeNull();
9290
expect(env.userTable(UserType.Guest)).toBeNull();
@@ -102,7 +100,7 @@ describe('CollaboratorsComponent', () => {
102100

103101
expect(env.noUsersLabel(UserType.Paratext)).toBeNull();
104102
expect(env.noUsersLabel(UserType.Guest)).toBeNull();
105-
const numParatextUsers = 3;
103+
const numParatextUsers = 5;
106104
const numProjectGuests = 1;
107105
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
108106
expect(env.userRowsByCategory(UserType.Guest).length).toEqual(numProjectGuests);
@@ -134,11 +132,11 @@ describe('CollaboratorsComponent', () => {
134132
tick();
135133
env.fixture.detectChanges();
136134

137-
const numParatextUsers = 3;
135+
const numParatextUsers = 5;
138136
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
139137
expect(
140138
env.component.projectUsers.find(u => u.userType === UserType.Paratext)!.rows.map(r => r.user.displayName)
141-
).toEqual(['User 01', 'User 02', 'User Not On SF']);
139+
).toEqual(['User 01', 'User 02', 'User C', 'User B', 'User A']);
142140
expect(env.userRowsByCategory(UserType.Paratext)[0].nativeElement.querySelector('.user-more-menu')).not.toBeNull();
143141
expect(env.userRowsByCategory(UserType.Paratext)[1].nativeElement.querySelector('.user-more-menu')).not.toBeNull();
144142
expect(env.userRowsByCategory(UserType.Paratext)[2].nativeElement.querySelector('.user-more-menu')).toBeNull();
@@ -157,7 +155,7 @@ describe('CollaboratorsComponent', () => {
157155
tick();
158156
env.fixture.detectChanges();
159157

160-
const numParatextUsers = 3;
158+
const numParatextUsers = 5;
161159
const numGuestUsers = 1;
162160
const numInvitees = 3;
163161
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
@@ -188,26 +186,14 @@ describe('CollaboratorsComponent', () => {
188186
{ email: '[email protected]', role: 'sf_community_checker', expired: false }
189187
]);
190188

191-
when(mockedParatextService.getProjects()).thenResolve([
192-
{
193-
paratextId: 'paratextId1',
194-
name: 'Project 01',
195-
members: [
196-
{ username: 'A User', role: SFProjectRole.ParatextConsultant, connectedToProject: false },
197-
{ username: 'B User', role: SFProjectRole.ParatextTranslator, connectedToProject: false },
198-
{ username: 'C User', role: SFProjectRole.ParatextAdministrator, connectedToProject: false }
199-
]
200-
} as ParatextProject
201-
]);
202-
203189
env.fixture.detectChanges();
204190
tick();
205191
env.fixture.detectChanges();
206192

207193
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(5);
208194
expect(env.userRowsByCategory(UserType.Guest).length).toEqual(4);
209195
const paratextRows = Array.from(env.component.projectUsers.find(u => u.userType === UserType.Paratext)!.rows);
210-
expect(paratextRows.map(r => r.user.displayName)).toEqual(['User 01', 'User 02', 'C User', 'B User', 'A User']);
196+
expect(paratextRows.map(r => r.user.displayName)).toEqual(['User 01', 'User 02', 'User C', 'User B', 'User A']);
211197
const guestRows = Array.from(env.component.projectUsers.find(u => u.userType === UserType.Guest)!.rows);
212198
expect(guestRows.map(r => r.user.displayName ?? r.user.email)).toEqual([
213199
'User 03',
@@ -217,18 +203,6 @@ describe('CollaboratorsComponent', () => {
217203
]);
218204
}));
219205

220-
it('handle error from paratext project query', fakeAsync(() => {
221-
const env = new TestEnvironment();
222-
when(mockedParatextService.getProjects()).thenThrow(new Error('Network error'));
223-
env.setupProjectData();
224-
env.fixture.detectChanges();
225-
expect(() => {
226-
tick();
227-
}).not.toThrow();
228-
verify(mockedNoticeService.show(anything())).once();
229-
tick();
230-
}));
231-
232206
it('handle error from invited users query, when user is not on project', fakeAsync(() => {
233207
// If an admin user is removed from the project, or loses admin
234208
// privileges, while looking at the component, they will run loadUsers
@@ -461,17 +435,6 @@ class TestEnvironment {
461435
}
462436
);
463437

464-
when(mockedParatextService.getProjects()).thenResolve([
465-
{
466-
paratextId: 'paratextId1',
467-
name: 'Project 01',
468-
members: [
469-
{ connectedToProject: true, username: 'User 01', role: SFProjectRole.ParatextAdministrator },
470-
{ connectedToProject: true, username: 'User 02', role: SFProjectRole.ParatextTranslator },
471-
{ connectedToProject: false, username: 'User Not On SF', role: SFProjectRole.ParatextTranslator }
472-
]
473-
} as ParatextProject
474-
]);
475438
this.realtimeService.addSnapshots<UserProfile>(UserProfileDoc.COLLECTION, [
476439
{
477440
id: 'user01',
@@ -611,20 +574,27 @@ class TestEnvironment {
611574
this.fixture.detectChanges();
612575
}
613576

614-
private createProject(userRoles: { [userRef: string]: string }): SFProjectProfile {
615-
return createTestProjectProfile({
577+
private createProject(userRoles: { [userRef: string]: string }): SFProject {
578+
const paratextUsers: ParatextUserProfile[] = paratextUsersFromRoles(userRoles);
579+
const ptMembersNotConnected = [
580+
{ username: 'User A', opaqueUserId: 'opaqueA', role: SFProjectRole.ParatextObserver },
581+
{ username: 'User B', opaqueUserId: 'opaqueB', role: SFProjectRole.ParatextTranslator },
582+
{ username: 'User C', opaqueUserId: 'opaqueC', role: SFProjectRole.ParatextAdministrator }
583+
];
584+
paratextUsers.push(...ptMembersNotConnected);
585+
return createTestProject({
616586
checkingConfig: {
617587
checkingEnabled: false,
618588
usersSeeEachOthersResponses: false,
619589
answerExportMethod: CheckingAnswerExport.MarkedForExport
620590
},
621-
userRoles
591+
userRoles,
592+
paratextUsers
622593
});
623594
}
624595

625596
private setupThisProjectData(projectId: string, project: SFProjectProfile): void {
626-
const projectDoc = { id: projectId, data: project } as SFProjectProfileDoc;
627-
when(mockedActivatedProject.changes$).thenReturn(of(projectDoc));
597+
when(mockedActivatedProject.projectId$).thenReturn(of(projectId));
628598
this.realtimeService.addSnapshot<SFProjectProfile>(SFProjectDoc.COLLECTION, {
629599
id: projectId,
630600
data: project

0 commit comments

Comments
 (0)