Skip to content

Commit fe06002

Browse files
committed
Make paratext role nullable
1 parent 8c98b0e commit fe06002

File tree

11 files changed

+46
-29
lines changed

11 files changed

+46
-29
lines changed

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

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

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ export class SFProjectService extends ProjectService<SFProject> {
558558
bsonType: 'array',
559559
items: {
560560
bsonType: 'object',
561-
required: ['username', 'opaqueUserId', 'role'],
561+
required: ['username', 'opaqueUserId'],
562562
properties: {
563563
username: {
564564
bsonType: 'string'

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -761,8 +761,7 @@ class TestEnvironment {
761761
isConnectable: false,
762762
isConnected: true,
763763
hasUserRoleChanged: false,
764-
hasUpdate: false,
765-
members: []
764+
hasUpdate: false
766765
},
767766
selectableProjectWithLanguageCode: translateSourceToSelectableProjectWithLanguageTag(o.data),
768767
translateSource: {
@@ -788,8 +787,7 @@ class TestEnvironment {
788787
isConnectable: true,
789788
isConnected: false,
790789
hasUserRoleChanged: false,
791-
hasUpdate: false,
792-
members: []
790+
hasUpdate: false
793791
})).map((o: ParatextProject) => ({
794792
paratextProject: o,
795793
selectableProjectWithLanguageCode: o,
@@ -810,8 +808,7 @@ class TestEnvironment {
810808
isConnectable: true,
811809
isConnected: false,
812810
hasUserRoleChanged: false,
813-
hasUpdate: false,
814-
members: []
811+
hasUpdate: false
815812
})).map((o: ParatextProject) => ({
816813
paratextProject: o,
817814
selectableProjectWithLanguageCode: o,

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
@@ -117,8 +117,7 @@ function setUpMocks(args: DraftSourcesComponentStoryState): void {
117117
isConnectable: true,
118118
isConnected: true,
119119
hasUserRoleChanged: false,
120-
hasUpdate: false,
121-
members: []
120+
hasUpdate: false
122121
}));
123122

124123
// Add a project that has an unknown language code

src/SIL.XForge.Scripture/ClientApp/src/app/users/collaborators/collaborators.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ <h2>
5959
></div>
6060
}
6161
<div class="hide-gt-sm">
62-
<em>{{ userRow.role ? i18n.localizeRole(userRow.role) : "" }}</em>
62+
<em>{{ userRow.role ? i18n.localizeRole(userRow.role) : t("role_unknown") }}</em>
6363
</div>
6464
</td>
6565
</ng-container>
@@ -83,7 +83,7 @@ <h2>
8383
</ng-container>
8484
<ng-container matColumnDef="role">
8585
<td class="hide-lt-sm" mat-cell *matCellDef="let userRow">
86-
<em>{{ userRow.role ? i18n.localizeRole(userRow.role) : "" }}</em>
86+
<em>{{ userRow.role ? i18n.localizeRole(userRow.role) : t("role_unknown") }}</em>
8787
</td>
8888
</ng-container>
8989
<ng-container matColumnDef="more">

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

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('CollaboratorsComponent', () => {
8484
env.fixture.detectChanges();
8585
tick();
8686
env.fixture.detectChanges();
87-
const numParatextUsers = 5;
87+
const numParatextUsers = 6;
8888
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
8989
expect(env.noUsersLabel(UserType.Paratext)).toBeNull();
9090
expect(env.userTable(UserType.Guest)).toBeNull();
@@ -100,7 +100,7 @@ describe('CollaboratorsComponent', () => {
100100

101101
expect(env.noUsersLabel(UserType.Paratext)).toBeNull();
102102
expect(env.noUsersLabel(UserType.Guest)).toBeNull();
103-
const numParatextUsers = 5;
103+
const numParatextUsers = 6;
104104
const numProjectGuests = 1;
105105
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
106106
expect(env.userRowsByCategory(UserType.Guest).length).toEqual(numProjectGuests);
@@ -132,11 +132,11 @@ describe('CollaboratorsComponent', () => {
132132
tick();
133133
env.fixture.detectChanges();
134134

135-
const numParatextUsers = 5;
135+
const numParatextUsers = 6;
136136
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
137137
expect(
138138
env.component.projectUsers.find(u => u.userType === UserType.Paratext)!.rows.map(r => r.user.displayName)
139-
).toEqual(['User 01', 'User 02', 'User C', 'User B', 'User A']);
139+
).toEqual(['User 01', 'User 02', 'User C', 'User B', 'User A', 'User No Role']);
140140
expect(env.userRowsByCategory(UserType.Paratext)[0].nativeElement.querySelector('.user-more-menu')).not.toBeNull();
141141
expect(env.userRowsByCategory(UserType.Paratext)[1].nativeElement.querySelector('.user-more-menu')).not.toBeNull();
142142
expect(env.userRowsByCategory(UserType.Paratext)[2].nativeElement.querySelector('.user-more-menu')).toBeNull();
@@ -155,7 +155,7 @@ describe('CollaboratorsComponent', () => {
155155
tick();
156156
env.fixture.detectChanges();
157157

158-
const numParatextUsers = 5;
158+
const numParatextUsers = 6;
159159
const numGuestUsers = 1;
160160
const numInvitees = 3;
161161
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
@@ -190,10 +190,19 @@ describe('CollaboratorsComponent', () => {
190190
tick();
191191
env.fixture.detectChanges();
192192

193-
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(5);
194-
expect(env.userRowsByCategory(UserType.Guest).length).toEqual(4);
193+
const numParatextUsers = 6;
194+
const numGuestUsers = 4;
195+
expect(env.userRowsByCategory(UserType.Paratext).length).toEqual(numParatextUsers);
196+
expect(env.userRowsByCategory(UserType.Guest).length).toEqual(numGuestUsers);
195197
const paratextRows = Array.from(env.component.projectUsers.find(u => u.userType === UserType.Paratext)!.rows);
196-
expect(paratextRows.map(r => r.user.displayName)).toEqual(['User 01', 'User 02', 'User C', 'User B', 'User A']);
198+
expect(paratextRows.map(r => r.user.displayName)).toEqual([
199+
'User 01',
200+
'User 02',
201+
'User C',
202+
'User B',
203+
'User A',
204+
'User No Role'
205+
]);
197206
const guestRows = Array.from(env.component.projectUsers.find(u => u.userType === UserType.Guest)!.rows);
198207
expect(guestRows.map(r => r.user.displayName ?? r.user.email)).toEqual([
199208
'User 03',
@@ -579,7 +588,8 @@ class TestEnvironment {
579588
const ptMembersNotConnected = [
580589
{ username: 'User A', opaqueUserId: 'opaqueA', role: SFProjectRole.ParatextObserver },
581590
{ username: 'User B', opaqueUserId: 'opaqueB', role: SFProjectRole.ParatextTranslator },
582-
{ username: 'User C', opaqueUserId: 'opaqueC', role: SFProjectRole.ParatextAdministrator }
591+
{ username: 'User C', opaqueUserId: 'opaqueC', role: SFProjectRole.ParatextAdministrator },
592+
{ username: 'User No Role', opaqueUserId: 'opaqueNoRole' }
583593
];
584594
paratextUsers.push(...ptMembersNotConnected);
585595
return createTestProject({

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,14 @@ export class CollaboratorsComponent extends DataLoadingComponent implements OnIn
9191

9292
get projectUsers(): ProjectUserLists[] {
9393
return [
94-
{ userType: UserType.Paratext, rows: this._userRows?.filter(u => isParatextRole(u.role)) ?? [] },
95-
{ userType: UserType.Guest, rows: this._userRows?.filter(u => !isParatextRole(u.role)) ?? [] }
94+
{
95+
userType: UserType.Paratext,
96+
rows: this._userRows?.filter(u => isParatextRole(u.role) || u.paratextMemberNotConnected) ?? []
97+
},
98+
{
99+
userType: UserType.Guest,
100+
rows: this._userRows?.filter(u => !isParatextRole(u.role) && !u.paratextMemberNotConnected) ?? []
101+
}
96102
];
97103
}
98104

@@ -235,15 +241,19 @@ export class CollaboratorsComponent extends DataLoadingComponent implements OnIn
235241
}
236242

237243
private sortUsers(projectUsers: Row[], paratextMembersNotConnected: Row[], invitees: Row[]): Row[] {
238-
// Administrators, Translators, Consultants, Observers, Community Checkers, Commenters, SF Observers, None
239-
const userRoles: SFProjectRole[] = Object.values(SFProjectRole).filter(r => r !== SFProjectRole.None);
244+
// Administrators, Translators, Consultants, Observers, Community Checkers, Commenters, SF Observers
245+
const userRoles: (SFProjectRole | null | undefined)[] = Object.values(SFProjectRole).filter(
246+
r => r !== SFProjectRole.None
247+
);
248+
240249
const sortedRows: Row[] = [];
241250
for (const role of userRoles) {
242251
const rowsForRole = projectUsers.filter(u => u.role === role).sort(this.sortByName);
243252
sortedRows.push(...rowsForRole);
244253
}
245254

246-
for (const role of userRoles) {
255+
for (const role of [...userRoles].concat(undefined, null)) {
256+
// include users that do not have their role set
247257
const paratextMembers = paratextMembersNotConnected.filter(u => u.role === role).sort(this.sortByName);
248258
sortedRows.push(...paratextMembers);
249259
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
"project_guests": "Project Guests",
104104
"remove_from_project": "Remove from project",
105105
"remove_user": "Remove User",
106+
"role_unknown": "Role unknown",
106107
"share_with_others": "Share with others"
107108
},
108109
"confirm_draft_sources": {

src/SIL.XForge.Scripture/Models/ParatextUserProfile.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ public class ParatextUserProfile
1313
/// </summary>
1414
public string OpaqueUserId { get; set; }
1515
public string? SFUserId { get; set; }
16-
public string Role { get; set; }
16+
public string? Role { get; set; }
1717
}

src/SIL.XForge.Scripture/Services/ParatextSyncRunner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1901,7 +1901,7 @@ await _projectDoc.SubmitJson0OpAsync(op =>
19011901
userIdsAdded.Add(updatedSFUserId);
19021902
}
19031903

1904-
string paratextRole = ptUserInRegistry?.Role ?? string.Empty;
1904+
string paratextRole = ptUserInRegistry?.Role;
19051905
if (paratextRole != existingUser.Role)
19061906
{
19071907
op.Set(pd => pd.ParatextUsers[index].Role, paratextRole);

0 commit comments

Comments
 (0)