diff --git a/GenotypeAssays/resources/web/genotypeassays/window/PublishResultsWindow.js b/GenotypeAssays/resources/web/genotypeassays/window/PublishResultsWindow.js index bac163ba..1e5d754e 100644 --- a/GenotypeAssays/resources/web/genotypeassays/window/PublishResultsWindow.js +++ b/GenotypeAssays/resources/web/genotypeassays/window/PublishResultsWindow.js @@ -100,7 +100,7 @@ Ext4.define('GenotypeAssays.window.PublishResultsWindow', { }); }, this); - if (results.length == 1){ + if (results.length === 1){ field.setValue(results[0].id); } field.setDisabled(false); diff --git a/IDR/resources/referenceStudy/study/datasets/datasets_manifest.xml b/IDR/resources/referenceStudy/study/datasets/datasets_manifest.xml index a57ce797..ad696d8e 100644 --- a/IDR/resources/referenceStudy/study/datasets/datasets_manifest.xml +++ b/IDR/resources/referenceStudy/study/datasets/datasets_manifest.xml @@ -10,6 +10,9 @@ + + + diff --git a/IDR/resources/referenceStudy/study/datasets/datasets_metadata.xml b/IDR/resources/referenceStudy/study/datasets/datasets_metadata.xml index e5ae4f48..051a8eec 100644 --- a/IDR/resources/referenceStudy/study/datasets/datasets_metadata.xml +++ b/IDR/resources/referenceStudy/study/datasets/datasets_metadata.xml @@ -1035,4 +1035,61 @@ Kinship + + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + urn:ehr.labkey.org/#EndDate + + + varchar + urn:ehr.labkey.org/#CaseId + + + timestamp + + + varchar + + + integer + urn:ehr.labkey.org/#Project + + + integer + + + varchar + + + entityid + urn:ehr.labkey.org/#ObjectId + true + + + varchar + urn:ehr.labkey.org/#VetReview + + + timestamp + urn:ehr.labkey.org/#VetReviewDate + + + varchar + + + Cases +
diff --git a/MccColony/resources/queries/study/departure/.qview.xml b/MccColony/resources/queries/study/departure/.qview.xml index b14b6365..baacd2b4 100644 --- a/MccColony/resources/queries/study/departure/.qview.xml +++ b/MccColony/resources/queries/study/departure/.qview.xml @@ -5,7 +5,7 @@ - + diff --git a/mGAP/src/org/labkey/mgap/columnTransforms/JBrowseSessionTransform.java b/mGAP/src/org/labkey/mgap/columnTransforms/JBrowseSessionTransform.java index cd8bfa81..f3b0ca46 100644 --- a/mGAP/src/org/labkey/mgap/columnTransforms/JBrowseSessionTransform.java +++ b/mGAP/src/org/labkey/mgap/columnTransforms/JBrowseSessionTransform.java @@ -148,7 +148,8 @@ protected void addTracks(final String databaseId, String releaseId) FieldKey.fromString("url"), FieldKey.fromString("description"), FieldKey.fromString("isprimarytrack"), - FieldKey.fromString("vcfId/dataid/DataFileUrl") + FieldKey.fromString("vcfId/dataid/DataFileUrl"), + FieldKey.fromString("releaseId/luceneIndex/dataid/DataFileUrl") ); TableInfo tracksPerRelease = QueryService.get().getUserSchema(getContainerUser().getUser(), getContainerUser().getContainer(), mGAPSchema.NAME).getTable(mGAPSchema.TABLE_TRACKS_PER_RELEASE); @@ -270,7 +271,8 @@ private String getOrCreateJsonFile(Results rs, String fieldKey) throws SQLExcept if (isDefaultTrack) { - boolean hasLuceneIndex = StringUtils.trimToNull(rs.getString(FieldKey.fromString("luceneIndex/dataid/DataFileUrl"))) != null; + boolean hasLuceneIndex = StringUtils.trimToNull(rs.getString(FieldKey.fromString("releaseId/luceneIndex/dataid/DataFileUrl"))) != null; + getStatusLogger().info("Creating track JSON for primary track, has lucene index: " + hasLuceneIndex); row.put("trackJson", getTrackJson(hasLuceneIndex)); } else diff --git a/mGAP/src/org/labkey/mgap/mGAPController.java b/mGAP/src/org/labkey/mgap/mGAPController.java index a6afe145..e8f0ebbc 100644 --- a/mGAP/src/org/labkey/mgap/mGAPController.java +++ b/mGAP/src/org/labkey/mgap/mGAPController.java @@ -996,7 +996,7 @@ public URLHelper getRedirectURL(GenomeBrowserForm form) } else { - throw new IllegalArgumentException("Unable to find primary track for release: " + ctx.getString("mgapReleaseGUID")); + throw new IllegalArgumentException("Unable to find primary track for release: " + ctx.getString("mgapReleaseGUID") + ", with JBrowse ID: " + jbrowseDatabaseId); } } diff --git a/mGAP/src/org/labkey/mgap/mGapMaintenanceTask.java b/mGAP/src/org/labkey/mgap/mGapMaintenanceTask.java index 85a42523..5a858804 100644 --- a/mGAP/src/org/labkey/mgap/mGapMaintenanceTask.java +++ b/mGAP/src/org/labkey/mgap/mGapMaintenanceTask.java @@ -133,9 +133,10 @@ private void checkMGapFiles(Logger log, User u) if (!commandsToRun.isEmpty()) { - log.error("There are missing symlinks. Please run makeSymlinks.sh"); + File bashFile = new File(baseDir, "makeSymlinks.sh"); + log.error("There are missing symlinks. Please run " + bashFile.getPath()); - try (PrintWriter writer = PrintWriters.getPrintWriter(new File(baseDir, "makeSymlinks.sh"))) + try (PrintWriter writer = PrintWriters.getPrintWriter(bashFile)) { writer.println("#!/bin/bash"); writer.println("set -e"); diff --git a/mGAP/src/org/labkey/mgap/pipeline/mGapReleaseGenerator.java b/mGAP/src/org/labkey/mgap/pipeline/mGapReleaseGenerator.java index d01e83c7..278960bc 100644 --- a/mGAP/src/org/labkey/mgap/pipeline/mGapReleaseGenerator.java +++ b/mGAP/src/org/labkey/mgap/pipeline/mGapReleaseGenerator.java @@ -353,8 +353,9 @@ private File getTrackListFile(File outputDir) } @Override - public void complete(PipelineJob job, List inputs, List outputsCreated, SequenceAnalysisJobSupport support) throws PipelineJobException + public void complete(JobContext ctx, List inputs, List outputsCreated) throws PipelineJobException { + PipelineJob job = ctx.getJob(); if (outputsCreated.isEmpty()) { job.getLogger().error("no outputs found"); diff --git a/mcc/package-lock.json b/mcc/package-lock.json index 1293be11..3655ca75 100644 --- a/mcc/package-lock.json +++ b/mcc/package-lock.json @@ -10,28 +10,28 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@labkey/api": "^1.34.1", + "@labkey/api": "^1.35.0", "@mui/material": "^5.0.0", "@mui/styles": "^5.14.7", "@mui/x-data-grid": "^6.0.0", - "chart.js": "^4.4.3", + "chart.js": "^4.4.4", "react": "^17.0.2", "react-chartjs-2": "^5.2.0", "react-dom": "^17.0.2", - "react-tooltip": "^5.21.1", + "react-tooltip": "^5.28.0", "tsv": "^0.2.0", - "uuid": "^9.0.0" + "uuid": "^10.0.0" }, "devDependencies": { - "@labkey/build": "^7.3.0", - "@types/chart.js": "^2.9.37", + "@labkey/build": "^7.7.1", + "@types/chart.js": "^2.9.0", "@types/jest": "^29.0.0", "@types/jexl": "^2.3.1", "@types/jquery": "^3.0.0", "@types/node": "^18.17.1", "@types/react": "^17.0.68", "@types/react-dom": "^17.0.21", - "@types/tsv": "^0.2.1", + "@types/tsv": "^0.2.4", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "canvas": "^2.11.2", "enzyme": "^3.11.0", @@ -2059,20 +2059,20 @@ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "node_modules/@floating-ui/core": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz", - "integrity": "sha512-jk3WqquEJRlcyu7997NtR5PibI+y5bi+LS3hPmguVClypenMsCY3CBa3LAQnozRCtCrYWSEtAdiskpamuJRFOQ==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", "dependencies": { - "@floating-ui/utils": "^0.1.1" + "@floating-ui/utils": "^0.2.7" } }, "node_modules/@floating-ui/dom": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.1.tgz", - "integrity": "sha512-KwvVcPSXg6mQygvA1TjbN/gh///36kKtllIF8SUm0qpFj8+rvYrpvlYdL1JoA71SHpDqgSSdGOSoQ0Mp3uY5aw==", + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", "dependencies": { - "@floating-ui/core": "^1.4.1", - "@floating-ui/utils": "^0.1.1" + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.7" } }, "node_modules/@floating-ui/react-dom": { @@ -2088,9 +2088,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz", - "integrity": "sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==" + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -3014,132 +3014,68 @@ "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" }, "node_modules/@labkey/api": { - "version": "1.34.1", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.34.1.tgz", - "integrity": "sha512-82dASLsBCq2IGecCIYNqFqbC1x/v/qIpH3rvd8e5S/VsFYjtAn9Xkd13DnDe0eO6+i0r54nSlIfLMtBCBKBchQ==" + "version": "1.35.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.35.0.tgz", + "integrity": "sha512-s0b7upFJiNbbZVl8X/5vnvUgEc9//ohJk/Yy3R5KhcazbCvcY1E/MO5T5O+dZLLVr0G7VPZgV3imX49OAtqXNQ==" }, "node_modules/@labkey/build": { - "version": "7.3.0", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/build/-/@labkey/build-7.3.0.tgz", - "integrity": "sha512-b+Ox+0KEYhj9EANZ2A9Wm5wi+NW9mqVqc5+vbjidjSbHkNTUVUTMFj8gd9vBBnWTFY8h8+l8cIW8A/J20VmLYQ==", - "dev": true, - "dependencies": { - "@babel/core": "~7.24.3", - "@babel/plugin-transform-class-properties": "~7.24.1", - "@babel/plugin-transform-object-rest-spread": "~7.24.1", - "@babel/preset-env": "~7.24.3", - "@babel/preset-react": "~7.24.1", - "@babel/preset-typescript": "~7.24.1", - "@pmmmwh/react-refresh-webpack-plugin": "~0.5.11", - "ajv": "~8.12.0", + "version": "7.7.1", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/build/-/@labkey/build-7.7.1.tgz", + "integrity": "sha512-yyhnElpvFXc/OJ/G1kU6HsJczequIkfMhCv2P93VOUXMK5usYZFqi9z8nFXy6yL5b6Z9sFdzWYfLPE9gtSTnHg==", + "dev": true, + "dependencies": { + "@babel/core": "~7.24.9", + "@babel/plugin-transform-class-properties": "~7.24.7", + "@babel/plugin-transform-object-rest-spread": "~7.24.7", + "@babel/preset-env": "~7.24.8", + "@babel/preset-react": "~7.24.7", + "@babel/preset-typescript": "~7.24.7", + "@pmmmwh/react-refresh-webpack-plugin": "~0.5.15", + "ajv": "~8.17.1", "babel-loader": "~9.1.3", "bootstrap-sass": "~3.4.3", "circular-dependency-plugin": "~5.2.2", "copy-webpack-plugin": "~12.0.2", "cross-env": "~7.0.3", - "css-loader": "~6.10.0", + "css-loader": "~7.1.2", "fork-ts-checker-webpack-plugin": "~9.0.2", "html-webpack-plugin": "~5.6.0", - "mini-css-extract-plugin": "~2.8.1", - "react-refresh": "~0.14.0", + "mini-css-extract-plugin": "~2.9.0", + "react-refresh": "~0.14.2", "resolve-url-loader": "~5.0.0", - "rimraf": "~5.0.5", - "sass": "~1.72.0", - "sass-loader": "~14.1.1", - "style-loader": "~3.3.4", - "typescript": "~5.4.3", - "webpack": "~5.91.0", - "webpack-bundle-analyzer": "~4.10.1", + "rimraf": "~6.0.1", + "sass": "~1.77.8", + "sass-loader": "~14.2.1", + "style-loader": "~4.0.0", + "typescript": "~5.5.4", + "webpack": "~5.93.0", + "webpack-bundle-analyzer": "~4.10.2", "webpack-cli": "~5.1.4", "webpack-dev-server": "~5.0.4" } }, "node_modules/@labkey/build/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@labkey/build/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@labkey/build/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@labkey/build/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/@labkey/build/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@labkey/build/node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", @@ -4040,9 +3976,9 @@ "dev": true }, "node_modules/@types/tsv": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@types/tsv/-/tsv-0.2.1.tgz", - "integrity": "sha512-oMaoqKmWkG+1GZshzFDAAr7V1Pg2AVb/fZ8YcFBi23MLWywjVuf0wRLNYIPE248NMq5xF1/Dbo8AWdna32eaSw==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@types/tsv/-/tsv-0.2.4.tgz", + "integrity": "sha512-yP+y/Nz8dwvHD3UR3XprGp2Up0pA6fuq4f3kCoIPhYH4dzADBXnuM0BIYDkCok6b678zQhAWXS4vLcD5HGbjCg==", "dev": true }, "node_modules/@types/ws": { @@ -4364,10 +4300,10 @@ "acorn-walk": "^8.0.2" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, "peerDependencies": { "acorn": "^8" @@ -4955,9 +4891,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -4968,7 +4904,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -5002,6 +4938,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bonjour-service": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", @@ -5130,13 +5081,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5227,9 +5184,9 @@ } }, "node_modules/chart.js": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", - "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.4.tgz", + "integrity": "sha512-emICKGBABnxhMjUjlYRR12PmOXhJ2eJjEHL2/dZlWjxRAZT1D8xplLFq5M0tMQK8ja+wBS/tuVEJB5C6r7VxJA==", "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -5713,22 +5670,22 @@ } }, "node_modules/css-loader": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", - "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", + "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.4", - "postcss-modules-scope": "^3.1.1", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", "semver": "^7.5.4" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", @@ -5736,7 +5693,7 @@ }, "peerDependencies": { "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" + "webpack": "^5.27.0" }, "peerDependenciesMeta": { "@rspack/core": { @@ -5928,6 +5885,23 @@ "node": ">= 10" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -6355,6 +6329,27 @@ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", "dev": true }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", @@ -6592,37 +6587,37 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.20.0.tgz", + "integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.2.0", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.0", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -6642,6 +6637,15 @@ "ms": "2.0.0" } }, + "node_modules/express/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -6688,6 +6692,12 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -7244,9 +7254,12 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.6", @@ -7314,15 +7327,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7526,12 +7543,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7582,6 +7599,18 @@ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -8564,24 +8593,6 @@ "node": ">=8" } }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jest": { "version": "29.6.4", "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", @@ -10684,10 +10695,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -10714,12 +10728,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -10781,9 +10795,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz", - "integrity": "sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.1.tgz", + "integrity": "sha512-+Vyi+GCCOHnrJ2VPS+6aPoXN2k2jgUzDRhTFLjjTBn23qyXJXkjUWQgTL+mXpF5/A8ixLdCc6kWsoeOjKGejKQ==", "dev": true, "dependencies": { "schema-utils": "^4.0.0", @@ -11154,10 +11168,13 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11542,9 +11559,9 @@ "dev": true }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true }, "node_modules/path-type": { @@ -11687,9 +11704,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", - "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -12022,11 +12039,11 @@ "dev": true }, "node_modules/react-tooltip": { - "version": "5.21.1", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.21.1.tgz", - "integrity": "sha512-wJqF/yzK1wuJuy5/zAkVErFA609fVv1ZukhGjw44PcMvg9wL0jomnpQyz3qH1H7TWjz/wqO/OMc3ipQNjZ8zYg==", + "version": "5.28.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.28.0.tgz", + "integrity": "sha512-R5cO3JPPXk6FRbBHMO0rI9nkUG/JKfalBSQfZedZYzmqaZQgq7GLzF8vcCWx6IhUCKg0yPqJhXIzmIO5ff15xg==", "dependencies": { - "@floating-ui/dom": "^1.0.0", + "@floating-ui/dom": "^1.6.1", "classnames": "^2.3.0" }, "peerDependencies": { @@ -12638,9 +12655,9 @@ "dev": true }, "node_modules/sass": { - "version": "1.72.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.72.0.tgz", - "integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==", + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -12655,9 +12672,9 @@ } }, "node_modules/sass-loader": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-14.1.1.tgz", - "integrity": "sha512-QX8AasDg75monlybel38BZ49JP5Z+uSKfKwF2rO7S74BywaRmGQMUBw9dtkS+ekyM/QnP+NOrRYq8ABMZ9G8jw==", + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-14.2.1.tgz", + "integrity": "sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==", "dev": true, "dependencies": { "neo-async": "^2.6.2" @@ -12797,9 +12814,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "dependencies": { "debug": "2.6.9", @@ -12929,9 +12946,9 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.0.tgz", + "integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==", "dev": true, "dependencies": { "encodeurl": "~1.0.2", @@ -12943,12 +12960,74 @@ "node": ">= 0.8.0" } }, + "node_modules/serve-static/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-static/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-static/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serve-static/node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -12998,14 +13077,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13352,19 +13435,19 @@ } }, "node_modules/style-loader": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", - "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", "dev": true, "engines": { - "node": ">= 12.13.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.0.0" + "webpack": "^5.27.0" } }, "node_modules/stylis": { @@ -13864,9 +13947,9 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -14032,9 +14115,13 @@ } }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -14115,9 +14202,9 @@ } }, "node_modules/webpack": { - "version": "5.91.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.91.0.tgz", - "integrity": "sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==", + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -14126,10 +14213,10 @@ "@webassemblyjs/wasm-edit": "^1.12.1", "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", + "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.16.0", + "enhanced-resolve": "^5.17.0", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", diff --git a/mcc/package.json b/mcc/package.json index ecb1a82c..7853ca02 100644 --- a/mcc/package.json +++ b/mcc/package.json @@ -13,28 +13,28 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@labkey/api": "^1.34.1", + "@labkey/api": "^1.35.0", "@mui/material": "^5.0.0", "@mui/styles": "^5.14.7", "@mui/x-data-grid": "^6.0.0", - "chart.js": "^4.4.3", + "chart.js": "^4.4.4", "react": "^17.0.2", "react-chartjs-2": "^5.2.0", "react-dom": "^17.0.2", - "react-tooltip": "^5.21.1", + "react-tooltip": "^5.28.0", "tsv": "^0.2.0", - "uuid": "^9.0.0" + "uuid": "^10.0.0" }, "devDependencies": { - "@labkey/build": "^7.3.0", - "@types/chart.js": "^2.9.37", + "@labkey/build": "^7.7.1", + "@types/chart.js": "^2.9.0", "@types/jest": "^29.0.0", "@types/jexl": "^2.3.1", "@types/jquery": "^3.0.0", "@types/node": "^18.17.1", "@types/react": "^17.0.68", "@types/react-dom": "^17.0.21", - "@types/tsv": "^0.2.1", + "@types/tsv": "^0.2.4", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "canvas": "^2.11.2", "enzyme": "^3.11.0", diff --git a/mcc/resources/etls/mcc.xml b/mcc/resources/etls/mcc.xml index 6698470d..f9379952 100644 --- a/mcc/resources/etls/mcc.xml +++ b/mcc/resources/etls/mcc.xml @@ -121,8 +121,12 @@ startdate enddate centerName + totalLiving + totalLivingU24 totalBreedingPairs - totalLivingOffspring + totalBreedingPairsU24 + totalOffspring + totalOffspringU24 survivalRates marmosetsShipped @@ -139,7 +143,7 @@ date source destination - mccTransfer + mccRequestId objectid diff --git a/mcc/resources/queries/mcc/requestScores/Completed Requests.qview.xml b/mcc/resources/queries/mcc/requestScores/Completed Requests.qview.xml new file mode 100644 index 00000000..7eaf0242 --- /dev/null +++ b/mcc/resources/queries/mcc/requestScores/Completed Requests.qview.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mcc/resources/queries/study/demographicsMostRecentDeparture.query.xml b/mcc/resources/queries/study/demographicsMostRecentDeparture.query.xml new file mode 100644 index 00000000..7136f001 --- /dev/null +++ b/mcc/resources/queries/study/demographicsMostRecentDeparture.query.xml @@ -0,0 +1,25 @@ + + + + + + + true + true + + + /query/executeQuery.view?schemaName=study& + query.queryName=departure& + query.Id~eq=${Id}& + query.sort=-Date& + + + + MCC Request Id(s) + + + MostRecentDeparture +
+
+
+
diff --git a/mcc/resources/queries/study/demographicsMostRecentDeparture.sql b/mcc/resources/queries/study/demographicsMostRecentDeparture.sql new file mode 100644 index 00000000..f504e2de --- /dev/null +++ b/mcc/resources/queries/study/demographicsMostRecentDeparture.sql @@ -0,0 +1,9 @@ +select + + T1.Id, + max(T1.date) as MostRecentDeparture, + group_concat(distinct t1.mccRequestId) as mccRequestId + +FROM study.departure T1 +WHERE T1.qcstate.publicdata = true +GROUP BY T1.Id diff --git a/mcc/resources/queries/study/departure.query.xml b/mcc/resources/queries/study/departure.query.xml index 81ee0cfb..93a87f0c 100644 --- a/mcc/resources/queries/study/departure.query.xml +++ b/mcc/resources/queries/study/departure.query.xml @@ -29,9 +29,8 @@
- - MCC U24 Transfer? - false + + MCC Request ID diff --git a/mcc/resources/queries/study/departure/.qview.xml b/mcc/resources/queries/study/departure/.qview.xml index 86b40496..dd18300d 100644 --- a/mcc/resources/queries/study/departure/.qview.xml +++ b/mcc/resources/queries/study/departure/.qview.xml @@ -4,7 +4,7 @@ - + diff --git a/mcc/resources/referenceStudy/study/datasets/datasets_manifest.xml b/mcc/resources/referenceStudy/study/datasets/datasets_manifest.xml index ccac6c93..76d65856 100644 --- a/mcc/resources/referenceStudy/study/datasets/datasets_manifest.xml +++ b/mcc/resources/referenceStudy/study/datasets/datasets_manifest.xml @@ -10,6 +10,9 @@ + + + diff --git a/mcc/resources/referenceStudy/study/datasets/datasets_metadata.xml b/mcc/resources/referenceStudy/study/datasets/datasets_metadata.xml index 805e4f0c..4535b215 100644 --- a/mcc/resources/referenceStudy/study/datasets/datasets_metadata.xml +++ b/mcc/resources/referenceStudy/study/datasets/datasets_metadata.xml @@ -77,7 +77,6 @@ varchar - http://cpas.labkey.com/Study#ParticipantId varchar @@ -712,9 +711,8 @@ varchar - - boolean - false + + integer entityid @@ -1037,7 +1035,6 @@ varchar - http://cpas.labkey.com/Study#ParticipantId double @@ -1081,4 +1078,61 @@ Genetic Datasets + + + + varchar + http://cpas.labkey.com/Study#ParticipantId + + ptid + + + + timestamp + http://cpas.labkey.com/Study#VisitDate + http://cpas.labkey.com/Study#VisitDate + + + timestamp + urn:ehr.labkey.org/#EndDate + + + varchar + urn:ehr.labkey.org/#CaseId + + + timestamp + + + varchar + + + integer + urn:ehr.labkey.org/#Project + + + integer + + + varchar + + + entityid + urn:ehr.labkey.org/#ObjectId + true + + + varchar + urn:ehr.labkey.org/#VetReview + + + timestamp + urn:ehr.labkey.org/#VetReviewDate + + + varchar + + + Cases +
diff --git a/mcc/resources/schemas/dbscripts/postgresql/mcc-20.016-20.017.sql b/mcc/resources/schemas/dbscripts/postgresql/mcc-20.016-20.017.sql new file mode 100644 index 00000000..170e7768 --- /dev/null +++ b/mcc/resources/schemas/dbscripts/postgresql/mcc-20.016-20.017.sql @@ -0,0 +1,5 @@ +ALTER TABLE mcc.census DROP COLUMN totalLivingOffspring; + +ALTER TABLE mcc.census ADD totalOffspring int; +ALTER TABLE mcc.census ADD totalOffspringU24 int; +ALTER TABLE mcc.census ADD totalBreedingPairsU24 int; diff --git a/mcc/resources/schemas/dbscripts/postgresql/mcc-20.017-20.018.sql b/mcc/resources/schemas/dbscripts/postgresql/mcc-20.017-20.018.sql new file mode 100644 index 00000000..ec54e227 --- /dev/null +++ b/mcc/resources/schemas/dbscripts/postgresql/mcc-20.017-20.018.sql @@ -0,0 +1,2 @@ +ALTER TABLE mcc.census ADD totalLiving int; +ALTER TABLE mcc.census ADD totalLivingU24 int; diff --git a/mcc/resources/schemas/dbscripts/sqlserver/mcc-20.016-20.017.sql b/mcc/resources/schemas/dbscripts/sqlserver/mcc-20.016-20.017.sql new file mode 100644 index 00000000..5b5643f0 --- /dev/null +++ b/mcc/resources/schemas/dbscripts/sqlserver/mcc-20.016-20.017.sql @@ -0,0 +1,5 @@ +ALTER TABLE mcc.census DROP COLUMN totalLivingOffspring; + +ALTER TABLE mcc.census ADD totalOffspring int; +ALTER TABLE mcc.census ADD totalOffspringU24 int; +ALTER TABLE mcc.census ADD totalBreedingPairsU24 int; \ No newline at end of file diff --git a/mcc/resources/schemas/dbscripts/sqlserver/mcc-20.017-20.018.sql b/mcc/resources/schemas/dbscripts/sqlserver/mcc-20.017-20.018.sql new file mode 100644 index 00000000..ec54e227 --- /dev/null +++ b/mcc/resources/schemas/dbscripts/sqlserver/mcc-20.017-20.018.sql @@ -0,0 +1,2 @@ +ALTER TABLE mcc.census ADD totalLiving int; +ALTER TABLE mcc.census ADD totalLivingU24 int; diff --git a/mcc/resources/schemas/mcc.xml b/mcc/resources/schemas/mcc.xml index 412deaf9..86970ae2 100644 --- a/mcc/resources/schemas/mcc.xml +++ b/mcc/resources/schemas/mcc.xml @@ -700,6 +700,7 @@ /mcc/requestReview.view?requestId=${requestId}&mode=details Animal Request Reviews + DETAILED rowid @@ -776,7 +777,7 @@ - +
@@ -807,14 +808,27 @@ Center Name false + + # Living (Total) + + + # Living (U24) + - # Breeding Pairs + # In Active Breeding (Total) + + + # In Active Breeding (U24) - - # Living Offspring + + # Offspring (Total) + + + # Offspring (U24) Survival Rates + true # Animals Shipped diff --git a/mcc/resources/views/mccRequestSummary.html b/mcc/resources/views/mccRequestSummary.html index 1cb37799..3ef51431 100644 --- a/mcc/resources/views/mccRequestSummary.html +++ b/mcc/resources/views/mccRequestSummary.html @@ -31,10 +31,11 @@ LDK.Utils.getBasicQWP({ containerPath: ctx.MCCRequestContainer, - title: 'All Requests', + title: 'Completed Requests', frame: 'left-nav', schemaName: 'mcc', queryName: 'requestScores', + viewName: 'Completed Requests', showRecordSelectors: true, showDetailsColumn: true, maxRows: 10 diff --git a/mcc/resources/views/requestLogin.view.xml b/mcc/resources/views/requestLogin.view.xml index 8927f2fe..1bb1e023 100644 --- a/mcc/resources/views/requestLogin.view.xml +++ b/mcc/resources/views/requestLogin.view.xml @@ -1,5 +1,5 @@ - + diff --git a/mcc/resources/web/mcc/panel/MccImportPanel.js b/mcc/resources/web/mcc/panel/MccImportPanel.js index 705e8574..e00d01a6 100644 --- a/mcc/resources/web/mcc/panel/MccImportPanel.js +++ b/mcc/resources/web/mcc/panel/MccImportPanel.js @@ -903,6 +903,7 @@ Ext4.define('MCC.panel.MccImportPanel', { QCStateLabel: 'Completed', QCState: null, date: dateVal, + colony: f.sourceRecord.colony, destination: otherVal }); } else { diff --git a/mcc/resources/web/mcc/window/MarkShippedWindow.js b/mcc/resources/web/mcc/window/MarkShippedWindow.js index 3e3896e4..ad39ba21 100644 --- a/mcc/resources/web/mcc/window/MarkShippedWindow.js +++ b/mcc/resources/web/mcc/window/MarkShippedWindow.js @@ -83,11 +83,6 @@ Ext4.define('MCC.window.MarkShippedWindow', { } } } - },{ - xtype: 'checkbox', - itemId: 'isMccTransfer', - fieldLabel: 'Is MCC Transfer', - checked: true }, this.getAnimalIdFields()], buttons: [{ text: 'Submit', @@ -123,6 +118,11 @@ Ext4.define('MCC.window.MarkShippedWindow', { fields = fields.concat([{ xtype: 'displayfield', value: animalId, + },{ + xtype: 'ldk-integerfield', + minValue: 1, + itemId: 'requestId-' + animalId, + allowBlank: true },{ xtype: 'checkbox', itemId: 'usePreviousId-' + animalId, @@ -173,7 +173,6 @@ Ext4.define('MCC.window.MarkShippedWindow', { var effectiveDate = win.down('#effectiveDate').getValue(); var centerName = win.down('#centerName').getValue(); var targetFolder = win.down('#targetFolder').getValue(); - var isMccTransfer = win.down('#isMccTransfer').getValue(); if (!effectiveDate || !centerName || !targetFolder) { Ext4.Msg.alert('Error', 'Must provide date, center name, and target folder'); @@ -215,10 +214,14 @@ Ext4.define('MCC.window.MarkShippedWindow', { var commands = []; Ext4.Array.forEach(results.rows, function(row){ var effectiveId = win.down('#usePreviousId-' + row.Id).getValue() ? row.Id : win.down('#newId-' + row.Id).getValue(); + var requestId = win.down('#requestId-' + row.Id).getValue(); // This should be checked above, although perhaps case sensitivity could get involved: LDK.Assert.assertNotEmpty('Missing effective ID after query', effectiveId); - var shouldAddDeparture = !row['Id/MostRecentDeparture/MostRecentDeparture'] || row['Id/MostRecentDeparture/MostRecentDeparture'] !== Ext4.Date.format(row.effectiveDate, 'Y-m-d') || row.Id !== effectiveId; + var shouldAddDeparture = !row['Id/MostRecentDeparture/MostRecentDeparture'] || + row['Id/MostRecentDeparture/MostRecentDeparture'] !== Ext4.Date.format(row.effectiveDate, 'Y-m-d') || + row['Id/MostRecentDeparture/mccRequestId'] !== requestId || + row.Id !== effectiveId; if (shouldAddDeparture) { commands.push({ command: 'insert', @@ -229,7 +232,7 @@ Ext4.define('MCC.window.MarkShippedWindow', { date: effectiveDate, source: row.colony, destination: centerName, - mccTransfer: isMccTransfer, + mccRequestId: requestId, description: row.colony ? 'Original center: ' + row.colony : null, qcstate: null, objectId: null, diff --git a/mcc/src/client/RequestReview/components/ReadOnlyRequest.tsx b/mcc/src/client/RequestReview/components/ReadOnlyRequest.tsx index b6b02709..b492f30c 100644 --- a/mcc/src/client/RequestReview/components/ReadOnlyRequest.tsx +++ b/mcc/src/client/RequestReview/components/ReadOnlyRequest.tsx @@ -272,6 +272,35 @@ export default function ReadOnlyRequest(props: {requestData: AnimalRequestModel} {requestData.request.comments} + {requestData.shipments.length ? ( + <> + + Shipments: + + + +
+ + Source Colony + Date + MCC Id + + + + {requestData.shipments.map((shipment, idx) => { + return( + + {shipment.source} + {shipment.date ? new Intl.DateTimeFormat("en-US").format(new Date(shipment.date)) : ''} + {shipment.Id} + + ) + })} + +
+ + + ) : null } Status: diff --git a/mcc/src/client/U24Dashboard/Dashboard.tsx b/mcc/src/client/U24Dashboard/Dashboard.tsx index d0204d84..7acbdd8e 100644 --- a/mcc/src/client/U24Dashboard/Dashboard.tsx +++ b/mcc/src/client/U24Dashboard/Dashboard.tsx @@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react'; import { ActionURL, Filter, getServerContext, Query } from '@labkey/api'; import PieChart from '../components/dashboard/PieChart'; -import BarChart from '../components/dashboard/BarChart'; +import BarChart, { ColorType } from '../components/dashboard/BarChart'; import { ActiveElement, Chart, ChartEvent } from 'chart.js/dist/types/index'; export function Dashboard() { @@ -86,7 +86,7 @@ export function Dashboard() { containerPath: containerPath, schemaName: 'mcc', queryName: 'census', - columns: 'yearNo,startdate,enddate,centerName,totalBreedingPairs,totalLivingOffspring,survivalRates,marmosetsShipped', + columns: 'yearNo,startdate,enddate,centerName,totalLiving,totalLivingU24,totalBreedingPairs,totalBreedingPairsU24,totalOffspring,totalOffspringU24,marmosetsShipped', success: function(results) { if (isApiSubscribed) { setCensusRows(results.rows); @@ -99,7 +99,7 @@ export function Dashboard() { })) setBirthData(results.rows.flatMap(row => { - return Array(row.totalLivingOffspring).fill({ + return Array(row.totalOffspring).fill({ yearNo: row.yearNo, centerName: row.centerName }) @@ -164,7 +164,7 @@ export function Dashboard() {
-
Center (All Animals)
+
U24 Animals By Center
@@ -184,7 +184,7 @@ export function Dashboard() {
Age (Living Animals)
- +
@@ -194,7 +194,7 @@ export function Dashboard() {
U24 Births By Year
- +
@@ -202,7 +202,7 @@ export function Dashboard() {
U24 Breeding Pairs
- +
diff --git a/mcc/src/client/components/RequestUtils.tsx b/mcc/src/client/components/RequestUtils.tsx index f36bcd37..b25c4a8e 100644 --- a/mcc/src/client/components/RequestUtils.tsx +++ b/mcc/src/client/components/RequestUtils.tsx @@ -1,11 +1,12 @@ import React from 'react'; -import { Filter, Query } from '@labkey/api'; +import { Filter, getServerContext, Query } from '@labkey/api'; import { v4 as uuidv4 } from 'uuid'; export class AnimalRequestModel { request: AnimalRequestProps = new AnimalRequestProps(); coinvestigators: CoInvestigatorModel[] = []; cohorts: AnimalCohort[] = []; + shipments: ShipmentModel[] = []; dataLoaded: boolean = false; } @@ -51,6 +52,13 @@ export class AnimalRequestProps { comments: string; } +export class ShipmentModel { + Id: string; + date: string; + source: string; + objectid: string; +} + export class CoInvestigatorModel { rowid: number; requestId: string; @@ -70,6 +78,18 @@ export class AnimalCohort { uuid: string = uuidv4().toUpperCase(); } +function canReadMccStudy() { + const ctx = getServerContext().getModuleContext('mcc') || {}; + + return !!ctx.hasAnimalDataReadPermission && !!ctx.hasMccStudyReadPermission +} + +function getMccDataContainerPath() { + const ctx = getServerContext().getModuleContext('mcc') || {}; + + return ctx.hasAnimalDataReadPermission ? ctx.MCCContainer : null +} + export async function queryRequestInformation(requestId, handleFailure) { const requestData = new AnimalRequestModel() @@ -194,10 +214,43 @@ export async function queryRequestInformation(requestId, handleFailure) { }) })] + if (canReadMccStudy()) { + promises.push(new Promise((resolve, reject) => { + Query.selectRows({ + containerPath: getMccDataContainerPath(), + schemaName: "study", + queryName: "departure", + columns: [ + "Id", + "date", + "source", + "objectid" + ], + filterArray: [ + Filter.create('mccRequestId/objectId', requestId) + ], + success: function (resp) { + // NOTE: abort so that we preserve the default value of one empty row + if (!resp.rows.length) { + requestData.shipments = [] + } else { + requestData.shipments = resp.rows + } + + resolve(requestData.shipments) + }, + failure: handleFailure + }) + })) + } + return await Promise.all(promises).then(values => { requestData.request = values[0] requestData.coinvestigators = values[1] requestData.cohorts = values[2] + if (promises.length > 3) { + requestData.shipments = values[3] + } requestData.dataLoaded = true return(requestData) diff --git a/mcc/src/client/components/dashboard/BarChart.tsx b/mcc/src/client/components/dashboard/BarChart.tsx index 693dfd7c..92f5f99b 100644 --- a/mcc/src/client/components/dashboard/BarChart.tsx +++ b/mcc/src/client/components/dashboard/BarChart.tsx @@ -5,22 +5,35 @@ import { ActiveElement, ChartEvent } from 'chart.js/dist/types/index'; Chart.register(Legend, BarController, BarElement, CategoryScale, LinearScale, Tooltip); const colors = [ - 'rgb(42, 49, 116)', - 'rgb(75, 77, 135)', - 'rgb(110, 107, 155)', - 'rgb(147, 145, 181)', - 'rgb(194, 192, 210)' + "#E41A1C", + "#377EB8", + "#4DAF4A", + "#984EA3", + "#FF7F00", + "#FFFF33", + "#A65628", + "#F781BF", + "#999999" ]; -export default function BarChart(props: {demographics: [], fieldName: string, groupField?: string, indexAxis?: 'x' | 'y', onClick?: (event: ChartEvent, elements: ActiveElement[], chart: Chart) => void }) { +export enum ColorType { + PRIMARY = "primary", + GROUP = "group" +} + +export default function BarChart(props: {demographics: [], fieldName: string, groupField?: string, colorBy?: ColorType, showLegend?: boolean, indexAxis?: 'x' | 'y', missingDataTerm?: string, onClick?: (event: ChartEvent, elements: ActiveElement[], chart: Chart) => void }) { const canvas = useRef(null); const { demographics, fieldName, groupField, onClick} = props + const { colorBy = ColorType.PRIMARY } = props + const { showLegend = false } = props + const { missingDataTerm = 'None' } = props + const indexAxis: 'x' | 'y' = props.indexAxis || 'y' const collectedData = demographics.reduce((acc, curr: {}, idx) => { const value = curr[fieldName] === null ? 'Unknown' : curr[fieldName]; - const group = groupField == null ? 'counts' : curr[groupField] || 'None' + const group = groupField == null ? 'counts' : curr[groupField] || missingDataTerm if (!acc[group]) { acc[group] = {} @@ -35,13 +48,15 @@ export default function BarChart(props: {demographics: [], fieldName: string, gr return acc; }, {}); - const labels = [...new Set(Object.keys(collectedData).flatMap(groupName => Object.keys(collectedData[groupName])))]; - const dataArr: any[] = Object.keys(collectedData).map(groupName => { + const labels = [...new Set(Object.keys(collectedData).flatMap(groupName => Object.keys(collectedData[groupName])))].sort(Intl.Collator().compare) + const groupNames = Object.keys(collectedData).sort(Intl.Collator().compare) + + const dataArr: any[] = groupNames.map(groupName => { const dat = labels.map(label => collectedData[groupName] ? collectedData[groupName][label] || 0 : 0) return { label: groupName, data: dat, - backgroundColor: colors.slice(0, labels.length) + backgroundColor: colorBy == ColorType.PRIMARY ? colors.slice(0, labels.length) : colors[groupNames.indexOf(groupName)] } }); @@ -64,7 +79,8 @@ export default function BarChart(props: {demographics: [], fieldName: string, gr }, plugins: { legend: { - display: false + display: showLegend, + position: 'right' } } } diff --git a/mcc/src/client/components/dashboard/PieChart.tsx b/mcc/src/client/components/dashboard/PieChart.tsx index 55b422aa..b9a28ec8 100644 --- a/mcc/src/client/components/dashboard/PieChart.tsx +++ b/mcc/src/client/components/dashboard/PieChart.tsx @@ -10,11 +10,15 @@ import { Chart.register(ArcElement, Legend, PieController, Tooltip); const colors = [ - 'rgb(42, 49, 116)', - 'rgb(75, 77, 135)', - 'rgb(110, 107, 155)', - 'rgb(147, 145, 181)', - 'rgb(194, 192, 210)' + "#E41A1C", + "#377EB8", + "#4DAF4A", + "#984EA3", + "#FF7F00", + "#FFFF33", + "#A65628", + "#F781BF", + "#999999" ]; export default function PieChart(props) { @@ -34,7 +38,7 @@ export default function PieChart(props) { return acc; }, {}); - const labels = Object.keys(collectedData).sort(); + const labels = Object.keys(collectedData).sort(Intl.Collator().compare); const data = labels.map(label => collectedData[label]); useEffect(() => { diff --git a/mcc/src/org/labkey/mcc/MccModule.java b/mcc/src/org/labkey/mcc/MccModule.java index f421e3ab..673b3d95 100644 --- a/mcc/src/org/labkey/mcc/MccModule.java +++ b/mcc/src/org/labkey/mcc/MccModule.java @@ -29,7 +29,10 @@ import org.labkey.api.module.ModuleContext; import org.labkey.api.query.DefaultSchema; import org.labkey.api.query.QuerySchema; +import org.labkey.api.security.permissions.ReadPermission; import org.labkey.api.security.roles.RoleManager; +import org.labkey.api.study.Study; +import org.labkey.api.study.StudyService; import org.labkey.api.util.SystemMaintenance; import org.labkey.api.view.WebPartFactory; import org.labkey.api.view.template.ClientDependency; @@ -71,7 +74,7 @@ public String getName() @Override public @Nullable Double getSchemaVersion() { - return 20.016; + return 20.018; } @Override @@ -109,6 +112,17 @@ public JSONObject getPageContextJson(ContainerUser context) ret.put("hasRabPermission", requestContainer != null && requestContainer.hasPermission(context.getUser(), MccRabReviewPermission.class)); ret.put("hasFinalDecisionPermission", requestContainer != null && requestContainer.hasPermission(context.getUser(), MccFinalReviewPermission.class)); + Container dataContainer = MccManager.get().getMCCContainer(context.getContainer()); + ret.put("hasAnimalDataReadPermission", dataContainer != null && dataContainer.hasPermission(context.getUser(), ReadPermission.class)); + if (dataContainer != null) + { + Study s = StudyService.get().getStudy(dataContainer); + if (s != null) + { + ret.put("hasMccStudyReadPermission", s.hasPermission(context.getUser(), ReadPermission.class)); + } + } + return ret; } diff --git a/mcc/src/org/labkey/mcc/MccUserSchema.java b/mcc/src/org/labkey/mcc/MccUserSchema.java index a60589d6..00481485 100644 --- a/mcc/src/org/labkey/mcc/MccUserSchema.java +++ b/mcc/src/org/labkey/mcc/MccUserSchema.java @@ -116,9 +116,7 @@ else if (MccSchema.TABLE_REQUEST_SCORE.equalsIgnoreCase(name)) ret.addPermissionMapping(UpdatePermission.class, MccViewRequestsPermission.class); ret.addPermissionMapping(DeletePermission.class, MccRequestAdminPermission.class); - ret = ret.init(); - - return addScoreColumns(ret); + return ret.init(); } else if (MccSchema.TABLE_CENSUS.equalsIgnoreCase(name)) { @@ -218,9 +216,12 @@ private TableInfo getCensusQuery() " d.startdate,\n" + " d.enddate,\n" + " d.centerName,\n" + + " d.totalLiving,\n" + + " d.totalLivingU24,\n" + " d.totalBreedingPairs,\n" + - " d.totalLivingOffspring,\n" + - " d.survivalRates,\n" + + " d.totalBreedingPairsU24,\n" + + " d.totalOffspring,\n" + + " d.totalOffspringU24,\n" + " d.marmosetsShipped,\n" + " d.container\n" + "\n" + @@ -237,11 +238,11 @@ private TableInfo getDepartureQuery() " d.date,\n" + " d.source,\n" + " d.destination,\n" + - " d.mccTransfer,\n" + + " d.mccRequestId,\n" + " d.objectid,\n" + " d.container\n" + "\n" + - "FROM \"\".study.departure d WHERE d.qcstate.publicdata = true AND d.mccTransfer = true\n"; + "FROM \"\".study.departure d WHERE d.qcstate.publicdata = true AND d.mccRequestId IS NOT NULL\n"; return makeAggregatedQuery(TABLE_AGGREGATED_DEPARTURES, template); } @@ -317,41 +318,4 @@ private TableInfo makeAggregatedQuery(String queryName, String sqlTemplate) return ti; } - - private CustomPermissionsTable addScoreColumns(CustomPermissionsTable ti) - { - if (ti.getColumn("rabReviewStatus") == null) - { - SQLFragment sql = new SQLFragment("(SELECT CONCAT(COALESCE(CAST(sum(CASE WHEN r.review IS NULL THEN 0 ELSE 1 END) as varchar), '0'), ' of ', cast(count(*) as varchar), ' completed') as expr FROM mcc.requestReviews r WHERE r.requestId = " + ExprColumn.STR_TABLE_ALIAS + ".requestId)"); - ExprColumn newCol = new ExprColumn(ti, "rabReviewStatus", sql, JdbcType.VARCHAR, ti.getColumn("requestId")); - newCol.setSortFieldKeys(Collections.singletonList(FieldKey.fromString("pendingRabReviews"))); - - newCol.setLabel("RAB Review Status"); - newCol.setDisplayColumnFactory(colInfo -> { - return new DataColumn(colInfo) - { - @Override - public boolean isFilterable() - { - return false; - } - - @Override - public boolean isSortable() - { - return false; - } - }; - }); - - ti.addColumn(newCol); - - SQLFragment sql2 = new SQLFragment("(SELECT COALESCE(sum(CASE WHEN r.review IS NULL THEN 1 ELSE 0 END), -1) as expr FROM mcc.requestReviews r WHERE r.requestId = " + ExprColumn.STR_TABLE_ALIAS + ".requestId)"); - ExprColumn newCol2 = new ExprColumn(ti, "pendingRabReviews", sql2, JdbcType.INTEGER, ti.getColumn("requestId")); - newCol2.setLabel("Pending RAB Reviews"); - ti.addColumn(newCol2); - } - - return ti; - } } diff --git a/mcc/src/org/labkey/mcc/query/MccEhrCustomizer.java b/mcc/src/org/labkey/mcc/query/MccEhrCustomizer.java index dfb202f9..e917e4ac 100644 --- a/mcc/src/org/labkey/mcc/query/MccEhrCustomizer.java +++ b/mcc/src/org/labkey/mcc/query/MccEhrCustomizer.java @@ -5,6 +5,7 @@ import org.labkey.api.data.AbstractTableInfo; import org.labkey.api.data.BaseColumnInfo; import org.labkey.api.data.ColumnInfo; +import org.labkey.api.data.Container; import org.labkey.api.data.JdbcType; import org.labkey.api.data.MutableColumnInfo; import org.labkey.api.data.SQLFragment; @@ -15,7 +16,9 @@ import org.labkey.api.query.FieldKey; import org.labkey.api.query.LookupForeignKey; import org.labkey.api.query.QueryForeignKey; +import org.labkey.api.query.QueryService; import org.labkey.api.query.UserSchema; +import org.labkey.mcc.MccManager; import org.labkey.mcc.MccSchema; public class MccEhrCustomizer extends AbstractTableCustomizer @@ -48,6 +51,10 @@ else if (matches(table, "study", "kinship")) { customizeKinship((AbstractTableInfo)table); } + else if (matches(table, "study", "departure")) + { + customizeDeparture((AbstractTableInfo)table); + } } } @@ -62,6 +69,29 @@ private void customizeKinship(AbstractTableInfo ti) addMccAlias(ti, "Id2", "id2MccAlias", "Id 2 MCC Alias"); } + private void customizeDeparture(AbstractTableInfo ti) + { + MutableColumnInfo ci = ti.getMutableColumn("mccRequestId"); + if (ci == null) + { + return; + } + + Container requestContainer = MccManager.get().getMCCRequestContainer(ti.getUserSchema().getContainer()); + if (requestContainer == null) + { + return; + } + + final UserSchema us = getUserSchema(ti, MccSchema.NAME, requestContainer); + + ci.setFk(QueryForeignKey.from(us, null) + .table(us.getTable(MccSchema.TABLE_ANIMAL_REQUESTS)) + .container(us.getContainer()) + .key("rowid") + .display("rowid")); + } + private void customizeWeight(AbstractTableInfo ti) { String name = "weightGrams"; diff --git a/mcc/src/org/labkey/mcc/query/MccRequestCustomizer.java b/mcc/src/org/labkey/mcc/query/MccRequestCustomizer.java new file mode 100644 index 00000000..cf0f8607 --- /dev/null +++ b/mcc/src/org/labkey/mcc/query/MccRequestCustomizer.java @@ -0,0 +1,100 @@ +package org.labkey.mcc.query; + +import org.labkey.api.data.Container; +import org.labkey.api.data.DataColumn; +import org.labkey.api.data.JdbcType; +import org.labkey.api.data.SQLFragment; +import org.labkey.api.data.TableInfo; +import org.labkey.api.exp.api.StorageProvisioner; +import org.labkey.api.ldk.table.AbstractTableCustomizer; +import org.labkey.api.ldk.table.CustomPermissionsTable; +import org.labkey.api.query.ExprColumn; +import org.labkey.api.query.FieldKey; +import org.labkey.api.study.Dataset; +import org.labkey.api.study.Study; +import org.labkey.api.study.StudyService; +import org.labkey.mcc.MccManager; +import org.labkey.mcc.MccSchema; + +import java.util.Collections; + +public class MccRequestCustomizer extends AbstractTableCustomizer +{ + @Override + public void customize(TableInfo tableInfo) + { + if (tableInfo instanceof CustomPermissionsTable ati) + { + customizeRequestScore(ati); + } + } + + private void customizeRequestScore(CustomPermissionsTable ti) + { + if (ti.getColumn("rabReviewStatus") == null) + { + SQLFragment sql = new SQLFragment("(SELECT CONCAT(COALESCE(CAST(sum(CASE WHEN r.review IS NULL THEN 0 ELSE 1 END) as varchar), '0'), ' of ', cast(count(*) as varchar), ' completed') as expr FROM mcc.requestReviews r WHERE r.requestId = " + ExprColumn.STR_TABLE_ALIAS + ".requestId)"); + ExprColumn newCol = new ExprColumn(ti, "rabReviewStatus", sql, JdbcType.VARCHAR, ti.getColumn("requestId")); + newCol.setSortFieldKeys(Collections.singletonList(FieldKey.fromString("pendingRabReviews"))); + + newCol.setLabel("RAB Review Status"); + newCol.setDisplayColumnFactory(colInfo -> { + return new DataColumn(colInfo) + { + @Override + public boolean isFilterable() + { + return false; + } + + @Override + public boolean isSortable() + { + return false; + } + }; + }); + + ti.addColumn(newCol); + + SQLFragment sql2 = new SQLFragment("(SELECT COALESCE(sum(CASE WHEN r.review IS NULL THEN 1 ELSE 0 END), -1) as expr FROM mcc.requestReviews r WHERE r.requestId = " + ExprColumn.STR_TABLE_ALIAS + ".requestId)"); + ExprColumn newCol2 = new ExprColumn(ti, "pendingRabReviews", sql2, JdbcType.INTEGER, ti.getColumn("requestId")); + newCol2.setLabel("Pending RAB Reviews"); + ti.addColumn(newCol2); + } + + if (ti.getColumn("transferIds") == null) + { + Container dataContainer = MccManager.get().getMCCContainer(ti.getContainer()); + if (dataContainer != null) + { + Study s = StudyService.get().getStudy(dataContainer); + if (s == null) + { + return; + } + + Dataset d = s.getDatasetByName("departure"); + if (d == null) + { + _log.error("Unable to find study.departure"); + return; + } + + TableInfo dti = StorageProvisioner.createTableInfo(d.getDomain()); + + SQLFragment sql = new SQLFragment("(SELECT "). + append(ti.getSqlDialect().getGroupConcat(new SQLFragment("d." + dti.getColumn("participantid").getSelectName()), true, true, new SQLFragment("', '"))). + append(" as expr FROM "). + append(" mcc." + MccSchema.TABLE_ANIMAL_REQUESTS + " ar JOIN studydataset.").append(dti.getName()). + append(" d ON (d.mccRequestId = ar.rowId)"). + append(" WHERE ar.objectid = " + ExprColumn.STR_TABLE_ALIAS + ".requestId)"); + + ExprColumn newCol = new ExprColumn(ti, "transferIds", sql, JdbcType.VARCHAR, ti.getColumn("requestId")); + newCol.setLabel("Animal ID(s)"); + newCol.setWidth("100"); + ti.addColumn(newCol); + } + } + } +} diff --git a/primeseq/src/org/labkey/primeseq/analysis/MethylationRateComparisonHandler.java b/primeseq/src/org/labkey/primeseq/analysis/MethylationRateComparisonHandler.java index ef7dd9ae..633a0827 100644 --- a/primeseq/src/org/labkey/primeseq/analysis/MethylationRateComparisonHandler.java +++ b/primeseq/src/org/labkey/primeseq/analysis/MethylationRateComparisonHandler.java @@ -143,13 +143,13 @@ public SequenceOutputProcessor getProcessor() public class Processor implements SequenceOutputProcessor { @Override - public void complete(PipelineJob job, List inputs, List outputsCreated, SequenceAnalysisJobSupport support) throws PipelineJobException + public void complete(JobContext ctx, List inputs, List outputsCreated) throws PipelineJobException { for (SequenceOutputFile so : outputsCreated) { if (so.getFile().getName().endsWith(".bed") && METHYLATION_RATE_COMPARISON.equals(so.getCategory())) { - job.getLogger().debug("preparing JBrowse files: " + so.getFile().getName()); + ctx.getJob().getLogger().debug("preparing JBrowse files: " + so.getFile().getName()); JSONObject json = new JSONObject(); json.put("type", "JBrowse/View/Track/Wiggle/XYPlot"); @@ -157,7 +157,7 @@ public void complete(PipelineJob job, List inputs, List inputFiles, List outputsCreated, SequenceAnalysisJobSupport support) throws PipelineJobException + public void complete(JobContext ctx, List inputFiles, List outputsCreated) throws PipelineJobException { for (SequenceOutputFile so : outputsCreated) { if (CATEGORY.equals(so.getCategory())) { - CellHashingService.get().processMetrics(so, job, true); + CellHashingService.get().processMetrics(so, ctx.getJob(), true); } } - if (StringUtils.trimToNull(job.getParameters().get(TARGET_ASSAY)) == null) + if (StringUtils.trimToNull(ctx.getJob().getParameters().get(TARGET_ASSAY)) == null) { - job.getLogger().info("No assay selected, will not import"); + ctx.getJob().getLogger().info("No assay selected, will not import"); } else { - Integer assayId = ConvertHelper.convert(job.getParameters().get(TARGET_ASSAY), Integer.class); + Integer assayId = ConvertHelper.convert(ctx.getJob().getParameters().get(TARGET_ASSAY), Integer.class); if (assayId == null) { - throw new PipelineJobException("Invalid assay Id, cannot import: " + job.getParameters().get(TARGET_ASSAY)); + throw new PipelineJobException("Invalid assay Id, cannot import: " + ctx.getJob().getParameters().get(TARGET_ASSAY)); } boolean deleteExistingData = false; - if (job.getParameters().get(DELETE_EXISTING_ASSAY_DATA) != null) + if (ctx.getJob().getParameters().get(DELETE_EXISTING_ASSAY_DATA) != null) { - deleteExistingData = ConvertHelper.convert(job.getParameters().get(DELETE_EXISTING_ASSAY_DATA), Boolean.class); + deleteExistingData = ConvertHelper.convert(ctx.getJob().getParameters().get(DELETE_EXISTING_ASSAY_DATA), Boolean.class); } for (SequenceOutputFile so : inputFiles) { - AnalysisModel model = support.getCachedAnalysis(so.getAnalysis_id()); - new CellRangerVDJUtils(job.getLogger()).importAssayData(job, model, so.getFile(), job.getLogFile().getParentFile(), assayId, null, deleteExistingData); + AnalysisModel model = ctx.getSequenceSupport().getCachedAnalysis(so.getAnalysis_id()); + new CellRangerVDJUtils(ctx.getJob().getLogger()).importAssayData(ctx.getJob(), model, so.getFile(), ctx.getJob().getLogFile().getParentFile(), assayId, null, deleteExistingData); } } }