diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..a4f3d5ef8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +# These owners will be the default owners for everything in the repo. Unless a +# later match takes precedence, these owners will be requested for review when +# someone opens a pull request. +* @yeatmanlab/roar-maintainers diff --git a/.github/workflows/firebase-hosting-preview.yml b/.github/workflows/firebase-hosting-preview.yml index 73d107a44..edadd87ad 100644 --- a/.github/workflows/firebase-hosting-preview.yml +++ b/.github/workflows/firebase-hosting-preview.yml @@ -44,10 +44,6 @@ jobs: - name: Install dependencies run: npm ci - # Inject the App Check Debug Token into the .env file at build time - - name: Create .env file with App Check Debug Token - run: echo "VITE_APPCHECK_DEBUG_TOKEN=${{ secrets.VITE_APPCHECK_DEBUG_TOKEN }}" >> .env - - name: Build project run: npm run build diff --git a/.github/workflows/firebase-hosting-production.yml b/.github/workflows/firebase-hosting-production.yml index 18c0f8183..6226cccb6 100644 --- a/.github/workflows/firebase-hosting-production.yml +++ b/.github/workflows/firebase-hosting-production.yml @@ -30,6 +30,7 @@ jobs: PARTICIPANT_USERNAME: ${{ secrets.PARTICIPANT_USERNAME}} PARTICIPANT_PASSWORD: ${{ secrets.PARTICIPANT_PASSWORD }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VITE_APPCHECK_DEBUG_TOKEN: ${{ secrets.VITE_APPCHECK_DEBUG_TOKEN }} steps: - name: Checkout code uses: actions/checkout@v2 @@ -88,6 +89,7 @@ jobs: PARTICIPANT_USERNAME: ${{ secrets.PARTICIPANT_USERNAME}} PARTICIPANT_PASSWORD: ${{ secrets.PARTICIPANT_PASSWORD }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VITE_APPCHECK_DEBUG_TOKEN: ${{ secrets.VITE_APPCHECK_DEBUG_TOKEN }} steps: - name: Checkout code uses: actions/checkout@v2 @@ -126,6 +128,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 'lts/*' + - name: 'vite production build' env: NODE_OPTIONS: '--max_old_space_size=8192' diff --git a/.github/workflows/firebase-hosting-staging.yml b/.github/workflows/firebase-hosting-staging.yml index 88ab7facb..b7e2b300e 100644 --- a/.github/workflows/firebase-hosting-staging.yml +++ b/.github/workflows/firebase-hosting-staging.yml @@ -14,6 +14,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 'lts/*' + - name: 'vite staging build' env: NODE_OPTIONS: '--max_old_space_size=8192' diff --git a/firebase/admin/firestore.indexes.json b/firebase/admin/firestore.indexes.json index 289ecbee9..60b0f6239 100644 --- a/firebase/admin/firestore.indexes.json +++ b/firebase/admin/firestore.indexes.json @@ -2998,6 +2998,10 @@ "collectionGroup": "classes", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "schoolId", "order": "ASCENDING" @@ -3012,6 +3016,10 @@ "collectionGroup": "classes", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "schoolId", "order": "ASCENDING" @@ -3022,10 +3030,70 @@ } ] }, + { + "collectionGroup": "classes", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "lastRoarSync", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "districts", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "families", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, + { + "collectionGroup": "groups", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, + { + "fieldPath": "name", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "districtId", "order": "ASCENDING" @@ -3040,6 +3108,10 @@ "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "districtId", "order": "ASCENDING" @@ -3054,6 +3126,10 @@ "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "districtId", "order": "ASCENDING" @@ -3068,6 +3144,10 @@ "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "districtId", "order": "ASCENDING" @@ -3082,6 +3162,10 @@ "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "districtId", "order": "ASCENDING" @@ -3096,6 +3180,10 @@ "collectionGroup": "schools", "queryScope": "COLLECTION", "fields": [ + { + "fieldPath": "archived", + "order": "ASCENDING" + }, { "fieldPath": "districtId", "order": "ASCENDING" @@ -3106,6 +3194,20 @@ } ] }, + { + "collectionGroup": "schools", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districtId", + "order": "ASCENDING" + }, + { + "fieldPath": "lastRoarSync", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "users", "queryScope": "COLLECTION", @@ -3352,6 +3454,20 @@ } ] }, + { + "collectionGroup": "users", + "queryScope": "COLLECTION", + "fields": [ + { + "fieldPath": "districts.current", + "arrayConfig": "CONTAINS" + }, + { + "fieldPath": "archived", + "order": "ASCENDING" + } + ] + }, { "collectionGroup": "users", "queryScope": "COLLECTION", diff --git a/package-lock.json b/package-lock.json index 92522fc0b..0031d0673 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "roar-dashboard", - "version": "2.11.15", + "version": "2.11.18", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "roar-dashboard", - "version": "2.11.15", + "version": "2.11.18", "dependencies": { "@bdelab/roam-fluency": "1.11.26", - "@bdelab/roar-firekit": "^8.0.6", + "@bdelab/roar-firekit": "^8.0.8", "@bdelab/roar-letter": "1.11.5", "@bdelab/roar-multichoice": "^1.11.3", "@bdelab/roar-pa": "2.2.4", @@ -17,9 +17,9 @@ "@bdelab/roar-swr": "^1.12.1", "@bdelab/roar-utils": "^1.2.1", "@bdelab/roar-vocab": "^1.8.0", - "@bdelab/roav-crowding": "1.1.12", - "@bdelab/roav-mep": "^1.1.17", - "@bdelab/roav-ran": "^1.0.21", + "@bdelab/roav-crowding": "1.1.15", + "@bdelab/roav-mep": "^1.1.21", + "@bdelab/roav-ran": "^1.0.30", "@levante-framework/core-tasks": "^1.0.0-beta.18", "@sentry/browser": "^8.0.0", "@sentry/integrations": "^7.114.0", @@ -1849,9 +1849,10 @@ } }, "node_modules/@bdelab/roar-firekit": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-8.0.6.tgz", - "integrity": "sha512-dEOQyuzUMZ5F73+JVNrIWzOE+bZ8/wIWNMV/UhaWjh4nheHZo0UgdMziycLiVpCQYZaoX075eF4MW4r11cQtMA==", + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-8.0.8.tgz", + "integrity": "sha512-L69a3uQff8OYHFUP9i036N1NGon3y2YR0SLYbHwtNyulkXemtZqNbPxvJPokdupOOAsuw+MRMUxPJPJrxX8ocQ==", + "license": "ISC", "dependencies": { "@bdelab/roar-firekit": "^4.1.1", "crc-32": "^1.2.2", @@ -6500,9 +6501,9 @@ } }, "node_modules/@bdelab/roav-crowding": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@bdelab/roav-crowding/-/roav-crowding-1.1.12.tgz", - "integrity": "sha512-Eg2XuOHNnwiciN4LuIDnkrfjKFrJBezDeN+s1DI+ZKU8R5qEksWqhMrkectOrKrHCCVx5UaXlJvnmqEJHJRA6w==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@bdelab/roav-crowding/-/roav-crowding-1.1.15.tgz", + "integrity": "sha512-9AlO3aO5v+HUvVnKqJY81d82AkB7eDgi2w22V90g/pVBOV0PCueWN+6fIJVoJUY/T5Gq++AtRTJfXnooa+Zvug==", "dependencies": { "@bdelab/jscat": "^4.0.0", "@bdelab/roar-firekit": "^4.7.0", @@ -6647,9 +6648,9 @@ } }, "node_modules/@bdelab/roav-mep": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/@bdelab/roav-mep/-/roav-mep-1.1.17.tgz", - "integrity": "sha512-p/G1JvQ5Ppna26o5nJ0X2mPTYkl9qi/YUVbDYqKcvPTrxZnoWwlZoK+fgQ/zorBi9EIrg+A9u1/vUAdJL7y6qQ==", + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/@bdelab/roav-mep/-/roav-mep-1.1.22.tgz", + "integrity": "sha512-igr+XtQ1Mdn01kKyrUGexLkakHMdz58HTRzC5ZzujDm2C0agzjKG3OOEQdy+ICmvtDL0v8xzlauNSgelSj93PA==", "dependencies": { "@bdelab/jscat": "^4.0.0", "@bdelab/roar-firekit": "^4.7.0", @@ -6709,9 +6710,9 @@ } }, "node_modules/@bdelab/roav-ran": { - "version": "1.0.21", - "resolved": "https://registry.npmjs.org/@bdelab/roav-ran/-/roav-ran-1.0.21.tgz", - "integrity": "sha512-aT8pUBgWXdDutE6xccaz2LRvNaDQ8VbAHrBsqwljysbOplyxIhFhzmsmvfAD1RTPRG3saUMlexTHiPHRZymVFQ==", + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/@bdelab/roav-ran/-/roav-ran-1.0.30.tgz", + "integrity": "sha512-iltS7eUkKXW2pOKGODAVxtT3n5A7WxDY/QnKYiLDjODh9oHKkZcszsPGvc13OgslOmaYao9uxrshGcfHLzCEgQ==", "dependencies": { "@bdelab/jscat": "^1.0.5", "@bdelab/roar-firekit": "^4.7.0", @@ -6721,9 +6722,13 @@ "@jspsych/plugin-audio-keyboard-response": "^1.1.0", "@jspsych/plugin-call-function": "^1.1.2", "@jspsych/plugin-fullscreen": "^1.1.0", + "@mediapipe/face_mesh": "^0.4.1633559619", + "@rollup/plugin-url": "^8.0.2", + "@rollup/plugin-wasm": "^6.2.2", "@sentry/browser": "^7.111.0", "@sentry/integrations": "^7.111.0", "@sentry/wasm": "^7.111.0", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", "@xenova/transformers": "^1.3.2", "dotenv": "^16.4.5", "fscreen": "^1.2.0", @@ -6732,11 +6737,18 @@ "i18next-browser-languagedetector": "^7.0.1", "jspsych": "^7.2.1", "lodash": "^4.17.21", + "ml-regression-polynomial": "^3.0.0", + "ndarray": "^1.0.19", + "ndarray-ops": "^1.2.2", "node-fetch": "^2.6.6", + "onnxjs": "^0.1.8", + "onnxruntime-web": "^1.17.1", "papaparse": "^5.4.1", "regenerator-runtime": "^0.13.9", "roarr": "^7.21.1", - "store2": "^2.13.2" + "store2": "^2.13.2", + "webpack": "^5.70.0", + "webpack-dev-server": "^4.7.4" } }, "node_modules/@bdelab/roav-ran/node_modules/@bdelab/jscat": { @@ -39051,9 +39063,9 @@ } }, "@bdelab/roar-firekit": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-8.0.6.tgz", - "integrity": "sha512-dEOQyuzUMZ5F73+JVNrIWzOE+bZ8/wIWNMV/UhaWjh4nheHZo0UgdMziycLiVpCQYZaoX075eF4MW4r11cQtMA==", + "version": "8.0.8", + "resolved": "https://registry.npmjs.org/@bdelab/roar-firekit/-/roar-firekit-8.0.8.tgz", + "integrity": "sha512-L69a3uQff8OYHFUP9i036N1NGon3y2YR0SLYbHwtNyulkXemtZqNbPxvJPokdupOOAsuw+MRMUxPJPJrxX8ocQ==", "requires": { "@bdelab/roar-firekit": "^4.1.1", "crc-32": "^1.2.2", @@ -42968,9 +42980,9 @@ } }, "@bdelab/roav-crowding": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@bdelab/roav-crowding/-/roav-crowding-1.1.12.tgz", - "integrity": "sha512-Eg2XuOHNnwiciN4LuIDnkrfjKFrJBezDeN+s1DI+ZKU8R5qEksWqhMrkectOrKrHCCVx5UaXlJvnmqEJHJRA6w==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@bdelab/roav-crowding/-/roav-crowding-1.1.15.tgz", + "integrity": "sha512-9AlO3aO5v+HUvVnKqJY81d82AkB7eDgi2w22V90g/pVBOV0PCueWN+6fIJVoJUY/T5Gq++AtRTJfXnooa+Zvug==", "requires": { "@bdelab/jscat": "^4.0.0", "@bdelab/roar-firekit": "^4.7.0", @@ -43096,9 +43108,9 @@ } }, "@bdelab/roav-mep": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/@bdelab/roav-mep/-/roav-mep-1.1.17.tgz", - "integrity": "sha512-p/G1JvQ5Ppna26o5nJ0X2mPTYkl9qi/YUVbDYqKcvPTrxZnoWwlZoK+fgQ/zorBi9EIrg+A9u1/vUAdJL7y6qQ==", + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/@bdelab/roav-mep/-/roav-mep-1.1.22.tgz", + "integrity": "sha512-igr+XtQ1Mdn01kKyrUGexLkakHMdz58HTRzC5ZzujDm2C0agzjKG3OOEQdy+ICmvtDL0v8xzlauNSgelSj93PA==", "requires": { "@bdelab/jscat": "^4.0.0", "@bdelab/roar-firekit": "^4.7.0", @@ -43160,9 +43172,9 @@ } }, "@bdelab/roav-ran": { - "version": "1.0.21", - "resolved": "https://registry.npmjs.org/@bdelab/roav-ran/-/roav-ran-1.0.21.tgz", - "integrity": "sha512-aT8pUBgWXdDutE6xccaz2LRvNaDQ8VbAHrBsqwljysbOplyxIhFhzmsmvfAD1RTPRG3saUMlexTHiPHRZymVFQ==", + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/@bdelab/roav-ran/-/roav-ran-1.0.30.tgz", + "integrity": "sha512-iltS7eUkKXW2pOKGODAVxtT3n5A7WxDY/QnKYiLDjODh9oHKkZcszsPGvc13OgslOmaYao9uxrshGcfHLzCEgQ==", "requires": { "@bdelab/jscat": "^1.0.5", "@bdelab/roar-firekit": "^4.7.0", @@ -43172,9 +43184,13 @@ "@jspsych/plugin-audio-keyboard-response": "^1.1.0", "@jspsych/plugin-call-function": "^1.1.2", "@jspsych/plugin-fullscreen": "^1.1.0", + "@mediapipe/face_mesh": "^0.4.1633559619", + "@rollup/plugin-url": "^8.0.2", + "@rollup/plugin-wasm": "^6.2.2", "@sentry/browser": "^7.111.0", "@sentry/integrations": "^7.111.0", "@sentry/wasm": "^7.111.0", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", "@xenova/transformers": "^1.3.2", "dotenv": "^16.4.5", "fscreen": "^1.2.0", @@ -43183,11 +43199,18 @@ "i18next-browser-languagedetector": "^7.0.1", "jspsych": "^7.2.1", "lodash": "^4.17.21", + "ml-regression-polynomial": "^3.0.0", + "ndarray": "^1.0.19", + "ndarray-ops": "^1.2.2", "node-fetch": "^2.6.6", + "onnxjs": "^0.1.8", + "onnxruntime-web": "^1.17.1", "papaparse": "^5.4.1", "regenerator-runtime": "^0.13.9", "roarr": "^7.21.1", - "store2": "^2.13.2" + "store2": "^2.13.2", + "webpack": "^5.70.0", + "webpack-dev-server": "^4.7.4" }, "dependencies": { "@bdelab/jscat": { diff --git a/package.json b/package.json index 3f1a47f70..e81006abe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "roar-dashboard", "private": true, - "version": "2.11.15", + "version": "2.11.18", "type": "module", "scripts": { "build": "export VITE_FIREBASE_DATA_SOURCE=live && vite build", @@ -32,7 +32,7 @@ }, "dependencies": { "@bdelab/roam-fluency": "1.11.26", - "@bdelab/roar-firekit": "^8.0.6", + "@bdelab/roar-firekit": "^8.0.8", "@bdelab/roar-letter": "1.11.5", "@bdelab/roar-multichoice": "^1.11.3", "@bdelab/roar-pa": "2.2.4", @@ -40,9 +40,9 @@ "@bdelab/roar-swr": "^1.12.1", "@bdelab/roar-utils": "^1.2.1", "@bdelab/roar-vocab": "^1.8.0", - "@bdelab/roav-crowding": "1.1.12", - "@bdelab/roav-mep": "^1.1.17", - "@bdelab/roav-ran": "^1.0.21", + "@bdelab/roav-crowding": "1.1.15", + "@bdelab/roav-mep": "^1.1.21", + "@bdelab/roav-ran": "^1.0.30", "@levante-framework/core-tasks": "^1.0.0-beta.18", "@sentry/browser": "^8.0.0", "@sentry/integrations": "^7.114.0", diff --git a/src/components/CardAdministration.vue b/src/components/CardAdministration.vue index fb2df96ca..51cedd077 100644 --- a/src/components/CardAdministration.vue +++ b/src/components/CardAdministration.vue @@ -396,7 +396,7 @@ const fetchTreeOrgs = async () => { treeTableOrgs.push(...dsgfOrgs.filter((node) => node.data.orgType === 'group')); treeTableOrgs.push(...dsgfOrgs.filter((node) => node.data.orgType === 'family')); - treeTableOrgs.forEach((node) => { + (treeTableOrgs ?? []).forEach((node) => { // Sort the schools by existance of stats then alphabetically if (node.children) { node.children.sort((a, b) => { @@ -499,8 +499,8 @@ const onExpand = async (node) => { }); // Sort the classes by existance of stats then alphabetically - newNodes.forEach((districtNode) => { - districtNode.children.forEach((schoolNode) => { + (newNodes ?? []).forEach((districtNode) => { + (districtNode?.children ?? []).forEach((schoolNode) => { if (schoolNode.children) { schoolNode.children.sort((a, b) => { if (!a.data.stats) return 1; diff --git a/src/components/EditOrgsForm.vue b/src/components/EditOrgsForm.vue new file mode 100644 index 000000000..86888062a --- /dev/null +++ b/src/components/EditOrgsForm.vue @@ -0,0 +1,206 @@ + + + diff --git a/src/components/ListOrgs.vue b/src/components/ListOrgs.vue index a80f42660..decea127e 100644 --- a/src/components/ListOrgs.vue +++ b/src/components/ListOrgs.vue @@ -61,6 +61,7 @@ @export-all="exportAll" @selected-org-id="showCode" @export-org-users="(orgId) => exportOrgUsers(orgId)" + @edit-button="onEditButtonClick($event)" /> @@ -112,6 +113,35 @@ + + + +