diff --git a/firebase/LEVANTE/admin/firestore.rules b/firebase/LEVANTE/admin/firestore.rules
index 2e10245ce..f74e9b0e0 100644
--- a/firebase/LEVANTE/admin/firestore.rules
+++ b/firebase/LEVANTE/admin/firestore.rules
@@ -67,12 +67,13 @@ service cloud.firestore {
allow read, write: if request.auth.uid == uid;
}
- function isUserAdmin() {
- let districts = resource.data.get(['districts', 'current'], []);
- let schools = resource.data.get(['schools', 'current'], []);
- let classes = resource.data.get(['classes', 'current'], []);
- let groups = resource.data.get(['groups', 'current'], []);
- let families = resource.data.get(['families', 'current'], []);
+ function isUserAdmin(requireCurrent) {
+ let orgStatus = requireCurrent ? 'current' : 'all';
+ let districts = resource.data.get(['districts', orgStatus], []);
+ let schools = resource.data.get(['schools', orgStatus], []);
+ let classes = resource.data.get(['classes', orgStatus], []);
+ let groups = resource.data.get(['groups', orgStatus], []);
+ let families = resource.data.get(['families', orgStatus], []);
let adminOrgs = get(/databases/$(database)/documents/userClaims/$(request.auth.uid)).data.get('claims', {}).get('adminOrgs', {});
return districts.hasAny(adminOrgs.get('districts', ['..']))
|| schools.hasAny(adminOrgs.get('schools', ['..']))
@@ -82,7 +83,7 @@ service cloud.firestore {
}
function canReadExistingUser() {
- return myData() || isUserAdmin();
+ return myData() || isUserAdmin(false) || isUserAdmin(true);
}
allow read: if canReadExistingUser();
diff --git a/firebase/LEVANTE/assessment/firestore.rules b/firebase/LEVANTE/assessment/firestore.rules
index 067f11b6d..2f6848964 100644
--- a/firebase/LEVANTE/assessment/firestore.rules
+++ b/firebase/LEVANTE/assessment/firestore.rules
@@ -55,12 +55,13 @@ service cloud.firestore {
return uid == roarUid();
}
- function isUserAdmin() {
- let districts = resource.data.get(['districts', 'current'], []);
- let schools = resource.data.get(['schools', 'current'], []);
- let classes = resource.data.get(['classes', 'current'], []);
- let groups = resource.data.get(['groups', 'current'], []);
- let families = resource.data.get(['families', 'current'], []);
+ function isUserAdmin(requireCurrent) {
+ let orgStatus = requireCurrent ? 'current' : 'all';
+ let districts = resource.data.get(['districts', orgStatus], []);
+ let schools = resource.data.get(['schools', orgStatus], []);
+ let classes = resource.data.get(['classes', orgStatus], []);
+ let groups = resource.data.get(['groups', orgStatus], []);
+ let families = resource.data.get(['families', orgStatus], []);
let adminOrgs = get(/databases/$(database)/documents/userClaims/$(request.auth.uid)).data.get('claims', {}).get('adminOrgs', {});
return districts.hasAny(adminOrgs.get('districts', ['..']))
|| schools.hasAny(adminOrgs.get('schools', ['..']))
@@ -70,7 +71,7 @@ service cloud.firestore {
}
function canReadExistingUser() {
- return myData() || isUserAdmin();
+ return myData() || isUserAdmin(false) || isUserAdmin(true);
}
allow read: if canReadExistingUser();
diff --git a/firebase/admin/firestore.indexes.json b/firebase/admin/firestore.indexes.json
index 289ecbee9..199db5dd3 100644
--- a/firebase/admin/firestore.indexes.json
+++ b/firebase/admin/firestore.indexes.json
@@ -2,11 +2,25 @@
"indexes": [
{
"collectionGroup": "administrations",
- "queryScope": "COLLECTION_GROUP",
+ "queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "testData",
+ "fieldPath": "districts",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "dateClosed",
"order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "administrations",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "readOrgs.classes",
+ "arrayConfig": "CONTAINS"
},
{
"fieldPath": "name",
@@ -19,7 +33,7 @@
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "readOrgs.classes",
+ "fieldPath": "readOrgs.districts",
"arrayConfig": "CONTAINS"
},
{
@@ -36,6 +50,10 @@
"fieldPath": "readOrgs.districts",
"arrayConfig": "CONTAINS"
},
+ {
+ "fieldPath": "testData",
+ "order": "ASCENDING"
+ },
{
"fieldPath": "name",
"order": "ASCENDING"
@@ -70,6 +88,24 @@
}
]
},
+ {
+ "collectionGroup": "administrations",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "readOrgs.groups",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "testData",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
{
"collectionGroup": "administrations",
"queryScope": "COLLECTION",
@@ -84,6 +120,80 @@
}
]
},
+ {
+ "collectionGroup": "administrations",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "schools",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "dateClosed",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "administrations",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "testData",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "assignedOrgs",
+ "queryScope": "COLLECTION_GROUP",
+ "fields": [
+ {
+ "fieldPath": "orgId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "dateClosed",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "assignedOrgs",
+ "queryScope": "COLLECTION_GROUP",
+ "fields": [
+ {
+ "fieldPath": "orgId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "testData",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "assignedOrgs",
+ "queryScope": "COLLECTION_GROUP",
+ "fields": [
+ {
+ "fieldPath": "orgId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "testData",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "dateClosed",
+ "order": "ASCENDING"
+ }
+ ]
+ },
{
"collectionGroup": "assignments",
"queryScope": "COLLECTION_GROUP",
@@ -2998,6 +3108,10 @@
"collectionGroup": "classes",
"queryScope": "COLLECTION",
"fields": [
+ {
+ "fieldPath": "archived",
+ "order": "ASCENDING"
+ },
{
"fieldPath": "schoolId",
"order": "ASCENDING"
@@ -3012,6 +3126,10 @@
"collectionGroup": "classes",
"queryScope": "COLLECTION",
"fields": [
+ {
+ "fieldPath": "archived",
+ "order": "ASCENDING"
+ },
{
"fieldPath": "schoolId",
"order": "ASCENDING"
@@ -3023,7 +3141,7 @@
]
},
{
- "collectionGroup": "schools",
+ "collectionGroup": "classes",
"queryScope": "COLLECTION",
"fields": [
{
@@ -3031,59 +3149,59 @@
"order": "ASCENDING"
},
{
- "fieldPath": "abbreviation",
+ "fieldPath": "lastRoarSync",
"order": "ASCENDING"
}
]
},
{
- "collectionGroup": "schools",
+ "collectionGroup": "classes",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "districtId",
+ "fieldPath": "schoolId",
"order": "ASCENDING"
},
{
- "fieldPath": "abbreviation",
- "order": "DESCENDING"
+ "fieldPath": "name",
+ "order": "ASCENDING"
}
]
},
{
- "collectionGroup": "schools",
+ "collectionGroup": "classes",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "districtId",
+ "fieldPath": "schoolId",
"order": "ASCENDING"
},
{
- "fieldPath": "address",
- "order": "ASCENDING"
+ "fieldPath": "name",
+ "order": "DESCENDING"
}
]
},
{
- "collectionGroup": "schools",
+ "collectionGroup": "districts",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "districtId",
+ "fieldPath": "archived",
"order": "ASCENDING"
},
{
- "fieldPath": "address",
- "order": "DESCENDING"
+ "fieldPath": "name",
+ "order": "ASCENDING"
}
]
},
{
- "collectionGroup": "schools",
+ "collectionGroup": "families",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "districtId",
+ "fieldPath": "archived",
"order": "ASCENDING"
},
{
@@ -3093,187 +3211,623 @@
]
},
{
- "collectionGroup": "schools",
+ "collectionGroup": "groups",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "districtId",
+ "fieldPath": "archived",
"order": "ASCENDING"
},
{
"fieldPath": "name",
- "order": "DESCENDING"
+ "order": "ASCENDING"
}
]
},
{
- "collectionGroup": "users",
- "queryScope": "COLLECTION",
+ "collectionGroup": "readOrgs",
+ "queryScope": "COLLECTION_GROUP",
"fields": [
{
- "fieldPath": "assigningOrgs.districts",
- "arrayConfig": "CONTAINS"
- },
- {
- "fieldPath": "schoolName",
+ "fieldPath": "orgId",
"order": "ASCENDING"
},
{
- "fieldPath": "assignmentsAssigned.wTWJITpjKthvDJ9fSTNW",
+ "fieldPath": "dateClosed",
"order": "ASCENDING"
}
]
},
{
- "collectionGroup": "users",
- "queryScope": "COLLECTION",
+ "collectionGroup": "readOrgs",
+ "queryScope": "COLLECTION_GROUP",
"fields": [
{
- "fieldPath": "assigningOrgs.districts",
- "arrayConfig": "CONTAINS"
- },
- {
- "fieldPath": "studentData.grade",
+ "fieldPath": "orgId",
"order": "ASCENDING"
},
{
- "fieldPath": "assignmentsAssigned.wTWJITpjKthvDJ9fSTNW",
+ "fieldPath": "testData",
"order": "ASCENDING"
}
]
},
{
- "collectionGroup": "users",
- "queryScope": "COLLECTION",
+ "collectionGroup": "readOrgs",
+ "queryScope": "COLLECTION_GROUP",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "orgId",
+ "order": "ASCENDING"
},
{
- "fieldPath": "name",
+ "fieldPath": "testData",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "dateClosed",
"order": "ASCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "archived",
+ "order": "ASCENDING"
},
{
- "fieldPath": "name.first",
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "abbreviation",
"order": "ASCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "archived",
+ "order": "ASCENDING"
},
{
- "fieldPath": "name.first",
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "abbreviation",
"order": "DESCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "archived",
+ "order": "ASCENDING"
},
{
- "fieldPath": "name.last",
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "address",
"order": "ASCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "archived",
+ "order": "ASCENDING"
},
{
- "fieldPath": "name.last",
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "address",
"order": "DESCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "archived",
+ "order": "ASCENDING"
},
{
- "fieldPath": "studentData.dob",
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "name",
"order": "ASCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "archived",
+ "order": "ASCENDING"
},
{
- "fieldPath": "studentData.dob",
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "name",
"order": "DESCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
},
{
- "fieldPath": "studentData.gender",
+ "fieldPath": "abbreviation",
"order": "ASCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
- "arrayConfig": "CONTAINS"
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
},
{
- "fieldPath": "studentData.gender",
+ "fieldPath": "abbreviation",
"order": "DESCENDING"
}
]
},
{
- "collectionGroup": "users",
+ "collectionGroup": "schools",
"queryScope": "COLLECTION",
"fields": [
{
- "fieldPath": "classes.current",
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "address",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "address",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "lastRoarSync",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "archived",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "archived",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "name",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "abbreviation",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "abbreviation",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "address",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "address",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "lastRoarSync",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "archived",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "schools",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "archived",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "districtId",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "name",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION_GROUP",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION_GROUP",
+ "fields": [
+ {
+ "fieldPath": "districts.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION_GROUP",
+ "fields": [
+ {
+ "fieldPath": "families.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION_GROUP",
+ "fields": [
+ {
+ "fieldPath": "groups.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION_GROUP",
+ "fields": [
+ {
+ "fieldPath": "schools.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "assigningOrgs.districts",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "schoolName",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "assignmentsAssigned.wTWJITpjKthvDJ9fSTNW",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "assigningOrgs.districts",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "studentData.grade",
+ "order": "ASCENDING"
+ },
+ {
+ "fieldPath": "assignmentsAssigned.wTWJITpjKthvDJ9fSTNW",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name.first",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name.first",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name.last",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "name.last",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "studentData.dob",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "studentData.dob",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "studentData.gender",
+ "order": "ASCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "studentData.gender",
+ "order": "DESCENDING"
+ }
+ ]
+ },
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "classes.current",
"arrayConfig": "CONTAINS"
},
{
@@ -3352,6 +3906,20 @@
}
]
},
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districts.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "archived",
+ "order": "ASCENDING"
+ }
+ ]
+ },
{
"collectionGroup": "users",
"queryScope": "COLLECTION",
@@ -3366,6 +3934,20 @@
}
]
},
+ {
+ "collectionGroup": "users",
+ "queryScope": "COLLECTION",
+ "fields": [
+ {
+ "fieldPath": "districts.current",
+ "arrayConfig": "CONTAINS"
+ },
+ {
+ "fieldPath": "lastRoarSync",
+ "order": "ASCENDING"
+ }
+ ]
+ },
{
"collectionGroup": "users",
"queryScope": "COLLECTION",
@@ -4218,46 +4800,88 @@
"collectionGroup": "administrations",
"fieldPath": "classes",
"ttl": false,
+ "indexes": []
+ },
+ {
+ "collectionGroup": "administrations",
+ "fieldPath": "createdBy",
+ "ttl": false,
"indexes": [
{
- "arrayConfig": "CONTAINS",
+ "order": "ASCENDING",
"queryScope": "COLLECTION"
}
]
},
{
"collectionGroup": "administrations",
- "fieldPath": "districts",
+ "fieldPath": "dateClosed",
"ttl": false,
"indexes": [
{
- "arrayConfig": "CONTAINS",
+ "order": "ASCENDING",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "order": "DESCENDING",
"queryScope": "COLLECTION"
}
]
},
{
"collectionGroup": "administrations",
- "fieldPath": "families",
+ "fieldPath": "dateCreated",
"ttl": false,
"indexes": [
{
- "arrayConfig": "CONTAINS",
+ "order": "ASCENDING",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "order": "DESCENDING",
"queryScope": "COLLECTION"
}
]
},
{
"collectionGroup": "administrations",
- "fieldPath": "groups",
+ "fieldPath": "dateOpened",
"ttl": false,
"indexes": [
{
- "arrayConfig": "CONTAINS",
+ "order": "ASCENDING",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "order": "DESCENDING",
"queryScope": "COLLECTION"
}
]
},
+ {
+ "collectionGroup": "administrations",
+ "fieldPath": "districts",
+ "ttl": false,
+ "indexes": []
+ },
+ {
+ "collectionGroup": "administrations",
+ "fieldPath": "families",
+ "ttl": false,
+ "indexes": []
+ },
+ {
+ "collectionGroup": "administrations",
+ "fieldPath": "groups",
+ "ttl": false,
+ "indexes": []
+ },
+ {
+ "collectionGroup": "administrations",
+ "fieldPath": "minimalOrgs",
+ "ttl": false,
+ "indexes": []
+ },
{
"collectionGroup": "administrations",
"fieldPath": "name",
@@ -4274,10 +4898,6 @@
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
- },
- {
- "order": "ASCENDING",
- "queryScope": "COLLECTION_GROUP"
}
]
},
@@ -4346,16 +4966,40 @@
"collectionGroup": "administrations",
"fieldPath": "schools",
"ttl": false,
+ "indexes": []
+ },
+ {
+ "collectionGroup": "administrations",
+ "fieldPath": "sequential",
+ "ttl": false,
+ "indexes": []
+ },
+ {
+ "collectionGroup": "administrations",
+ "fieldPath": "testData",
+ "ttl": false,
"indexes": [
+ {
+ "order": "ASCENDING",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "order": "DESCENDING",
+ "queryScope": "COLLECTION"
+ },
{
"arrayConfig": "CONTAINS",
"queryScope": "COLLECTION"
+ },
+ {
+ "order": "ASCENDING",
+ "queryScope": "COLLECTION_GROUP"
}
]
},
{
- "collectionGroup": "administrations",
- "fieldPath": "testData",
+ "collectionGroup": "assignedOrgs",
+ "fieldPath": "orgId",
"ttl": false,
"indexes": [
{
@@ -4376,6 +5020,25 @@
}
]
},
+ {
+ "collectionGroup": "assignments",
+ "fieldPath": "assessments",
+ "ttl": false,
+ "indexes": [
+ {
+ "order": "ASCENDING",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "order": "DESCENDING",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "arrayConfig": "CONTAINS",
+ "queryScope": "COLLECTION"
+ }
+ ]
+ },
{
"collectionGroup": "assignments",
"fieldPath": "assigningOrgs",
@@ -4432,6 +5095,29 @@
"ttl": false,
"indexes": []
},
+ {
+ "collectionGroup": "readOrgs",
+ "fieldPath": "orgId",
+ "ttl": false,
+ "indexes": [
+ {
+ "order": "ASCENDING",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "order": "DESCENDING",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "arrayConfig": "CONTAINS",
+ "queryScope": "COLLECTION"
+ },
+ {
+ "order": "ASCENDING",
+ "queryScope": "COLLECTION_GROUP"
+ }
+ ]
+ },
{
"collectionGroup": "status",
"fieldPath": "completion",
diff --git a/firebase/admin/firestore.rules b/firebase/admin/firestore.rules
index 284b25c27..2a36db6a1 100644
--- a/firebase/admin/firestore.rules
+++ b/firebase/admin/firestore.rules
@@ -74,12 +74,13 @@ service cloud.firestore {
return uid == roarUid();
}
- function isUserAdmin() {
- let districts = resource.data.get(['districts', 'current'], []);
- let schools = resource.data.get(['schools', 'current'], []);
- let classes = resource.data.get(['classes', 'current'], []);
- let groups = resource.data.get(['groups', 'current'], []);
- let families = resource.data.get(['families', 'current'], []);
+ function isUserAdmin(requireCurrent) {
+ let orgStatus = requireCurrent ? 'current' : 'all';
+ let districts = resource.data.get(['districts', orgStatus], []);
+ let schools = resource.data.get(['schools', orgStatus], []);
+ let classes = resource.data.get(['classes', orgStatus], []);
+ let groups = resource.data.get(['groups', orgStatus], []);
+ let families = resource.data.get(['families', orgStatus], []);
let adminOrgs = get(/databases/$(database)/documents/userClaims/$(request.auth.uid)).data.get('claims', {}).get('adminOrgs', {});
return districts.hasAny(adminOrgs.get('districts', ['..']))
|| schools.hasAny(adminOrgs.get('schools', ['..']))
@@ -89,7 +90,7 @@ service cloud.firestore {
}
function canReadExistingUser() {
- return myData() || isUserAdmin();
+ return myData() || isUserAdmin(false) || isUserAdmin(true);
}
allow read: if canReadExistingUser();
diff --git a/firebase/assessment/firestore.rules b/firebase/assessment/firestore.rules
index ea0b52863..70a609805 100644
--- a/firebase/assessment/firestore.rules
+++ b/firebase/assessment/firestore.rules
@@ -57,12 +57,13 @@ service cloud.firestore {
return uid == roarUid();
}
- function isUserAdmin() {
- let districts = resource.data.get(['districts', 'current'], []);
- let schools = resource.data.get(['schools', 'current'], []);
- let classes = resource.data.get(['classes', 'current'], []);
- let groups = resource.data.get(['groups', 'current'], []);
- let families = resource.data.get(['families', 'current'], []);
+ function isUserAdmin(requireCurrent) {
+ let orgStatus = requireCurrent ? 'current' : 'all';
+ let districts = resource.data.get(['districts', orgStatus], []);
+ let schools = resource.data.get(['schools', orgStatus], []);
+ let classes = resource.data.get(['classes', orgStatus], []);
+ let groups = resource.data.get(['groups', orgStatus], []);
+ let families = resource.data.get(['families', orgStatus], []);
let adminOrgs = get(/databases/$(database)/documents/userClaims/$(request.auth.uid)).data.get('claims', {}).get('adminOrgs', {});
return districts.hasAny(adminOrgs.get('districts', ['..']))
|| schools.hasAny(adminOrgs.get('schools', ['..']))
@@ -72,7 +73,7 @@ service cloud.firestore {
}
function canReadExistingUser() {
- return myData() || isUserAdmin();
+ return myData() || isUserAdmin(false) || isUserAdmin(true);
}
allow read: if canReadExistingUser();
diff --git a/package-lock.json b/package-lock.json
index 59ce71c39..057e6f2f2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
"version": "2.11.18",
"dependencies": {
"@bdelab/roam-fluency": "1.11.26",
- "@bdelab/roar-firekit": "^8.0.8",
+ "@bdelab/roar-firekit": "^9.0.1",
"@bdelab/roar-letter": "1.11.8",
"@bdelab/roar-multichoice": "^1.11.3",
"@bdelab/roar-pa": "2.2.4",
@@ -1848,9 +1848,9 @@
}
},
"node_modules/@bdelab/roar-firekit": {
- "version": "8.0.8",
- "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-8.0.8.tgz",
- "integrity": "sha512-L69a3uQff8OYHFUP9i036N1NGon3y2YR0SLYbHwtNyulkXemtZqNbPxvJPokdupOOAsuw+MRMUxPJPJrxX8ocQ==",
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-9.0.1.tgz",
+ "integrity": "sha512-MscBltVjx0V1BsTP+n5/3Afwtp76DDe67CgeqrnCTClXgqUyq2KWzB9cndppVhr2Fk6XZWPbk5rrnAvjZpN6fw==",
"license": "ISC",
"dependencies": {
"@bdelab/roar-firekit": "^4.1.1",
@@ -24790,7 +24790,6 @@
},
"node_modules/npm/node_modules/lodash._baseindexof": {
"version": "3.1.0",
- "extraneous": true,
"inBundle": true,
"license": "MIT"
},
@@ -24815,19 +24814,16 @@
},
"node_modules/npm/node_modules/lodash._bindcallback": {
"version": "3.0.1",
- "extraneous": true,
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/lodash._cacheindexof": {
"version": "3.0.2",
- "extraneous": true,
"inBundle": true,
"license": "MIT"
},
"node_modules/npm/node_modules/lodash._createcache": {
"version": "3.1.2",
- "extraneous": true,
"inBundle": true,
"license": "MIT",
"dependencies": {
@@ -24836,7 +24832,6 @@
},
"node_modules/npm/node_modules/lodash._getnative": {
"version": "3.9.1",
- "extraneous": true,
"inBundle": true,
"license": "MIT"
},
@@ -24847,7 +24842,6 @@
},
"node_modules/npm/node_modules/lodash.restparam": {
"version": "3.6.1",
- "extraneous": true,
"inBundle": true,
"license": "MIT"
},
@@ -38988,9 +38982,9 @@
}
},
"@bdelab/roar-firekit": {
- "version": "8.0.8",
- "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-8.0.8.tgz",
- "integrity": "sha512-L69a3uQff8OYHFUP9i036N1NGon3y2YR0SLYbHwtNyulkXemtZqNbPxvJPokdupOOAsuw+MRMUxPJPJrxX8ocQ==",
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-9.0.1.tgz",
+ "integrity": "sha512-MscBltVjx0V1BsTP+n5/3Afwtp76DDe67CgeqrnCTClXgqUyq2KWzB9cndppVhr2Fk6XZWPbk5rrnAvjZpN6fw==",
"requires": {
"@bdelab/roar-firekit": "^4.1.1",
"crc-32": "^1.2.2",
@@ -56414,8 +56408,7 @@
},
"lodash._baseindexof": {
"version": "3.1.0",
- "bundled": true,
- "extraneous": true
+ "bundled": true
},
"lodash._baseuniq": {
"version": "4.6.0",
@@ -56437,26 +56430,22 @@
},
"lodash._bindcallback": {
"version": "3.0.1",
- "bundled": true,
- "extraneous": true
+ "bundled": true
},
"lodash._cacheindexof": {
"version": "3.0.2",
- "bundled": true,
- "extraneous": true
+ "bundled": true
},
"lodash._createcache": {
"version": "3.1.2",
"bundled": true,
- "extraneous": true,
"requires": {
"lodash._getnative": "^3.0.0"
}
},
"lodash._getnative": {
"version": "3.9.1",
- "bundled": true,
- "extraneous": true
+ "bundled": true
},
"lodash.clonedeep": {
"version": "4.5.0",
@@ -56464,8 +56453,7 @@
},
"lodash.restparam": {
"version": "3.6.1",
- "bundled": true,
- "extraneous": true
+ "bundled": true
},
"lodash.union": {
"version": "4.6.0",
diff --git a/package.json b/package.json
index 96e0f1565..9af767ae2 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
},
"dependencies": {
"@bdelab/roam-fluency": "1.11.26",
- "@bdelab/roar-firekit": "^8.0.8",
+ "@bdelab/roar-firekit": "^9.0.1",
"@bdelab/roar-letter": "1.11.8",
"@bdelab/roar-multichoice": "^1.11.3",
"@bdelab/roar-pa": "2.2.4",
diff --git a/src/App.vue b/src/App.vue
index ae4ad4dfa..7316fa2a9 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -88,11 +88,13 @@ onBeforeMount(async () => {
authStore.setUser();
await authStore.initStateFromRedirect().then(async () => {
if (authStore.uid) {
- const userData = await fetchDocById('users', authStore.uid);
const userClaims = await fetchDocById('userClaims', authStore.uid);
- authStore.userData = userData;
authStore.userClaims = userClaims;
}
+ if (authStore.roarUid) {
+ const userData = await fetchDocById('users', authStore.roarUid);
+ authStore.userData = userData;
+ }
});
isAuthStoreReady.value = true;
});
diff --git a/src/components/CardAdministration.vue b/src/components/CardAdministration.vue
index 51cedd077..e87afe53d 100644
--- a/src/components/CardAdministration.vue
+++ b/src/components/CardAdministration.vue
@@ -19,7 +19,6 @@
button-class="p-button-outlined p-button-sm w-3rem h-3rem border-primary border-1 border-circle bg-transparent hover:surface-300"
:tooltip-options="{ position: 'top' }"
:pt="{ button: { size: 'small' } }"
- data-cy="button-speed-dial"
/>
@@ -94,7 +93,7 @@
-
+
-
+
+
userClaims.value?.claims?.minimalAdminOrgs);
const exhaustiveAdminOrgs = computed(() => userClaims.value?.claims?.adminOrgs);
const isSuperAdmin = computed(() => Boolean(userClaims.value?.claims?.super_admin));
const canQueryAdministrations = computed(() => {
return initialized.value && !isLoadingClaims.value;
});
+const isFetchingCachedAdministrations = ref(false);
+
/**
* Fetches administrations from the cache or the server
* @param {Array} queryKey - The query key to use for fetching the data
* @returns {Promise} - The cached or fetched data
*/
const getAdministrations = async (queryKey) => {
+ isFetchingCachedAdministrations.value = true;
+
let cachedData = await queryClient.getQueryData(queryKey);
if (!cachedData) {
cachedData = await queryClient.fetchQuery({
queryKey,
queryFn: () =>
- administrationPageFetcher(
- orderBy,
- ref(10000),
- ref(0),
- isSuperAdmin,
- adminOrgs,
- exhaustiveAdminOrgs,
- fetchTestAdministrations.value,
- ),
+ administrationPageFetcher(isSuperAdmin, exhaustiveAdminOrgs, fetchTestAdministrations.value, orderBy),
keepPreviousData: true,
enabled: canQueryAdministrations,
staleTime: 5 * 60 * 1000, // 5 minutes
@@ -193,6 +188,7 @@ const getAdministrations = async (queryKey) => {
testAdminsCached.value = true;
}
+ isFetchingCachedAdministrations.value = false;
return cachedData;
};
@@ -205,22 +201,9 @@ const { isLoading: isLoadingClaims, data: userClaims } = useQuery({
cacheTime: Infinity,
});
-const {
- isLoading: isLoadingAdministrations,
- isFetching: isFetchingAdministrations,
- data: administrations,
-} = useQuery({
- queryKey: ['administrations', uid, orderBy, ref(0), ref(10000), isSuperAdmin, administrationQueryKeyIndex],
- queryFn: () =>
- administrationPageFetcher(
- orderBy,
- ref(10000),
- ref(0),
- isSuperAdmin,
- adminOrgs,
- exhaustiveAdminOrgs,
- fetchTestAdministrations,
- ),
+const { isFetching: isFetchingAdministrations, data: administrations } = useQuery({
+ queryKey: ['administrations', uid, isSuperAdmin, administrationQueryKeyIndex, fetchTestAdministrations.value],
+ queryFn: () => administrationPageFetcher(isSuperAdmin, exhaustiveAdminOrgs, fetchTestAdministrations.value, orderBy),
keepPreviousData: true,
enabled: canQueryAdministrations,
staleTime: 5 * 60 * 1000, // 5 minutes
@@ -240,12 +223,14 @@ const {
},
});
+const fetchingAdministrations = computed(() => {
+ return isFetchingAdministrations.value || isFetchingCachedAdministrations.value;
+});
+
const filteredAdministrations = ref(administrations.value);
watch(fetchTestAdministrations, async (newState) => {
- const queryKey = newState
- ? ['testAdministrations', uid, orderBy, ref(0), ref(10000), isSuperAdmin, administrationQueryKeyIndex]
- : ['administrations', uid, orderBy, ref(0), ref(10000), isSuperAdmin, administrationQueryKeyIndex];
+ const queryKey = ['administrations', uid, isSuperAdmin, administrationQueryKeyIndex, newState];
filteredAdministrations.value = await getAdministrations(queryKey);
});
diff --git a/src/pages/HomeParticipant.vue b/src/pages/HomeParticipant.vue
index 397311a2d..89caf8f18 100644
--- a/src/pages/HomeParticipant.vue
+++ b/src/pages/HomeParticipant.vue
@@ -6,8 +6,8 @@
{{ $t('homeParticipant.loadingAssignments') }}
-
- {{ adminInfo.at(0).publicName || adminInfo.at(0).name }}
+
+ {{ assignmentInfo.at(0).publicName || assignmentInfo.at(0).name }}
(assignmentInfo.value ?? []).map((assignment) => assignment.id));
-const administrationQueryEnabled = computed(() => !isLoadingAssignments.value);
-
-const {
- isLoading: isLoadingAdmins,
- isFetching: isFetchingAdmins,
- data: adminInfo,
-} = useQuery({
- queryKey: ['administrations', uid, administrationIds],
- queryFn: () =>
- fetchDocsById(
- administrationIds.value.map((administrationId) => {
- return {
- collection: 'administrations',
- docId: administrationId,
- select: ['name', 'publicName', 'sequential', 'assessments', 'legal'],
- };
- }),
- ),
- keepPreviousData: true,
- enabled: administrationQueryEnabled,
- staleTime: 5 * 60 * 1000,
-});
-
const sortedAdminInfo = computed(() => {
- return [...(adminInfo.value ?? [])].sort((a, b) => a.name.localeCompare(b.name));
+ return [...(assignmentInfo.value ?? [])].sort((a, b) => (a.name || '').localeCompare(b.name || ''));
});
async function checkConsent() {
showConsent.value = false;
const dob = new Date(userData.value?.studentData?.dob);
- const grade = userData.value?.studentData.grade;
+ const grade = userData.value?.studentData?.grade;
const currentDate = new Date();
const age = currentDate.getFullYear() - dob.getFullYear();
const legal = selectedAdmin.value?.legal;
@@ -318,11 +294,11 @@ const { data: surveyResponsesData } = useQuery({
});
const isLoading = computed(() => {
- return isLoadingUserData.value || isLoadingAssignments.value || isLoadingAdmins.value || isLoadingTasks.value;
+ return isLoadingUserData.value || isLoadingAssignments.value || isLoadingTasks.value;
});
const isFetching = computed(() => {
- return isFetchingUserData.value || isFetchingAssignments.value || isFetchingAdmins.value || isFetchingTasks.value;
+ return isFetchingUserData.value || isFetchingAssignments.value || isFetchingTasks.value;
});
const noGamesAvailable = computed(() => {
@@ -393,7 +369,7 @@ const optionalAssessments = computed(() => {
const isSequential = computed(() => {
return (
_get(
- _find(adminInfo.value, (admin) => {
+ _find(assignmentInfo.value, (admin) => {
return admin.id === selectedAdmin.value.id;
}),
'sequential',
@@ -422,18 +398,22 @@ const studentInfo = computed(() => {
});
watch(
- [selectedAdmin, adminInfo],
+ [selectedAdmin, assignmentInfo],
async ([updateSelectedAdmin]) => {
if (updateSelectedAdmin) {
await checkConsent();
}
const selectedAdminId = selectedAdmin.value?.id;
- const allAdminIds = (adminInfo.value ?? []).map((admin) => admin.id);
+ const allAdminIds = (assignmentInfo.value ?? []).map((admin) => admin.id);
// If there is no selected admin or if the selected admin is not in the list
// of all administrations choose the first one after sorting alphabetically by publicName
if (allAdminIds.length > 0 && (!selectedAdminId || !allAdminIds.includes(selectedAdminId))) {
// Choose the first sorted administration
selectedAdmin.value = sortedAdminInfo.value[0];
+ } else {
+ // N.B. Although this seems redundant, we ensure that the selected admin is a fresh instance of the admin.
+ // This is relevant in the case that the game store does not flush properly.
+ selectedAdmin.value = sortedAdminInfo.value.find((admin) => admin.id === selectedAdminId);
}
},
{ immediate: true },
diff --git a/src/pages/HomeSelector.vue b/src/pages/HomeSelector.vue
index 17cc7c267..081b07b89 100644
--- a/src/pages/HomeSelector.vue
+++ b/src/pages/HomeSelector.vue
@@ -25,6 +25,7 @@ import { useRouter } from 'vue-router';
import { useAuthStore } from '@/store/auth';
import { useGameStore } from '@/store/game';
import _get from 'lodash/get';
+import _isArray from 'lodash/isArray';
import _isEmpty from 'lodash/isEmpty';
import _union from 'lodash/union';
import { storeToRefs } from 'pinia';
@@ -126,7 +127,8 @@ async function checkConsent() {
return;
}
- const legalDocs = _get(toRaw(consentStatus), consentDoc.version);
+ let legalDocs = _get(toRaw(consentStatus), consentDoc.version);
+ legalDocs = _isArray(legalDocs) ? legalDocs : [legalDocs];
const signedBeforeAugFirst = legalDocs.some((doc) => isSignedBeforeAugustFirst(doc.dateSigned));
if (signedBeforeAugFirst) {
@@ -143,11 +145,15 @@ function isSignedBeforeAugustFirst(signedDate) {
}
// Only check consent if the user data is loaded
-watch(userData, async (newValue) => {
- if (!_isEmpty(newValue)) {
- await checkConsent();
- }
-});
+watch(
+ [userData, userClaims],
+ async ([newUserData, newUserClaims]) => {
+ if (!_isEmpty(newUserData) && !_isEmpty(newUserClaims)) {
+ await checkConsent();
+ }
+ },
+ { immediate: true },
+);
onMounted(async () => {
if (requireRefresh.value) {
diff --git a/src/pages/ScoreReport.vue b/src/pages/ScoreReport.vue
index a6360a71c..fee44066b 100644
--- a/src/pages/ScoreReport.vue
+++ b/src/pages/ScoreReport.vue
@@ -125,7 +125,6 @@
:page-limit="pageLimit"
:loading="isLoadingScores || isFetchingScores"
:groupheaders="true"
- :lazy-pre-sorting="orderBy"
data-cy="roar-data-table"
@reset-filters="resetFilters"
@export-all="exportAll"
@@ -420,23 +419,6 @@ const handleExportToPdf = async () => {
return;
};
-const orderBy = ref([
- {
- field: 'user.grade',
- order: '1',
- },
- {
- field: 'user.lastName',
- order: '1',
- },
-]);
-// If this is a district report, make the schools column first sorted.
-if (props.orgType === 'district') {
- orderBy.value.unshift({
- order: '1',
- field: 'user.schoolName',
- });
-}
const filterSchools = ref([]);
const filterGrades = ref([]);
const pageLimit = ref(10);
@@ -648,7 +630,7 @@ const computeAssignmentAndRunData = computed(() => {
// swr: { support_level: 'Needs Extra Support', percentile: 10, raw: 10, reliable: true, engagementFlags: {}},
};
- let numAssignmentsCompleted = 0;
+ let numAssessmentsCompleted = 0;
const currRowScores = {};
for (const assessment of assignment.assessments) {
// General Logic to grab support level, scores, etc
@@ -667,7 +649,7 @@ const computeAssignmentAndRunData = computed(() => {
}
// Add filter tags for completed/incomplete
if (assessment.completedOn != undefined) {
- numAssignmentsCompleted += 1;
+ numAssessmentsCompleted += 1;
scoreFilterTags += ' Completed ';
} else if (assessment.startedOn != undefined) {
scoreFilterTags += ' Started ';
@@ -813,13 +795,38 @@ const computeAssignmentAndRunData = computed(() => {
// update scores for current row with computed object
currRow.scores = currRowScores;
- currRow.numAssignmentsCompleted = numAssignmentsCompleted;
+ currRow.numAssessmentsCompleted = numAssessmentsCompleted;
// push currRow to assignmentTableDataAcc
assignmentTableDataAcc.push(currRow);
}
- // sort by numAssignmentsCompleted
- assignmentTableDataAcc.sort((a, b) => b.numAssignmentsCompleted - a.numAssignmentsCompleted);
+ // sort by numAssessmentsCompleted
+ assignmentTableDataAcc.sort((a, b) => {
+ const completionDiff = b.numAssessmentsCompleted - a.numAssessmentsCompleted;
+ if (completionDiff !== 0) {
+ return completionDiff;
+ }
+
+ const schoolDiff = (a.user?.schoolName ?? '').localeCompare(b.user?.schoolName ?? '');
+ if (schoolDiff !== 0) {
+ return schoolDiff;
+ }
+
+ const gradeDiff = Number(a.user.grade) - Number(b.user.grade);
+ if (isNaN(gradeDiff)) {
+ const gradeA = a.user?.grade?.toString() ?? '';
+ const gradeB = b.user?.grade?.toString() ?? '';
+ const stringGradeDiff = gradeA.localeCompare(gradeB);
+ if (stringGradeDiff !== 0) {
+ return stringGradeDiff;
+ }
+ } else if (gradeDiff !== 0) {
+ return gradeDiff;
+ }
+
+ const lastNameDiff = (a.user?.lastName ?? '').localeCompare(b.user?.lastName ?? '');
+ return lastNameDiff;
+ });
const filteredRunsByTaskId = _pickBy(runsByTaskIdAcc, (scores, taskId) => {
return Object.keys(taskInfoById).includes(taskId);
diff --git a/src/pages/SignIn.vue b/src/pages/SignIn.vue
index ae4baa395..0f0a0e92c 100644
--- a/src/pages/SignIn.vue
+++ b/src/pages/SignIn.vue
@@ -187,11 +187,13 @@ const authWithGoogle = () => {
.signInWithGooglePopup()
.then(async () => {
if (authStore.uid) {
- const userData = await fetchDocById('users', authStore.uid);
const userClaims = await fetchDocById('userClaims', authStore.uid);
- authStore.userData = userData;
authStore.userClaims = userClaims;
}
+ if (authStore.roarUid) {
+ const userData = await fetchDocById('users', authStore.roarUid);
+ authStore.userData = userData;
+ }
})
.catch((e) => {
const errorCode = e.code;
@@ -213,9 +215,12 @@ const modalPassword = ref('');
const authWithClever = () => {
console.log('---> authWithClever');
- authStore.signInWithCleverRedirect();
+ if (process.env.NODE_ENV === 'development' && !window.Cypress) {
+ authStore.signInWithCleverPopup();
+ } else {
+ authStore.signInWithCleverRedirect();
+ }
spinner.value = true;
- // }
};
const authWithClassLink = () => {
@@ -225,7 +230,6 @@ const authWithClassLink = () => {
spinner.value = true;
} else {
authStore.signInWithClassLinkRedirect();
- // authStore.signInWithCleverPopup();
spinner.value = true;
}
};
@@ -248,11 +252,13 @@ const authWithEmail = (state) => {
.logInWithEmailAndPassword(creds)
.then(async () => {
if (authStore.uid) {
- const userData = await fetchDocById('users', authStore.uid);
const userClaims = await fetchDocById('userClaims', authStore.uid);
- authStore.userData = userData;
authStore.userClaims = userClaims;
}
+ if (authStore.roarUid) {
+ const userData = await fetchDocById('users', authStore.roarUid);
+ authStore.userData = userData;
+ }
spinner.value = true;
})