diff --git a/.gitignore b/.gitignore index 6c760e0a..a3da684b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +src/config.json deploy.log src/app/**/*.js diff --git a/README.md b/README.md index d0e1d970..b2257e0a 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ For setup information, consult our [Wiki](https://github.com/vitrivr/vitrivr-ng/ ## Config -There is a `config.json` which enables configuration of the UI to a certain extend. -While we provide a sensible [default config](src/config.json), the -some default values are better explored in the [code](src/app/shared/model/config/config.model.ts). +We follow a zero-config approach, where everything has reasonable defaults. +There is a `src/config.template.json` file which you can copy to `src/config.json` and modify if you have custom needs. +The default values are in the [code](src/app/shared/model/config/config.model.ts). Information about the configuration can be found in [the wiki](https://github.com/vitrivr/vitrivr-ng/wiki/Configuration). ## Development server diff --git a/package-lock.json b/package-lock.json index 29241341..4e0d3245 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@angular/common": "13.3.2", "@angular/compiler": "13.3.2", "@angular/core": "13.3.2", - "@angular/flex-layout": "12.0.0-beta.35", + "@angular/flex-layout": "13.0.0-beta.38", "@angular/forms": "13.3.2", "@angular/material": "13.3.2", "@angular/platform-browser": "13.3.2", @@ -26,10 +26,10 @@ "@types/leaflet": "1.7.5", "@types/openseadragon": "^2.4.7", "@types/three": "0.134.0", - "@videogular/ngx-videogular": "5.0.0", + "@videogular/ngx-videogular": "5.0.1", "core-js": "3.19.1", "deepmerge": "4.2.2", - "dexie": "^3.0.3", + "dexie": "^3.2.2", "flatted": "3.2.4", "jszip": "3.7.1", "leaflet": "1.7.1", @@ -37,7 +37,7 @@ "ngx-color-picker": "11.0.0", "ngx-infinite-scroll": "10.0.1", "node": "^17.4.0", - "npm": "^8.1.2", + "npm": "^8.11.0", "openapi-generator": "^0.1.39", "openseadragon": "^2.4.2", "rxjs": "7.5.5", @@ -804,18 +804,18 @@ } }, "node_modules/@angular/flex-layout": { - "version": "12.0.0-beta.35", - "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-12.0.0-beta.35.tgz", - "integrity": "sha512-nPi2MGDFuCacwWHqxF/G7lUJd2X99HbLjjUvKXnyLwyCIVgH1sfS52su2wYbVYWJRqAVAB2/VMlrtW8Khr8hDA==", + "version": "13.0.0-beta.38", + "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-13.0.0-beta.38.tgz", + "integrity": "sha512-kcWb7CcoHbvw7fjo/knizWVmSSmvaTnr8v1ML6zOdxu1PK9UPPOcOS8RTm6fy61zoC2LABivP1/6Z2jF5XfpdQ==", "dependencies": { - "tslib": "^2.1.0" + "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": "^12.0.0", - "@angular/common": ">=12.0.0", - "@angular/core": ">=12.0.0", - "@angular/platform-browser": ">=12.0.0", - "rxjs": "^6.0.0 || ^7.0.0" + "@angular/cdk": "^13.0.0", + "@angular/common": "^13.0.0", + "@angular/core": "^13.0.0", + "@angular/platform-browser": "^13.0.0", + "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/forms": { @@ -4749,19 +4749,19 @@ } }, "node_modules/@videogular/ngx-videogular": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@videogular/ngx-videogular/-/ngx-videogular-5.0.0.tgz", - "integrity": "sha512-xdhB5ymXDTfaUKzoJAoGS8UYUgqHMiJpIUSlf9hhwTXNiOAZ5fcXlvJ4RG3WurAtQx0Ct7ua3sdBkV23ZVxjgg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@videogular/ngx-videogular/-/ngx-videogular-5.0.1.tgz", + "integrity": "sha512-ITA3GZBzh0XoCAGQzucAX+q7h72z43kG8G9ZspLMAfyvl2Z2MEHMfC6ct6hzSWTfqr48x62Avl935dcdl/NgXQ==", "dependencies": { "tslib": "^1.11.1 || ^2.0.0" }, "peerDependencies": { - "@angular/common": ">=8.0.0 <13.0.0", - "@angular/core": ">=8.0.0 <13.0.0", - "@angular/platform-browser-dynamic": ">=8.0.0 <13.0.0", - "core-js": ">=2.5.4 <=3.15.1", + "@angular/common": ">=8.0.0", + "@angular/core": ">=8.0.0", + "@angular/platform-browser-dynamic": ">=8.0.0", + "core-js": ">=2.5.4", "rxjs": ">=6.5.4", - "zone.js": ">=0.10.2 <=0.11.4" + "zone.js": ">=0.10.2" } }, "node_modules/@webassemblyjs/ast": { @@ -5310,9 +5310,9 @@ "dev": true }, "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, "dependencies": { "lodash": "^4.17.14" @@ -7279,9 +7279,9 @@ } }, "node_modules/dexie": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dexie/-/dexie-3.0.3.tgz", - "integrity": "sha512-BSFhGpngnCl1DOr+8YNwBDobRMH0ziJs2vts69VilwetHYOtEDcLqo7d/XiIphM0tJZ2rPPyAGd31lgH2Ln3nw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/dexie/-/dexie-3.2.2.tgz", + "integrity": "sha512-q5dC3HPmir2DERlX+toCBbHQXW5MsyrFqPFcovkH9N2S/UW/H3H5AWAB6iEOExeraAu+j+zRDG+zg/D7YhH0qg==", "engines": { "node": ">=6.0" } @@ -11175,20 +11175,19 @@ } }, "node_modules/npm": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/npm/-/npm-8.5.4.tgz", - "integrity": "sha512-VnGLT4t88cUE78lLw5kxBwtLn2/Sx6O7Uw9dYwmq6AnF/taWHyMYQgDzUEsLhaXAVH7prG+sjG+MvxlHdIasgg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-8.11.0.tgz", + "integrity": "sha512-4qmtwHa28J4SPmwCNoQI07KIF/ljmBhhuqG+xNXsIIRpwdKB5OXkMIGfH6KlThR6kzusxlkgR7t1haFDB88dcQ==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", "@npmcli/ci-detect", "@npmcli/config", + "@npmcli/fs", "@npmcli/map-workspaces", "@npmcli/package-json", "@npmcli/run-script", "abbrev", - "ansicolors", - "ansistyles", "archy", "cacache", "chalk", @@ -11252,77 +11251,76 @@ "write-file-atomic" ], "dependencies": { - "@isaacs/string-locale-compare": "*", - "@npmcli/arborist": "*", - "@npmcli/ci-detect": "*", - "@npmcli/config": "*", - "@npmcli/map-workspaces": "*", - "@npmcli/package-json": "*", - "@npmcli/run-script": "*", - "abbrev": "*", - "ansicolors": "*", - "ansistyles": "*", - "archy": "*", - "cacache": "*", - "chalk": "*", - "chownr": "*", - "cli-columns": "*", - "cli-table3": "*", - "columnify": "*", - "fastest-levenshtein": "*", - "glob": "*", - "graceful-fs": "*", - "hosted-git-info": "*", - "ini": "*", - "init-package-json": "*", - "is-cidr": "*", - "json-parse-even-better-errors": "*", - "libnpmaccess": "*", - "libnpmdiff": "*", - "libnpmexec": "*", - "libnpmfund": "*", - "libnpmhook": "*", - "libnpmorg": "*", - "libnpmpack": "*", - "libnpmpublish": "*", - "libnpmsearch": "*", - "libnpmteam": "*", - "libnpmversion": "*", - "make-fetch-happen": "*", - "minipass": "*", - "minipass-pipeline": "*", - "mkdirp": "*", - "mkdirp-infer-owner": "*", - "ms": "*", - "node-gyp": "*", - "nopt": "*", - "npm-audit-report": "*", - "npm-install-checks": "*", - "npm-package-arg": "*", - "npm-pick-manifest": "*", - "npm-profile": "*", - "npm-registry-fetch": "*", - "npm-user-validate": "*", - "npmlog": "*", - "opener": "*", - "pacote": "*", - "parse-conflict-json": "*", - "proc-log": "*", - "qrcode-terminal": "*", - "read": "*", - "read-package-json": "*", - "read-package-json-fast": "*", - "readdir-scoped-modules": "*", - "rimraf": "*", - "semver": "*", - "ssri": "*", - "tar": "*", - "text-table": "*", - "tiny-relative-date": "*", - "treeverse": "*", - "validate-npm-package-name": "*", - "which": "*", - "write-file-atomic": "*" + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^5.0.4", + "@npmcli/ci-detect": "^2.0.0", + "@npmcli/config": "^4.1.0", + "@npmcli/fs": "^2.1.0", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/package-json": "^2.0.0", + "@npmcli/run-script": "^3.0.1", + "abbrev": "~1.1.1", + "archy": "~1.0.0", + "cacache": "^16.1.0", + "chalk": "^4.1.2", + "chownr": "^2.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.2", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.12", + "glob": "^8.0.1", + "graceful-fs": "^4.2.10", + "hosted-git-info": "^5.0.0", + "ini": "^3.0.0", + "init-package-json": "^3.0.2", + "is-cidr": "^4.0.2", + "json-parse-even-better-errors": "^2.3.1", + "libnpmaccess": "^6.0.2", + "libnpmdiff": "^4.0.2", + "libnpmexec": "^4.0.2", + "libnpmfund": "^3.0.1", + "libnpmhook": "^8.0.2", + "libnpmorg": "^4.0.2", + "libnpmpack": "^4.0.2", + "libnpmpublish": "^6.0.2", + "libnpmsearch": "^5.0.2", + "libnpmteam": "^4.0.2", + "libnpmversion": "^3.0.1", + "make-fetch-happen": "^10.1.5", + "minipass": "^3.1.6", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "ms": "^2.1.2", + "node-gyp": "^9.0.0", + "nopt": "^5.0.0", + "npm-audit-report": "^3.0.0", + "npm-install-checks": "^5.0.0", + "npm-package-arg": "^9.0.2", + "npm-pick-manifest": "^7.0.1", + "npm-profile": "^6.0.3", + "npm-registry-fetch": "^13.1.1", + "npm-user-validate": "^1.0.1", + "npmlog": "^6.0.2", + "opener": "^1.5.2", + "pacote": "^13.4.1", + "parse-conflict-json": "^2.0.2", + "proc-log": "^2.0.1", + "qrcode-terminal": "^0.12.0", + "read": "~1.0.7", + "read-package-json": "^5.0.1", + "read-package-json-fast": "^2.0.3", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^9.0.1", + "tar": "^6.1.11", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^2.0.0", + "validate-npm-package-name": "^4.0.0", + "which": "^2.0.2", + "write-file-atomic": "^4.0.1" }, "bin": { "npm": "bin/npm-cli.js", @@ -11647,6 +11645,15 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/@colors/colors": { + "version": "1.5.0", + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/npm/node_modules/@gar/promisify": { "version": "1.1.3", "inBundle": true, @@ -11658,33 +11665,33 @@ "license": "ISC" }, "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "5.0.2", + "version": "5.2.0", "inBundle": true, "license": "ISC", "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/map-workspaces": "^2.0.0", - "@npmcli/metavuln-calculator": "^3.0.0", - "@npmcli/move-file": "^1.1.0", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/metavuln-calculator": "^3.0.1", + "@npmcli/move-file": "^2.0.0", "@npmcli/name-from-folder": "^1.0.1", - "@npmcli/node-gyp": "^1.0.3", - "@npmcli/package-json": "^1.0.1", + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/package-json": "^2.0.0", "@npmcli/run-script": "^3.0.0", "bin-links": "^3.0.0", - "cacache": "^15.0.3", + "cacache": "^16.0.6", "common-ancestor-path": "^1.0.1", "json-parse-even-better-errors": "^2.3.1", "json-stringify-nice": "^1.1.4", "mkdirp": "^1.0.4", "mkdirp-infer-owner": "^2.0.0", "nopt": "^5.0.0", - "npm-install-checks": "^4.0.0", + "npm-install-checks": "^5.0.0", "npm-package-arg": "^9.0.0", "npm-pick-manifest": "^7.0.0", "npm-registry-fetch": "^13.0.0", - "npmlog": "^6.0.1", - "pacote": "^13.0.2", + "npmlog": "^6.0.2", + "pacote": "^13.0.5", "parse-conflict-json": "^2.0.1", "proc-log": "^2.0.0", "promise-all-reject-late": "^1.0.0", @@ -11692,16 +11699,16 @@ "read-package-json-fast": "^2.0.2", "readdir-scoped-modules": "^1.1.0", "rimraf": "^3.0.2", - "semver": "^7.3.5", - "ssri": "^8.0.1", - "treeverse": "^1.0.4", + "semver": "^7.3.7", + "ssri": "^9.0.0", + "treeverse": "^2.0.0", "walk-up-path": "^1.0.0" }, "bin": { "arborist": "bin/index.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/ci-detect": { @@ -11713,12 +11720,12 @@ } }, "node_modules/npm/node_modules/@npmcli/config": { - "version": "4.0.1", + "version": "4.1.0", "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/map-workspaces": "^2.0.1", - "ini": "^2.0.0", + "@npmcli/map-workspaces": "^2.0.2", + "ini": "^3.0.0", "mkdirp-infer-owner": "^2.0.0", "nopt": "^5.0.0", "proc-log": "^2.0.0", @@ -11727,39 +11734,39 @@ "walk-up-path": "^1.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/disparity-colors": { - "version": "1.0.1", + "version": "2.0.0", "inBundle": true, "license": "ISC", "dependencies": { "ansi-styles": "^4.3.0" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/fs": { - "version": "1.1.0", + "version": "2.1.0", "inBundle": true, "license": "ISC", "dependencies": { - "@gar/promisify": "^1.0.1", + "@gar/promisify": "^1.1.3", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/git": { - "version": "3.0.0", + "version": "3.0.1", "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/promise-spawn": "^1.3.2", - "lru-cache": "^7.3.1", + "@npmcli/promise-spawn": "^3.0.0", + "lru-cache": "^7.4.4", "mkdirp": "^1.0.4", "npm-pick-manifest": "^7.0.0", "proc-log": "^2.0.0", @@ -11769,15 +11776,7 @@ "which": "^2.0.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/npm/node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "7.4.0", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=12" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/installed-package-contents": { @@ -11796,54 +11795,35 @@ } }, "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "2.0.2", + "version": "2.0.3", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/name-from-folder": "^1.0.1", - "glob": "^7.2.0", + "glob": "^8.0.1", "minimatch": "^5.0.1", "read-package-json-fast": "^2.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { - "version": "2.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces/node_modules/minimatch": { - "version": "5.0.1", - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "3.0.0", + "version": "3.1.0", "inBundle": true, "license": "ISC", "dependencies": { - "cacache": "^15.3.0", + "cacache": "^16.0.0", "json-parse-even-better-errors": "^2.3.1", - "pacote": "^13.0.1", + "pacote": "^13.0.3", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/move-file": { - "version": "1.1.2", + "version": "2.0.0", "inBundle": true, "license": "MIT", "dependencies": { @@ -11851,7 +11831,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/name-from-folder": { @@ -11860,38 +11840,47 @@ "license": "ISC" }, "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "1.0.3", + "version": "2.0.0", "inBundle": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } }, "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "1.0.1", + "version": "2.0.0", "inBundle": true, "license": "ISC", "dependencies": { "json-parse-even-better-errors": "^2.3.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "1.3.2", + "version": "3.0.0", "inBundle": true, "license": "ISC", "dependencies": { "infer-owner": "^1.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "3.0.1", + "version": "3.0.2", "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/node-gyp": "^1.0.3", - "@npmcli/promise-spawn": "^1.3.2", + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/promise-spawn": "^3.0.0", "node-gyp": "^9.0.0", "read-package-json-fast": "^2.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/@tootallnate/once": { @@ -11943,6 +11932,14 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/npm/node_modules/ansi-styles": { "version": "4.3.0", "inBundle": true, @@ -11957,16 +11954,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/npm/node_modules/ansicolors": { - "version": "0.3.2", - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/ansistyles": { - "version": "0.1.3", - "inBundle": true, - "license": "MIT" - }, "node_modules/npm/node_modules/aproba": { "version": "2.0.0", "inBundle": true, @@ -12000,19 +11987,19 @@ "license": "MIT" }, "node_modules/npm/node_modules/bin-links": { - "version": "3.0.0", + "version": "3.0.1", "inBundle": true, "license": "ISC", "dependencies": { - "cmd-shim": "^4.0.1", + "cmd-shim": "^5.0.0", "mkdirp-infer-owner": "^2.0.0", "npm-normalize-package-bin": "^1.0.0", - "read-cmd-shim": "^2.0.0", + "read-cmd-shim": "^3.0.0", "rimraf": "^3.0.0", "write-file-atomic": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/binary-extensions": { @@ -12024,45 +12011,47 @@ } }, "node_modules/npm/node_modules/brace-expansion": { - "version": "1.1.11", + "version": "2.0.1", "inBundle": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/npm/node_modules/builtins": { - "version": "1.0.3", + "version": "5.0.1", "inBundle": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "semver": "^7.0.0" + } }, "node_modules/npm/node_modules/cacache": { - "version": "15.3.0", + "version": "16.1.0", "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", "unique-filename": "^1.1.1" }, "engines": { - "node": ">= 10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/chalk": { @@ -12119,27 +12108,8 @@ "node": ">= 10" } }, - "node_modules/npm/node_modules/cli-columns/node_modules/ansi-regex": { - "version": "5.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/cli-columns/node_modules/strip-ansi": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/npm/node_modules/cli-table3": { - "version": "0.6.1", + "version": "0.6.2", "inBundle": true, "license": "MIT", "dependencies": { @@ -12149,7 +12119,7 @@ "node": "10.* || >= 12.*" }, "optionalDependencies": { - "colors": "1.4.0" + "@colors/colors": "1.5.0" } }, "node_modules/npm/node_modules/clone": { @@ -12161,14 +12131,14 @@ } }, "node_modules/npm/node_modules/cmd-shim": { - "version": "4.1.0", + "version": "5.0.0", "inBundle": true, "license": "ISC", "dependencies": { "mkdirp-infer-owner": "^2.0.0" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/color-convert": { @@ -12195,15 +12165,6 @@ "color-support": "bin.js" } }, - "node_modules/npm/node_modules/colors": { - "version": "1.4.0", - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/npm/node_modules/columnify": { "version": "1.6.0", "inBundle": true, @@ -12216,25 +12177,6 @@ "node": ">=8.0.0" } }, - "node_modules/npm/node_modules/columnify/node_modules/ansi-regex": { - "version": "5.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/columnify/node_modules/strip-ansi": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/npm/node_modules/common-ancestor-path": { "version": "1.0.1", "inBundle": true, @@ -12251,7 +12193,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/debug": { - "version": "4.3.3", + "version": "4.3.4", "inBundle": true, "license": "MIT", "dependencies": { @@ -12301,7 +12243,7 @@ } }, "node_modules/npm/node_modules/dezalgo": { - "version": "1.0.3", + "version": "1.0.4", "inBundle": true, "license": "ISC", "dependencies": { @@ -12371,7 +12313,7 @@ "license": "MIT" }, "node_modules/npm/node_modules/gauge": { - "version": "4.0.3", + "version": "4.0.4", "inBundle": true, "license": "ISC", "dependencies": { @@ -12385,49 +12327,30 @@ "wide-align": "^1.1.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/npm/node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/glob": { - "version": "7.2.0", + "version": "8.0.1", "inBundle": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^5.0.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/npm/node_modules/graceful-fs": { - "version": "4.2.9", + "version": "4.2.10", "inBundle": true, "license": "ISC" }, @@ -12456,14 +12379,14 @@ "license": "ISC" }, "node_modules/npm/node_modules/hosted-git-info": { - "version": "4.1.0", + "version": "5.0.0", "inBundle": true, "license": "ISC", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.5.1" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16" } }, "node_modules/npm/node_modules/http-cache-semantics": { @@ -12485,7 +12408,7 @@ } }, "node_modules/npm/node_modules/https-proxy-agent": { - "version": "5.0.0", + "version": "5.0.1", "inBundle": true, "license": "MIT", "dependencies": { @@ -12517,14 +12440,14 @@ } }, "node_modules/npm/node_modules/ignore-walk": { - "version": "4.0.1", + "version": "5.0.1", "inBundle": true, "license": "ISC", "dependencies": { - "minimatch": "^3.0.4" + "minimatch": "^5.0.1" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/imurmurhash": { @@ -12563,32 +12486,32 @@ "license": "ISC" }, "node_modules/npm/node_modules/ini": { - "version": "2.0.0", + "version": "3.0.0", "inBundle": true, "license": "ISC", "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/init-package-json": { - "version": "3.0.0", + "version": "3.0.2", "inBundle": true, "license": "ISC", "dependencies": { - "npm-package-arg": "^9.0.0", + "npm-package-arg": "^9.0.1", "promzard": "^0.3.0", "read": "^1.0.7", - "read-package-json": "^4.1.1", + "read-package-json": "^5.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^3.0.0" + "validate-npm-package-name": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/ip": { - "version": "1.1.5", + "version": "1.1.8", "inBundle": true, "license": "MIT" }, @@ -12612,7 +12535,7 @@ } }, "node_modules/npm/node_modules/is-core-module": { - "version": "2.8.1", + "version": "2.9.0", "inBundle": true, "license": "MIT", "dependencies": { @@ -12662,49 +12585,49 @@ "license": "MIT" }, "node_modules/npm/node_modules/just-diff": { - "version": "5.0.1", + "version": "5.0.2", "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/just-diff-apply": { - "version": "4.0.1", + "version": "5.2.0", "inBundle": true, "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { - "version": "6.0.1", + "version": "6.0.3", "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", "minipass": "^3.1.1", - "npm-package-arg": "^9.0.0", + "npm-package-arg": "^9.0.1", "npm-registry-fetch": "^13.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmdiff": { - "version": "4.0.1", + "version": "4.0.3", "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/disparity-colors": "^1.0.1", + "@npmcli/disparity-colors": "^2.0.0", "@npmcli/installed-package-contents": "^1.0.7", "binary-extensions": "^2.2.0", "diff": "^5.0.0", - "minimatch": "^3.0.4", - "npm-package-arg": "^9.0.0", - "pacote": "^13.0.2", + "minimatch": "^5.0.1", + "npm-package-arg": "^9.0.1", + "pacote": "^13.0.5", "tar": "^6.1.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "4.0.1", + "version": "4.0.5", "inBundle": true, "license": "ISC", "dependencies": { @@ -12713,31 +12636,31 @@ "@npmcli/run-script": "^3.0.0", "chalk": "^4.1.0", "mkdirp-infer-owner": "^2.0.0", - "npm-package-arg": "^9.0.0", - "npmlog": "^6.0.1", - "pacote": "^13.0.2", + "npm-package-arg": "^9.0.1", + "npmlog": "^6.0.2", + "pacote": "^13.0.5", "proc-log": "^2.0.0", "read": "^1.0.7", "read-package-json-fast": "^2.0.2", "walk-up-path": "^1.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmfund": { - "version": "3.0.1", + "version": "3.0.2", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/arborist": "^5.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmhook": { - "version": "8.0.1", + "version": "8.0.3", "inBundle": true, "license": "ISC", "dependencies": { @@ -12745,11 +12668,11 @@ "npm-registry-fetch": "^13.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmorg": { - "version": "4.0.1", + "version": "4.0.3", "inBundle": true, "license": "ISC", "dependencies": { @@ -12757,50 +12680,50 @@ "npm-registry-fetch": "^13.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmpack": { - "version": "4.0.1", + "version": "4.1.0", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/run-script": "^3.0.0", - "npm-package-arg": "^9.0.0", - "pacote": "^13.0.2" + "npm-package-arg": "^9.0.1", + "pacote": "^13.5.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmpublish": { - "version": "6.0.1", + "version": "6.0.4", "inBundle": true, "license": "ISC", "dependencies": { - "normalize-package-data": "^3.0.2", - "npm-package-arg": "^9.0.0", + "normalize-package-data": "^4.0.0", + "npm-package-arg": "^9.0.1", "npm-registry-fetch": "^13.0.0", - "semver": "^7.1.3", - "ssri": "^8.0.1" + "semver": "^7.3.7", + "ssri": "^9.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmsearch": { - "version": "5.0.1", + "version": "5.0.3", "inBundle": true, "license": "ISC", "dependencies": { "npm-registry-fetch": "^13.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmteam": { - "version": "4.0.1", + "version": "4.0.3", "inBundle": true, "license": "ISC", "dependencies": { @@ -12808,11 +12731,11 @@ "npm-registry-fetch": "^13.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/libnpmversion": { - "version": "3.0.1", + "version": "3.0.4", "inBundle": true, "license": "ISC", "dependencies": { @@ -12820,67 +12743,55 @@ "@npmcli/run-script": "^3.0.0", "json-parse-even-better-errors": "^2.3.1", "proc-log": "^2.0.0", - "semver": "^7.3.5", - "stringify-package": "^1.0.1" + "semver": "^7.3.7" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/lru-cache": { - "version": "6.0.0", + "version": "7.9.0", "inBundle": true, "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/npm/node_modules/make-fetch-happen": { - "version": "10.0.5", + "version": "10.1.5", "inBundle": true, "license": "ISC", "dependencies": { "agentkeepalive": "^4.2.1", - "cacache": "^15.3.0", + "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", - "lru-cache": "^7.4.1", + "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.2", + "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^6.1.1", - "ssri": "^8.0.1" + "ssri": "^9.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/npm/node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.4.2", - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=12" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/minimatch": { - "version": "3.1.2", + "version": "5.0.1", "inBundle": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=10" } }, "node_modules/npm/node_modules/minipass": { @@ -12906,7 +12817,7 @@ } }, "node_modules/npm/node_modules/minipass-fetch": { - "version": "2.0.2", + "version": "2.1.0", "inBundle": true, "license": "MIT", "dependencies": { @@ -12915,7 +12826,7 @@ "minizlib": "^2.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" }, "optionalDependencies": { "encoding": "^0.1.13" @@ -13040,6 +12951,45 @@ "node": "^12.22 || ^14.13 || >=16" } }, + "node_modules/npm/node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/glob": { + "version": "7.2.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/minimatch": { + "version": "3.1.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/npm/node_modules/nopt": { "version": "5.0.0", "inBundle": true, @@ -13055,28 +13005,28 @@ } }, "node_modules/npm/node_modules/normalize-package-data": { - "version": "3.0.3", + "version": "4.0.0", "inBundle": true, "license": "BSD-2-Clause", "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16" } }, "node_modules/npm/node_modules/npm-audit-report": { - "version": "2.1.5", + "version": "3.0.0", "inBundle": true, "license": "ISC", "dependencies": { "chalk": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/npm-bundled": { @@ -13088,14 +13038,14 @@ } }, "node_modules/npm/node_modules/npm-install-checks": { - "version": "4.0.0", + "version": "5.0.0", "inBundle": true, "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/npm-normalize-package-bin": { @@ -13104,76 +13054,76 @@ "license": "ISC" }, "node_modules/npm/node_modules/npm-package-arg": { - "version": "9.0.0", + "version": "9.0.2", "inBundle": true, "license": "ISC", "dependencies": { - "hosted-git-info": "^4.1.0", + "hosted-git-info": "^5.0.0", "semver": "^7.3.5", - "validate-npm-package-name": "^3.0.0" + "validate-npm-package-name": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/npm-packlist": { - "version": "3.0.0", + "version": "5.1.0", "inBundle": true, "license": "ISC", "dependencies": { - "glob": "^7.1.6", - "ignore-walk": "^4.0.1", - "npm-bundled": "^1.1.1", + "glob": "^8.0.1", + "ignore-walk": "^5.0.1", + "npm-bundled": "^1.1.2", "npm-normalize-package-bin": "^1.0.1" }, "bin": { "npm-packlist": "bin/index.js" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "7.0.0", + "version": "7.0.1", "inBundle": true, "license": "ISC", "dependencies": { - "npm-install-checks": "^4.0.0", + "npm-install-checks": "^5.0.0", "npm-normalize-package-bin": "^1.0.1", "npm-package-arg": "^9.0.0", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/npm-profile": { - "version": "6.0.2", + "version": "6.0.3", "inBundle": true, "license": "ISC", "dependencies": { - "npm-registry-fetch": "^13.0.0", + "npm-registry-fetch": "^13.0.1", "proc-log": "^2.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "13.0.1", + "version": "13.1.1", "inBundle": true, "license": "ISC", "dependencies": { - "make-fetch-happen": "^10.0.3", + "make-fetch-happen": "^10.0.6", "minipass": "^3.1.6", - "minipass-fetch": "^2.0.1", + "minipass-fetch": "^2.0.3", "minipass-json-stream": "^1.0.1", "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.0", + "npm-package-arg": "^9.0.1", "proc-log": "^2.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/npm-user-validate": { @@ -13182,17 +13132,17 @@ "license": "BSD-2-Clause" }, "node_modules/npm/node_modules/npmlog": { - "version": "6.0.1", + "version": "6.0.2", "inBundle": true, "license": "ISC", "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", - "gauge": "^4.0.0", + "gauge": "^4.0.3", "set-blocking": "^2.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/once": { @@ -13226,50 +13176,50 @@ } }, "node_modules/npm/node_modules/pacote": { - "version": "13.0.3", + "version": "13.5.0", "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/git": "^3.0.0", "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^1.2.0", - "@npmcli/run-script": "^3.0.0", - "cacache": "^15.3.0", + "@npmcli/promise-spawn": "^3.0.0", + "@npmcli/run-script": "^3.0.1", + "cacache": "^16.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "infer-owner": "^1.0.4", "minipass": "^3.1.6", "mkdirp": "^1.0.4", "npm-package-arg": "^9.0.0", - "npm-packlist": "^3.0.0", + "npm-packlist": "^5.1.0", "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.0", + "npm-registry-fetch": "^13.0.1", "proc-log": "^2.0.0", "promise-retry": "^2.0.1", - "read-package-json": "^4.1.1", + "read-package-json": "^5.0.0", "read-package-json-fast": "^2.0.3", "rimraf": "^3.0.2", - "ssri": "^8.0.1", + "ssri": "^9.0.0", "tar": "^6.1.11" }, "bin": { "pacote": "lib/bin.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/parse-conflict-json": { - "version": "2.0.1", + "version": "2.0.2", "inBundle": true, "license": "ISC", "dependencies": { "json-parse-even-better-errors": "^2.3.1", "just-diff": "^5.0.1", - "just-diff-apply": "^4.0.1" + "just-diff-apply": "^5.2.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/path-is-absolute": { @@ -13281,11 +13231,11 @@ } }, "node_modules/npm/node_modules/proc-log": { - "version": "2.0.0", + "version": "2.0.1", "inBundle": true, "license": "ISC", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/promise-all-reject-late": { @@ -13348,22 +13298,25 @@ } }, "node_modules/npm/node_modules/read-cmd-shim": { - "version": "2.0.0", + "version": "3.0.0", "inBundle": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } }, "node_modules/npm/node_modules/read-package-json": { - "version": "4.1.2", + "version": "5.0.1", "inBundle": true, "license": "ISC", "dependencies": { - "glob": "^7.1.1", - "json-parse-even-better-errors": "^2.3.0", - "normalize-package-data": "^3.0.0", - "npm-normalize-package-bin": "^1.0.0" + "glob": "^8.0.1", + "json-parse-even-better-errors": "^2.3.1", + "normalize-package-data": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1" }, "engines": { - "node": ">=10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/read-package-json-fast": { @@ -13424,6 +13377,45 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/npm/node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm/node_modules/rimraf/node_modules/glob": { + "version": "7.2.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/npm/node_modules/safe-buffer": { "version": "5.2.1", "funding": [ @@ -13450,7 +13442,7 @@ "optional": true }, "node_modules/npm/node_modules/semver": { - "version": "7.3.5", + "version": "7.3.7", "inBundle": true, "license": "ISC", "dependencies": { @@ -13463,6 +13455,17 @@ "node": ">=10" } }, + "node_modules/npm/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/npm/node_modules/set-blocking": { "version": "2.0.0", "inBundle": true, @@ -13496,13 +13499,13 @@ } }, "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "6.1.1", + "version": "6.2.0", "inBundle": true, "license": "MIT", "dependencies": { "agent-base": "^6.0.2", - "debug": "^4.3.1", - "socks": "^2.6.1" + "debug": "^4.3.3", + "socks": "^2.6.2" }, "engines": { "node": ">= 10" @@ -13537,14 +13540,14 @@ "license": "CC0-1.0" }, "node_modules/npm/node_modules/ssri": { - "version": "8.0.1", + "version": "9.0.1", "inBundle": true, "license": "ISC", "dependencies": { "minipass": "^3.1.1" }, "engines": { - "node": ">= 8" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/string_decoder": { @@ -13568,15 +13571,7 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/string-width/node_modules/ansi-regex": { - "version": "5.0.1", - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/string-width/node_modules/strip-ansi": { + "node_modules/npm/node_modules/strip-ansi": { "version": "6.0.1", "inBundle": true, "license": "MIT", @@ -13587,11 +13582,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/stringify-package": { - "version": "1.0.1", - "inBundle": true, - "license": "ISC" - }, "node_modules/npm/node_modules/supports-color": { "version": "7.2.0", "inBundle": true, @@ -13630,9 +13620,12 @@ "license": "MIT" }, "node_modules/npm/node_modules/treeverse": { - "version": "1.0.4", + "version": "2.0.0", "inBundle": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } }, "node_modules/npm/node_modules/unique-filename": { "version": "1.1.1", @@ -13665,11 +13658,14 @@ } }, "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "3.0.0", + "version": "4.0.0", "inBundle": true, "license": "ISC", "dependencies": { - "builtins": "^1.0.3" + "builtins": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/npm/node_modules/walk-up-path": { @@ -18804,11 +18800,11 @@ } }, "@angular/flex-layout": { - "version": "12.0.0-beta.35", - "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-12.0.0-beta.35.tgz", - "integrity": "sha512-nPi2MGDFuCacwWHqxF/G7lUJd2X99HbLjjUvKXnyLwyCIVgH1sfS52su2wYbVYWJRqAVAB2/VMlrtW8Khr8hDA==", + "version": "13.0.0-beta.38", + "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-13.0.0-beta.38.tgz", + "integrity": "sha512-kcWb7CcoHbvw7fjo/knizWVmSSmvaTnr8v1ML6zOdxu1PK9UPPOcOS8RTm6fy61zoC2LABivP1/6Z2jF5XfpdQ==", "requires": { - "tslib": "^2.1.0" + "tslib": "^2.3.0" } }, "@angular/forms": { @@ -21571,9 +21567,9 @@ } }, "@videogular/ngx-videogular": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@videogular/ngx-videogular/-/ngx-videogular-5.0.0.tgz", - "integrity": "sha512-xdhB5ymXDTfaUKzoJAoGS8UYUgqHMiJpIUSlf9hhwTXNiOAZ5fcXlvJ4RG3WurAtQx0Ct7ua3sdBkV23ZVxjgg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@videogular/ngx-videogular/-/ngx-videogular-5.0.1.tgz", + "integrity": "sha512-ITA3GZBzh0XoCAGQzucAX+q7h72z43kG8G9ZspLMAfyvl2Z2MEHMfC6ct6hzSWTfqr48x62Avl935dcdl/NgXQ==", "requires": { "tslib": "^1.11.1 || ^2.0.0" } @@ -22038,9 +22034,9 @@ "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, "requires": { "lodash": "^4.17.14" @@ -23508,9 +23504,9 @@ } }, "dexie": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dexie/-/dexie-3.0.3.tgz", - "integrity": "sha512-BSFhGpngnCl1DOr+8YNwBDobRMH0ziJs2vts69VilwetHYOtEDcLqo7d/XiIphM0tJZ2rPPyAGd31lgH2Ln3nw==" + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/dexie/-/dexie-3.2.2.tgz", + "integrity": "sha512-q5dC3HPmir2DERlX+toCBbHQXW5MsyrFqPFcovkH9N2S/UW/H3H5AWAB6iEOExeraAu+j+zRDG+zg/D7YhH0qg==" }, "didyoumean": { "version": "1.2.2", @@ -26355,83 +26351,87 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" }, "npm": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/npm/-/npm-8.5.4.tgz", - "integrity": "sha512-VnGLT4t88cUE78lLw5kxBwtLn2/Sx6O7Uw9dYwmq6AnF/taWHyMYQgDzUEsLhaXAVH7prG+sjG+MvxlHdIasgg==", - "requires": { - "@isaacs/string-locale-compare": "*", - "@npmcli/arborist": "*", - "@npmcli/ci-detect": "*", - "@npmcli/config": "*", - "@npmcli/map-workspaces": "*", - "@npmcli/package-json": "*", - "@npmcli/run-script": "*", - "abbrev": "*", - "ansicolors": "*", - "ansistyles": "*", - "archy": "*", - "cacache": "*", - "chalk": "*", - "chownr": "*", - "cli-columns": "*", - "cli-table3": "*", - "columnify": "*", - "fastest-levenshtein": "*", - "glob": "*", - "graceful-fs": "*", - "hosted-git-info": "*", - "ini": "*", - "init-package-json": "*", - "is-cidr": "*", - "json-parse-even-better-errors": "*", - "libnpmaccess": "*", - "libnpmdiff": "*", - "libnpmexec": "*", - "libnpmfund": "*", - "libnpmhook": "*", - "libnpmorg": "*", - "libnpmpack": "*", - "libnpmpublish": "*", - "libnpmsearch": "*", - "libnpmteam": "*", - "libnpmversion": "*", - "make-fetch-happen": "*", - "minipass": "*", - "minipass-pipeline": "*", - "mkdirp": "*", - "mkdirp-infer-owner": "*", - "ms": "*", - "node-gyp": "*", - "nopt": "*", - "npm-audit-report": "*", - "npm-install-checks": "*", - "npm-package-arg": "*", - "npm-pick-manifest": "*", - "npm-profile": "*", - "npm-registry-fetch": "*", - "npm-user-validate": "*", - "npmlog": "*", - "opener": "*", - "pacote": "*", - "parse-conflict-json": "*", - "proc-log": "*", - "qrcode-terminal": "*", - "read": "*", - "read-package-json": "*", - "read-package-json-fast": "*", - "readdir-scoped-modules": "*", - "rimraf": "*", - "semver": "*", - "ssri": "*", - "tar": "*", - "text-table": "*", - "tiny-relative-date": "*", - "treeverse": "*", - "validate-npm-package-name": "*", - "which": "*", - "write-file-atomic": "*" + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-8.11.0.tgz", + "integrity": "sha512-4qmtwHa28J4SPmwCNoQI07KIF/ljmBhhuqG+xNXsIIRpwdKB5OXkMIGfH6KlThR6kzusxlkgR7t1haFDB88dcQ==", + "requires": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^5.0.4", + "@npmcli/ci-detect": "^2.0.0", + "@npmcli/config": "^4.1.0", + "@npmcli/fs": "^2.1.0", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/package-json": "^2.0.0", + "@npmcli/run-script": "^3.0.1", + "abbrev": "~1.1.1", + "archy": "~1.0.0", + "cacache": "^16.1.0", + "chalk": "^4.1.2", + "chownr": "^2.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.2", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.12", + "glob": "^8.0.1", + "graceful-fs": "^4.2.10", + "hosted-git-info": "^5.0.0", + "ini": "^3.0.0", + "init-package-json": "^3.0.2", + "is-cidr": "^4.0.2", + "json-parse-even-better-errors": "^2.3.1", + "libnpmaccess": "^6.0.2", + "libnpmdiff": "^4.0.2", + "libnpmexec": "^4.0.2", + "libnpmfund": "^3.0.1", + "libnpmhook": "^8.0.2", + "libnpmorg": "^4.0.2", + "libnpmpack": "^4.0.2", + "libnpmpublish": "^6.0.2", + "libnpmsearch": "^5.0.2", + "libnpmteam": "^4.0.2", + "libnpmversion": "^3.0.1", + "make-fetch-happen": "^10.1.5", + "minipass": "^3.1.6", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "ms": "^2.1.2", + "node-gyp": "^9.0.0", + "nopt": "^5.0.0", + "npm-audit-report": "^3.0.0", + "npm-install-checks": "^5.0.0", + "npm-package-arg": "^9.0.2", + "npm-pick-manifest": "^7.0.1", + "npm-profile": "^6.0.3", + "npm-registry-fetch": "^13.1.1", + "npm-user-validate": "^1.0.1", + "npmlog": "^6.0.2", + "opener": "^1.5.2", + "pacote": "^13.4.1", + "parse-conflict-json": "^2.0.2", + "proc-log": "^2.0.1", + "qrcode-terminal": "^0.12.0", + "read": "~1.0.7", + "read-package-json": "^5.0.1", + "read-package-json-fast": "^2.0.3", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^9.0.1", + "tar": "^6.1.11", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^2.0.0", + "validate-npm-package-name": "^4.0.0", + "which": "^2.0.2", + "write-file-atomic": "^4.0.1" }, "dependencies": { + "@colors/colors": { + "version": "1.5.0", + "bundled": true, + "optional": true + }, "@gar/promisify": { "version": "1.1.3", "bundled": true @@ -26441,32 +26441,32 @@ "bundled": true }, "@npmcli/arborist": { - "version": "5.0.2", + "version": "5.2.0", "bundled": true, "requires": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/map-workspaces": "^2.0.0", - "@npmcli/metavuln-calculator": "^3.0.0", - "@npmcli/move-file": "^1.1.0", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/metavuln-calculator": "^3.0.1", + "@npmcli/move-file": "^2.0.0", "@npmcli/name-from-folder": "^1.0.1", - "@npmcli/node-gyp": "^1.0.3", - "@npmcli/package-json": "^1.0.1", + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/package-json": "^2.0.0", "@npmcli/run-script": "^3.0.0", "bin-links": "^3.0.0", - "cacache": "^15.0.3", + "cacache": "^16.0.6", "common-ancestor-path": "^1.0.1", "json-parse-even-better-errors": "^2.3.1", "json-stringify-nice": "^1.1.4", "mkdirp": "^1.0.4", "mkdirp-infer-owner": "^2.0.0", "nopt": "^5.0.0", - "npm-install-checks": "^4.0.0", + "npm-install-checks": "^5.0.0", "npm-package-arg": "^9.0.0", "npm-pick-manifest": "^7.0.0", "npm-registry-fetch": "^13.0.0", - "npmlog": "^6.0.1", - "pacote": "^13.0.2", + "npmlog": "^6.0.2", + "pacote": "^13.0.5", "parse-conflict-json": "^2.0.1", "proc-log": "^2.0.0", "promise-all-reject-late": "^1.0.0", @@ -26474,9 +26474,9 @@ "read-package-json-fast": "^2.0.2", "readdir-scoped-modules": "^1.1.0", "rimraf": "^3.0.2", - "semver": "^7.3.5", - "ssri": "^8.0.1", - "treeverse": "^1.0.4", + "semver": "^7.3.7", + "ssri": "^9.0.0", + "treeverse": "^2.0.0", "walk-up-path": "^1.0.0" } }, @@ -26485,11 +26485,11 @@ "bundled": true }, "@npmcli/config": { - "version": "4.0.1", + "version": "4.1.0", "bundled": true, "requires": { - "@npmcli/map-workspaces": "^2.0.1", - "ini": "^2.0.0", + "@npmcli/map-workspaces": "^2.0.2", + "ini": "^3.0.0", "mkdirp-infer-owner": "^2.0.0", "nopt": "^5.0.0", "proc-log": "^2.0.0", @@ -26499,39 +26499,33 @@ } }, "@npmcli/disparity-colors": { - "version": "1.0.1", + "version": "2.0.0", "bundled": true, "requires": { "ansi-styles": "^4.3.0" } }, "@npmcli/fs": { - "version": "1.1.0", + "version": "2.1.0", "bundled": true, "requires": { - "@gar/promisify": "^1.0.1", + "@gar/promisify": "^1.1.3", "semver": "^7.3.5" } }, "@npmcli/git": { - "version": "3.0.0", + "version": "3.0.1", "bundled": true, "requires": { - "@npmcli/promise-spawn": "^1.3.2", - "lru-cache": "^7.3.1", + "@npmcli/promise-spawn": "^3.0.0", + "lru-cache": "^7.4.4", "mkdirp": "^1.0.4", "npm-pick-manifest": "^7.0.0", "proc-log": "^2.0.0", "promise-inflight": "^1.0.1", "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" - }, - "dependencies": { - "lru-cache": { - "version": "7.4.0", - "bundled": true - } + "semver": "^7.3.5", + "which": "^2.0.2" } }, "@npmcli/installed-package-contents": { @@ -26543,43 +26537,27 @@ } }, "@npmcli/map-workspaces": { - "version": "2.0.2", + "version": "2.0.3", "bundled": true, "requires": { "@npmcli/name-from-folder": "^1.0.1", - "glob": "^7.2.0", + "glob": "^8.0.1", "minimatch": "^5.0.1", "read-package-json-fast": "^2.0.3" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "bundled": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } } }, "@npmcli/metavuln-calculator": { - "version": "3.0.0", + "version": "3.1.0", "bundled": true, "requires": { - "cacache": "^15.3.0", + "cacache": "^16.0.0", "json-parse-even-better-errors": "^2.3.1", - "pacote": "^13.0.1", + "pacote": "^13.0.3", "semver": "^7.3.5" } }, "@npmcli/move-file": { - "version": "1.1.2", + "version": "2.0.0", "bundled": true, "requires": { "mkdirp": "^1.0.4", @@ -26591,29 +26569,29 @@ "bundled": true }, "@npmcli/node-gyp": { - "version": "1.0.3", + "version": "2.0.0", "bundled": true }, "@npmcli/package-json": { - "version": "1.0.1", + "version": "2.0.0", "bundled": true, "requires": { "json-parse-even-better-errors": "^2.3.1" } }, "@npmcli/promise-spawn": { - "version": "1.3.2", + "version": "3.0.0", "bundled": true, "requires": { "infer-owner": "^1.0.4" } }, "@npmcli/run-script": { - "version": "3.0.1", + "version": "3.0.2", "bundled": true, "requires": { - "@npmcli/node-gyp": "^1.0.3", - "@npmcli/promise-spawn": "^1.3.2", + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/promise-spawn": "^3.0.0", "node-gyp": "^9.0.0", "read-package-json-fast": "^2.0.3" } @@ -26650,6 +26628,10 @@ "indent-string": "^4.0.0" } }, + "ansi-regex": { + "version": "5.0.1", + "bundled": true + }, "ansi-styles": { "version": "4.3.0", "bundled": true, @@ -26657,14 +26639,6 @@ "color-convert": "^2.0.1" } }, - "ansicolors": { - "version": "0.3.2", - "bundled": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true - }, "aproba": { "version": "2.0.0", "bundled": true @@ -26690,13 +26664,13 @@ "bundled": true }, "bin-links": { - "version": "3.0.0", + "version": "3.0.1", "bundled": true, "requires": { - "cmd-shim": "^4.0.1", + "cmd-shim": "^5.0.0", "mkdirp-infer-owner": "^2.0.0", "npm-normalize-package-bin": "^1.0.0", - "read-cmd-shim": "^2.0.0", + "read-cmd-shim": "^3.0.0", "rimraf": "^3.0.0", "write-file-atomic": "^4.0.0" } @@ -26706,38 +26680,40 @@ "bundled": true }, "brace-expansion": { - "version": "1.1.11", + "version": "2.0.1", "bundled": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "builtins": { - "version": "1.0.3", - "bundled": true + "version": "5.0.1", + "bundled": true, + "requires": { + "semver": "^7.0.0" + } }, "cacache": { - "version": "15.3.0", + "version": "16.1.0", "bundled": true, "requires": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", "unique-filename": "^1.1.1" } }, @@ -26770,26 +26746,13 @@ "requires": { "string-width": "^4.2.3", "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "bundled": true - }, - "strip-ansi": { - "version": "6.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } } }, "cli-table3": { - "version": "0.6.1", + "version": "0.6.2", "bundled": true, "requires": { - "colors": "1.4.0", + "@colors/colors": "1.5.0", "string-width": "^4.2.0" } }, @@ -26798,7 +26761,7 @@ "bundled": true }, "cmd-shim": { - "version": "4.1.0", + "version": "5.0.0", "bundled": true, "requires": { "mkdirp-infer-owner": "^2.0.0" @@ -26819,30 +26782,12 @@ "version": "1.1.3", "bundled": true }, - "colors": { - "version": "1.4.0", - "bundled": true, - "optional": true - }, "columnify": { "version": "1.6.0", "bundled": true, "requires": { "strip-ansi": "^6.0.1", "wcwidth": "^1.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "bundled": true - }, - "strip-ansi": { - "version": "6.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } } }, "common-ancestor-path": { @@ -26858,7 +26803,7 @@ "bundled": true }, "debug": { - "version": "4.3.3", + "version": "4.3.4", "bundled": true, "requires": { "ms": "2.1.2" @@ -26890,7 +26835,7 @@ "bundled": true }, "dezalgo": { - "version": "1.0.3", + "version": "1.0.4", "bundled": true, "requires": { "asap": "^2.0.0", @@ -26941,7 +26886,7 @@ "bundled": true }, "gauge": { - "version": "4.0.3", + "version": "4.0.4", "bundled": true, "requires": { "aproba": "^1.0.3 || ^2.0.0", @@ -26952,35 +26897,22 @@ "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "wide-align": "^1.1.5" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "bundled": true - }, - "strip-ansi": { - "version": "6.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } } }, "glob": { - "version": "7.2.0", + "version": "8.0.1", "bundled": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^5.0.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "graceful-fs": { - "version": "4.2.9", + "version": "4.2.10", "bundled": true }, "has": { @@ -26999,10 +26931,10 @@ "bundled": true }, "hosted-git-info": { - "version": "4.1.0", + "version": "5.0.0", "bundled": true, "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.5.1" } }, "http-cache-semantics": { @@ -27019,7 +26951,7 @@ } }, "https-proxy-agent": { - "version": "5.0.0", + "version": "5.0.1", "bundled": true, "requires": { "agent-base": "6", @@ -27042,10 +26974,10 @@ } }, "ignore-walk": { - "version": "4.0.1", + "version": "5.0.1", "bundled": true, "requires": { - "minimatch": "^3.0.4" + "minimatch": "^5.0.1" } }, "imurmurhash": { @@ -27073,24 +27005,24 @@ "bundled": true }, "ini": { - "version": "2.0.0", + "version": "3.0.0", "bundled": true }, "init-package-json": { - "version": "3.0.0", + "version": "3.0.2", "bundled": true, "requires": { - "npm-package-arg": "^9.0.0", + "npm-package-arg": "^9.0.1", "promzard": "^0.3.0", "read": "^1.0.7", - "read-package-json": "^4.1.1", + "read-package-json": "^5.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^3.0.0" + "validate-npm-package-name": "^4.0.0" } }, "ip": { - "version": "1.1.5", + "version": "1.1.8", "bundled": true }, "ip-regex": { @@ -27105,7 +27037,7 @@ } }, "is-core-module": { - "version": "2.8.1", + "version": "2.9.0", "bundled": true, "requires": { "has": "^1.0.3" @@ -27136,39 +27068,39 @@ "bundled": true }, "just-diff": { - "version": "5.0.1", + "version": "5.0.2", "bundled": true }, "just-diff-apply": { - "version": "4.0.1", + "version": "5.2.0", "bundled": true }, "libnpmaccess": { - "version": "6.0.1", + "version": "6.0.3", "bundled": true, "requires": { "aproba": "^2.0.0", "minipass": "^3.1.1", - "npm-package-arg": "^9.0.0", + "npm-package-arg": "^9.0.1", "npm-registry-fetch": "^13.0.0" } }, "libnpmdiff": { - "version": "4.0.1", + "version": "4.0.3", "bundled": true, "requires": { - "@npmcli/disparity-colors": "^1.0.1", + "@npmcli/disparity-colors": "^2.0.0", "@npmcli/installed-package-contents": "^1.0.7", "binary-extensions": "^2.2.0", "diff": "^5.0.0", - "minimatch": "^3.0.4", - "npm-package-arg": "^9.0.0", - "pacote": "^13.0.2", + "minimatch": "^5.0.1", + "npm-package-arg": "^9.0.1", + "pacote": "^13.0.5", "tar": "^6.1.0" } }, "libnpmexec": { - "version": "4.0.1", + "version": "4.0.5", "bundled": true, "requires": { "@npmcli/arborist": "^5.0.0", @@ -27176,9 +27108,9 @@ "@npmcli/run-script": "^3.0.0", "chalk": "^4.1.0", "mkdirp-infer-owner": "^2.0.0", - "npm-package-arg": "^9.0.0", - "npmlog": "^6.0.1", - "pacote": "^13.0.2", + "npm-package-arg": "^9.0.1", + "npmlog": "^6.0.2", + "pacote": "^13.0.5", "proc-log": "^2.0.0", "read": "^1.0.7", "read-package-json-fast": "^2.0.2", @@ -27186,14 +27118,14 @@ } }, "libnpmfund": { - "version": "3.0.1", + "version": "3.0.2", "bundled": true, "requires": { "@npmcli/arborist": "^5.0.0" } }, "libnpmhook": { - "version": "8.0.1", + "version": "8.0.3", "bundled": true, "requires": { "aproba": "^2.0.0", @@ -27201,7 +27133,7 @@ } }, "libnpmorg": { - "version": "4.0.1", + "version": "4.0.3", "bundled": true, "requires": { "aproba": "^2.0.0", @@ -27209,34 +27141,34 @@ } }, "libnpmpack": { - "version": "4.0.1", + "version": "4.1.0", "bundled": true, "requires": { "@npmcli/run-script": "^3.0.0", - "npm-package-arg": "^9.0.0", - "pacote": "^13.0.2" + "npm-package-arg": "^9.0.1", + "pacote": "^13.5.0" } }, "libnpmpublish": { - "version": "6.0.1", + "version": "6.0.4", "bundled": true, "requires": { - "normalize-package-data": "^3.0.2", - "npm-package-arg": "^9.0.0", + "normalize-package-data": "^4.0.0", + "npm-package-arg": "^9.0.1", "npm-registry-fetch": "^13.0.0", - "semver": "^7.1.3", - "ssri": "^8.0.1" + "semver": "^7.3.7", + "ssri": "^9.0.0" } }, "libnpmsearch": { - "version": "5.0.1", + "version": "5.0.3", "bundled": true, "requires": { "npm-registry-fetch": "^13.0.0" } }, "libnpmteam": { - "version": "4.0.1", + "version": "4.0.3", "bundled": true, "requires": { "aproba": "^2.0.0", @@ -27244,57 +27176,47 @@ } }, "libnpmversion": { - "version": "3.0.1", + "version": "3.0.4", "bundled": true, "requires": { "@npmcli/git": "^3.0.0", "@npmcli/run-script": "^3.0.0", "json-parse-even-better-errors": "^2.3.1", "proc-log": "^2.0.0", - "semver": "^7.3.5", - "stringify-package": "^1.0.1" + "semver": "^7.3.7" } }, "lru-cache": { - "version": "6.0.0", - "bundled": true, - "requires": { - "yallist": "^4.0.0" - } + "version": "7.9.0", + "bundled": true }, "make-fetch-happen": { - "version": "10.0.5", + "version": "10.1.5", "bundled": true, "requires": { "agentkeepalive": "^4.2.1", - "cacache": "^15.3.0", + "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", - "lru-cache": "^7.4.1", + "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.2", + "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^6.1.1", - "ssri": "^8.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "7.4.2", - "bundled": true - } + "ssri": "^9.0.0" } }, "minimatch": { - "version": "3.1.2", + "version": "5.0.1", "bundled": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" } }, "minipass": { @@ -27312,7 +27234,7 @@ } }, "minipass-fetch": { - "version": "2.0.2", + "version": "2.1.0", "bundled": true, "requires": { "encoding": "^0.1.13", @@ -27397,6 +27319,35 @@ "semver": "^7.3.5", "tar": "^6.1.2", "which": "^2.0.2" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.0", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "nopt": { @@ -27407,17 +27358,17 @@ } }, "normalize-package-data": { - "version": "3.0.3", + "version": "4.0.0", "bundled": true, "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" } }, "npm-audit-report": { - "version": "2.1.5", + "version": "3.0.0", "bundled": true, "requires": { "chalk": "^4.0.0" @@ -27431,7 +27382,7 @@ } }, "npm-install-checks": { - "version": "4.0.0", + "version": "5.0.0", "bundled": true, "requires": { "semver": "^7.1.1" @@ -27442,52 +27393,52 @@ "bundled": true }, "npm-package-arg": { - "version": "9.0.0", + "version": "9.0.2", "bundled": true, "requires": { - "hosted-git-info": "^4.1.0", + "hosted-git-info": "^5.0.0", "semver": "^7.3.5", - "validate-npm-package-name": "^3.0.0" + "validate-npm-package-name": "^4.0.0" } }, "npm-packlist": { - "version": "3.0.0", + "version": "5.1.0", "bundled": true, "requires": { - "glob": "^7.1.6", - "ignore-walk": "^4.0.1", - "npm-bundled": "^1.1.1", + "glob": "^8.0.1", + "ignore-walk": "^5.0.1", + "npm-bundled": "^1.1.2", "npm-normalize-package-bin": "^1.0.1" } }, "npm-pick-manifest": { - "version": "7.0.0", + "version": "7.0.1", "bundled": true, "requires": { - "npm-install-checks": "^4.0.0", + "npm-install-checks": "^5.0.0", "npm-normalize-package-bin": "^1.0.1", "npm-package-arg": "^9.0.0", "semver": "^7.3.5" } }, "npm-profile": { - "version": "6.0.2", + "version": "6.0.3", "bundled": true, "requires": { - "npm-registry-fetch": "^13.0.0", + "npm-registry-fetch": "^13.0.1", "proc-log": "^2.0.0" } }, "npm-registry-fetch": { - "version": "13.0.1", + "version": "13.1.1", "bundled": true, "requires": { - "make-fetch-happen": "^10.0.3", + "make-fetch-happen": "^10.0.6", "minipass": "^3.1.6", - "minipass-fetch": "^2.0.1", + "minipass-fetch": "^2.0.3", "minipass-json-stream": "^1.0.1", "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.0", + "npm-package-arg": "^9.0.1", "proc-log": "^2.0.0" } }, @@ -27496,12 +27447,12 @@ "bundled": true }, "npmlog": { - "version": "6.0.1", + "version": "6.0.2", "bundled": true, "requires": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", - "gauge": "^4.0.0", + "gauge": "^4.0.3", "set-blocking": "^2.0.0" } }, @@ -27524,39 +27475,39 @@ } }, "pacote": { - "version": "13.0.3", + "version": "13.5.0", "bundled": true, "requires": { "@npmcli/git": "^3.0.0", "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^1.2.0", - "@npmcli/run-script": "^3.0.0", - "cacache": "^15.3.0", + "@npmcli/promise-spawn": "^3.0.0", + "@npmcli/run-script": "^3.0.1", + "cacache": "^16.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "infer-owner": "^1.0.4", "minipass": "^3.1.6", "mkdirp": "^1.0.4", "npm-package-arg": "^9.0.0", - "npm-packlist": "^3.0.0", + "npm-packlist": "^5.1.0", "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.0", + "npm-registry-fetch": "^13.0.1", "proc-log": "^2.0.0", "promise-retry": "^2.0.1", - "read-package-json": "^4.1.1", + "read-package-json": "^5.0.0", "read-package-json-fast": "^2.0.3", "rimraf": "^3.0.2", - "ssri": "^8.0.1", + "ssri": "^9.0.0", "tar": "^6.1.11" } }, "parse-conflict-json": { - "version": "2.0.1", + "version": "2.0.2", "bundled": true, "requires": { "json-parse-even-better-errors": "^2.3.1", "just-diff": "^5.0.1", - "just-diff-apply": "^4.0.1" + "just-diff-apply": "^5.2.0" } }, "path-is-absolute": { @@ -27564,7 +27515,7 @@ "bundled": true }, "proc-log": { - "version": "2.0.0", + "version": "2.0.1", "bundled": true }, "promise-all-reject-late": { @@ -27606,17 +27557,17 @@ } }, "read-cmd-shim": { - "version": "2.0.0", + "version": "3.0.0", "bundled": true }, "read-package-json": { - "version": "4.1.2", + "version": "5.0.1", "bundled": true, "requires": { - "glob": "^7.1.1", - "json-parse-even-better-errors": "^2.3.0", - "normalize-package-data": "^3.0.0", - "npm-normalize-package-bin": "^1.0.0" + "glob": "^8.0.1", + "json-parse-even-better-errors": "^2.3.1", + "normalize-package-data": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1" } }, "read-package-json-fast": { @@ -27655,6 +27606,35 @@ "bundled": true, "requires": { "glob": "^7.1.3" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.0", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "safe-buffer": { @@ -27667,10 +27647,19 @@ "optional": true }, "semver": { - "version": "7.3.5", + "version": "7.3.7", "bundled": true, "requires": { "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + } } }, "set-blocking": { @@ -27694,12 +27683,12 @@ } }, "socks-proxy-agent": { - "version": "6.1.1", + "version": "6.2.0", "bundled": true, "requires": { "agent-base": "^6.0.2", - "debug": "^4.3.1", - "socks": "^2.6.1" + "debug": "^4.3.3", + "socks": "^2.6.2" } }, "spdx-correct": { @@ -27727,7 +27716,7 @@ "bundled": true }, "ssri": { - "version": "8.0.1", + "version": "9.0.1", "bundled": true, "requires": { "minipass": "^3.1.1" @@ -27747,24 +27736,14 @@ "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "bundled": true - }, - "strip-ansi": { - "version": "6.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } } }, - "stringify-package": { - "version": "1.0.1", - "bundled": true + "strip-ansi": { + "version": "6.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^5.0.1" + } }, "supports-color": { "version": "7.2.0", @@ -27794,7 +27773,7 @@ "bundled": true }, "treeverse": { - "version": "1.0.4", + "version": "2.0.0", "bundled": true }, "unique-filename": { @@ -27824,10 +27803,10 @@ } }, "validate-npm-package-name": { - "version": "3.0.0", + "version": "4.0.0", "bundled": true, "requires": { - "builtins": "^1.0.3" + "builtins": "^5.0.0" } }, "walk-up-path": { diff --git a/package.json b/package.json index d194dc72..a3b4f3be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vitrivr-ng", - "version": "2.7.1", + "version": "2.8.0", "license": "MIT", "scripts": { "ng": "ng", @@ -25,7 +25,7 @@ "@angular/common": "13.3.2", "@angular/compiler": "13.3.2", "@angular/core": "13.3.2", - "@angular/flex-layout": "12.0.0-beta.35", + "@angular/flex-layout": "13.0.0-beta.38", "@angular/forms": "13.3.2", "@angular/material": "13.3.2", "@angular/platform-browser": "13.3.2", @@ -35,10 +35,10 @@ "@types/leaflet": "1.7.5", "@types/openseadragon": "^2.4.7", "@types/three": "0.134.0", - "@videogular/ngx-videogular": "5.0.0", + "@videogular/ngx-videogular": "5.0.1", "core-js": "3.19.1", "deepmerge": "4.2.2", - "dexie": "^3.0.3", + "dexie": "^3.2.2", "flatted": "3.2.4", "jszip": "3.7.1", "leaflet": "1.7.1", @@ -46,7 +46,7 @@ "ngx-color-picker": "11.0.0", "ngx-infinite-scroll": "10.0.1", "node": "^17.4.0", - "npm": "^8.1.2", + "npm": "^8.11.0", "openapi-generator": "^0.1.39", "openseadragon": "^2.4.2", "rxjs": "7.5.5", @@ -79,4 +79,4 @@ "ts-node": "10.7.0", "tslint": "^6.1.3" } -} +} \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e52f17f7..081b89df 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -93,8 +93,4 @@ export class AppComponent implements OnInit, AfterViewInit { this._active_view = view; } - isCompetitionActive() { - return this._configService.configAsObservable; - return this._config.dresEndpointRest && (this._config.get('competition.vbs') || this._config.get('competition.lsc')) - } } diff --git a/src/app/app.config.ts b/src/app/app.config.ts index ec641a71..9bd5dd9f 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -63,13 +63,13 @@ export class AppConfig { AppConfig.settingsSubject.next(AppConfig.settings); resolve(); }).catch((response: any) => { - this._snackBar.open('Could not parse config.json. Using default config, your UI may not work', 'Dismiss', { + this._snackBar.open('No config file present, using default config.', 'Dismiss', { duration: 1_000_000, verticalPosition: 'top' }) AppConfig.settings = new Proxy(new Config(), this.handler); AppConfig.settingsSubject.next(AppConfig.settings); - console.log(`Could not load config file '${jsonFile}'. Fallback to default.`); + console.log(`No config present at '${jsonFile}'. Using default.`); resolve(); }); }); diff --git a/src/app/core/basics/basic.module.ts b/src/app/core/basics/basic.module.ts index 0a5d811d..b5de1bc6 100644 --- a/src/app/core/basics/basic.module.ts +++ b/src/app/core/basics/basic.module.ts @@ -9,11 +9,12 @@ import {NotificationService} from './notification.service'; import {NoConnectDialogComponent} from './no-connect-dialog'; import {MatDialogModule} from '@angular/material/dialog'; import {MatButtonModule} from '@angular/material/button'; +import {DresService} from './dres.service'; @NgModule({ imports: [HttpClientModule, MatDialogModule, MatButtonModule], declarations: [NoConnectDialogComponent], - providers: [ResolverService, EventBusService, PingService, DatabaseService, KeyboardService, NotificationService] + providers: [ResolverService, EventBusService, PingService, DatabaseService, KeyboardService, NotificationService, DresService] }) export class BasicModule { diff --git a/src/app/core/basics/database.service.ts b/src/app/core/basics/database.service.ts index 65a39552..e64fb678 100644 --- a/src/app/core/basics/database.service.ts +++ b/src/app/core/basics/database.service.ts @@ -11,11 +11,12 @@ export class DatabaseService { */ constructor() { DatabaseService.DB.version(1).stores({ - config: 'id,config', history: '++id,timestamp', - log_results: '++id,log', - log_interaction: '++id,log', - log_submission: '++id,log' + log_results_dres: '++id,log', + log_interaction_dres: '++id,log', + log_submission_dres: '++id,log', + log_results: '++id,entry', + log_queries: '++id,entry', }); } diff --git a/src/app/core/basics/dres.service.ts b/src/app/core/basics/dres.service.ts new file mode 100644 index 00000000..664f80d1 --- /dev/null +++ b/src/app/core/basics/dres.service.ts @@ -0,0 +1,92 @@ +import {Injectable} from '@angular/core'; +import {AppConfig} from '../../app.config'; +import {ClientRunInfo, ClientRunInfoService, ClientTaskInfo, UserDetails, UserService} from '../../../../openapi/dres'; +import {BehaviorSubject, Observable} from 'rxjs'; + +@Injectable() +export class DresService { + + private _status: BehaviorSubject = new BehaviorSubject(null) + private _activeRun: BehaviorSubject = new BehaviorSubject(null); + private _activeTask: BehaviorSubject = new BehaviorSubject(null); + + constructor(private _configService: AppConfig, private _runInfo: ClientRunInfoService, private _dresUser: UserService,) { + this._configService.configAsObservable.subscribe(config => { + if (config?.dresEndpointRest == null) { + return + } + this._dresUser.getApiV1User().subscribe( + { + next: (user) => { + this._status.next(user) + }, + error: (error) => { + this._status.error(error) + } + }) + } + ) + + // init dres info + this.updateDresInfo() + + // update every 5 seconds + setInterval( + () => { + this.updateDresInfo() + }, + 5 * 1000 + ) + + } + + private updateDresInfo() { + if (this.getStatus() == null) { + return + } + this._runInfo.getApiV1ClientRunInfoList(this.getStatus()?.sessionId).subscribe(list => { + const l = list.runs.filter(info => info.status == 'ACTIVE'); + const activeRun = l.length == 0 ? null : l[0] + this._activeRun.next(activeRun) + if (activeRun) { + this._runInfo.getApiV1ClientRunInfoCurrenttaskWithRunid(this._activeRun.getValue().id, this.getStatus().sessionId).subscribe(task => { + this._activeTask.next(task) + }) + } + }) + } + + public statusObservable(): Observable { + return this._status.asObservable() + } + + public activeTaskObservable(): Observable { + return this._activeTask.asObservable() + } + + public activeRunObservable(): Observable { + return this._activeRun.asObservable() + } + + public activeTask(): ClientTaskInfo { + return this._activeTask.getValue() + } + + public activeRun(): ClientRunInfo { + return this._activeRun.getValue() + } + + /** + * Returns null if an error was thrown during connection + */ + public getStatus(): UserDetails { + try { + if (this._status.getValue()) { + return this._status.getValue() + } + return null + } catch (e) { + return null + } + } +} \ No newline at end of file diff --git a/src/app/core/basics/event-bus.service.ts b/src/app/core/basics/event-bus.service.ts index 8b355194..978859b9 100644 --- a/src/app/core/basics/event-bus.service.ts +++ b/src/app/core/basics/event-bus.service.ts @@ -17,7 +17,7 @@ export class EventBusService { private _currentView: Subject = new BehaviorSubject(null); /** The subject used to track the currently active view. */ - private _lastQuery: Subject = new BehaviorSubject(null); + private _lastQuery = new BehaviorSubject(null); /** * Publishes a nev InteractionEvent to the bus. @@ -44,12 +44,10 @@ export class EventBusService { } /** - * Returns an observable that allows a consumer to be informed about the last query issued. - * - * @return {Observable} + * Returns the latest query */ - public lastQuery(): Observable { - return this._lastQuery.asObservable() + public lastQueryInteractionEvent(): InteractionEvent { + return this._lastQuery.getValue() } /** diff --git a/src/app/core/basics/notification.service.ts b/src/app/core/basics/notification.service.ts index ca58eb0c..e2bf470f 100644 --- a/src/app/core/basics/notification.service.ts +++ b/src/app/core/basics/notification.service.ts @@ -1,17 +1,18 @@ import {Injectable} from '@angular/core'; import {BehaviorSubject, combineLatest, of} from 'rxjs'; -import {VbsSubmissionService} from '../vbs/vbs-submission.service'; +import {VbsSubmissionService} from '../competition/vbs-submission.service'; import {NotificationUtil} from '../../shared/util/notification.util'; import {catchError, tap} from 'rxjs/operators'; import {AppConfig} from '../../app.config'; +import {DresService} from './dres.service'; @Injectable() export class NotificationService { private _dresStatusBadge = new BehaviorSubject('') - constructor(private _submissionService: VbsSubmissionService, private _configService: AppConfig) { - combineLatest([this._submissionService.statusObservable, this._configService.configAsObservable]).pipe( + constructor(private _submissionService: VbsSubmissionService, private _configService: AppConfig, private _dresService: DresService) { + combineLatest([this._dresService.statusObservable(), this._configService.configAsObservable]).pipe( tap(([status, config]) => { if (config._config.competition.host) { /* Do not update observable for undefined since that is the initial value*/ diff --git a/src/app/core/vbs/collabordinator.service.ts b/src/app/core/competition/collabordinator.service.ts similarity index 84% rename from src/app/core/vbs/collabordinator.service.ts rename to src/app/core/competition/collabordinator.service.ts index e047b048..8748091f 100644 --- a/src/app/core/vbs/collabordinator.service.ts +++ b/src/app/core/competition/collabordinator.service.ts @@ -30,7 +30,7 @@ export class CollabordinatorService extends Subject { constructor(@Inject(AppConfig) _config: AppConfig) { super(); _config.configAsObservable.pipe( - filter(c => c.get('competition.collabordinator') != null) + filter(c => c._config.competition.collabordinator != null) ).subscribe(c => { this._config = c; this.connect(); @@ -86,21 +86,24 @@ export class CollabordinatorService extends Subject { if (this._webSocket) { this._webSocket.complete(); } - this._webSocket = webSocket(this._config.get('competition.collabordinator')); + this._webSocket = webSocket(this._config._config.competition.collabordinator); + this._online.next(true) this._webSocket.subscribe( - v => { - this.next(v) - this._online.next(true) - }, - e => { - console.log('Error occurred while communicating with Collabordinator web service'); - this._online.next(false) - }, - () => { - console.log('Connection to Collabordinator web service was closed.'); - this._online.next(false) + { + next: (v) => { + this.next(v) + }, + error: (error) => { + console.error('Error occurred while communicating with Collabordinator web service'); + console.error(error) + this._online.next(false) + }, + complete: () => { + console.log('Connection to Collabordinator web service was closed.'); + this._online.next(false) + } } - ); + ) return true; } } diff --git a/src/app/core/vbs/vbs.module.ts b/src/app/core/competition/competition.module.ts similarity index 95% rename from src/app/core/vbs/vbs.module.ts rename to src/app/core/competition/competition.module.ts index 5ddaa0eb..39cd7fe7 100644 --- a/src/app/core/vbs/vbs.module.ts +++ b/src/app/core/competition/competition.module.ts @@ -13,4 +13,4 @@ import {AppConfig} from '../../app.config'; declarations: [], providers: [VbsSubmissionService, CollabordinatorService] }) -export class VbsModule { } +export class CompetitionModule { } diff --git a/src/app/core/vbs/dres-type-converter.util.ts b/src/app/core/competition/dres-type-converter.util.ts similarity index 100% rename from src/app/core/vbs/dres-type-converter.util.ts rename to src/app/core/competition/dres-type-converter.util.ts diff --git a/src/app/core/competition/logging/filter-information.ts b/src/app/core/competition/logging/filter-information.ts new file mode 100644 index 00000000..e9bb77de --- /dev/null +++ b/src/app/core/competition/logging/filter-information.ts @@ -0,0 +1,50 @@ +import {MediaObjectDescriptor} from "../../../../../openapi/cineast"; +import {ColorLabel} from "../../../shared/model/misc/colorlabel.model"; +import {Tag} from "../../selection/tag.model"; + +/** + * A simple data class for logging + */ +export class FilterInformation { + + /** + * When set to true, objects who have metadata matching for any of the categories are displayed. + */ + useOrForMetadataCategoriesFilter = false; + + id: string; + + /** + * A filter by MediaType. Affects both MediaObjectScoreContainers and MediaSegmentScoreContainers. If non-empty, only objects + * that match one of the MediaTypes contained in this array will pass the filter. + */ + mediatypes: Map = new Map(); + + /** + * A filter by dominant color. Affects only MediaSegmentScoreContainers. If non-empty, only segments + * that match at least one of the dominant colors contained in this array will pass the filter. + */ + dominant: Map = new Map(); + + /** + * A filter by metadata. For each metadata category (e.g. day), a list of allowed values is kept. + * If empty, all results are displayed. If non-empty, only results are displayed where for every key in the filter, the metadata value of the object matches an allowed value in the list. + * Behavior across categories is determined by a different boolean. + * If the object does not have one of the metadata keys, it is filtered. + */ + filterMetadata: Map> = new Map(); + + /** + * A filter for tags. This is the list of allowed tag names. If the set is empty, no filter is applied. + */ + filterTags: Set = new Set(); + + /** + * A filter by metadata for numeric values. + * For each category, a min and max number is kept (or null) + */ + filterRangeMetadata: Map = new Map(); + + /** Threshold for score filtering. */ + threshold = 0.0; +} \ No newline at end of file diff --git a/src/app/core/competition/logging/query-log-item.ts b/src/app/core/competition/logging/query-log-item.ts new file mode 100644 index 00000000..0bf60df7 --- /dev/null +++ b/src/app/core/competition/logging/query-log-item.ts @@ -0,0 +1,7 @@ +import {ClientRunInfo, ClientTaskInfo} from '../../../../../openapi/dres'; + +export interface QueryLogItem { + query: any, + dresTask: ClientTaskInfo, + dresRun: ClientRunInfo, +} diff --git a/src/app/core/competition/logging/result-log-item.ts b/src/app/core/competition/logging/result-log-item.ts new file mode 100644 index 00000000..da04f369 --- /dev/null +++ b/src/app/core/competition/logging/result-log-item.ts @@ -0,0 +1,8 @@ +import {FilterInformation} from "./filter-information"; +import {SegmentScoreLogContainer} from "./segment-score-log-container"; + +export interface ResultLogItem { + filter: FilterInformation + query: any, + results: SegmentScoreLogContainer[], +} \ No newline at end of file diff --git a/src/app/core/competition/logging/segment-score-log-container.ts b/src/app/core/competition/logging/segment-score-log-container.ts new file mode 100644 index 00000000..1dd40b0d --- /dev/null +++ b/src/app/core/competition/logging/segment-score-log-container.ts @@ -0,0 +1,15 @@ +export class SegmentScoreLogContainer { + public readonly objectId: string; + public readonly segmentId: string; + public readonly startabs: number; + public readonly endabs: number; + public readonly _score: number; + + constructor(objectId: string, segmentId: string, startabs: number, endabs: number, score: number) { + this.objectId = objectId; + this.segmentId = segmentId; + this.startabs = startabs; + this.endabs = endabs; + this._score = score; + } +} \ No newline at end of file diff --git a/src/app/core/vbs/vbs-submission.service.ts b/src/app/core/competition/vbs-submission.service.ts similarity index 50% rename from src/app/core/vbs/vbs-submission.service.ts rename to src/app/core/competition/vbs-submission.service.ts index 9617720f..d7702930 100644 --- a/src/app/core/vbs/vbs-submission.service.ts +++ b/src/app/core/competition/vbs-submission.service.ts @@ -2,7 +2,7 @@ import {Injectable} from '@angular/core'; import {MediaSegmentScoreContainer} from '../../shared/model/results/scores/segment-score-container.model'; import {VideoUtil} from '../../shared/util/video.util'; import {HttpClient} from '@angular/common/http'; -import {BehaviorSubject, combineLatest, EMPTY, Observable, of, Subject, Subscription} from 'rxjs'; +import {combineLatest, EMPTY, Observable, of, Subject, Subscription} from 'rxjs'; import {MatSnackBar} from '@angular/material/snack-bar'; import {Config} from '../../shared/model/config/config.model'; import {EventBusService} from '../basics/event-bus.service'; @@ -14,8 +14,13 @@ import {DatabaseService} from '../basics/database.service'; import Dexie from 'dexie'; import {AppConfig} from '../../app.config'; import {MetadataService} from '../../../../openapi/cineast'; -import {LogService, QueryEventLog, QueryResultLog, SubmissionService, SuccessfulSubmissionsStatus, UserDetails, UserService} from '../../../../openapi/dres'; +import {LogService, QueryEventLog, QueryResultLog, SubmissionService, SuccessfulSubmissionsStatus, UserService} from '../../../../openapi/dres'; import {TemporalListComponent} from '../../results/temporal/temporal-list.component'; +import {FilterService} from '../queries/filter.service'; +import {ResultLogItem} from './logging/result-log-item'; +import {SegmentScoreLogContainer} from './logging/segment-score-log-container'; +import {QueryLogItem} from './logging/query-log-item'; +import {DresService} from '../basics/dres.service'; /** * This service is used to submit segments to VBS web-service for the Video Browser Showdown challenge. Furthermore, if @@ -38,24 +43,23 @@ export class VbsSubmissionService { /** Reference to the subscription that is used to submit updates to the results list. */ private _resultsSubscription: Subscription; - /** Reference to the subscription for temporal scoring objects that is used to submit updates to the results list. */ - private _temporalResultsSubscription: Subscription; - - /** Reference to the subscription that is used to submit interaction logs on a regular basis to the VBS server. */ private _interactionlogSubscription: Subscription; - /** Reference to the subscription to the vitrivr NG configuration. */ - private _configSubscription: Subscription; + /** Table for persisting our result logs. */ + private _resultsLogTable: Dexie.Table; - /** Table for persisting result logs. */ - private _resultsLogTable: Dexie.Table; + /** Table for persisting our query logs. */ + private _queryLogTable: Dexie.Table; - /** Table for persisting submission logs */ - private _submissionLogTable: Dexie.Table; + /** Table for persisting DRES result logs. */ + private _dresResultsLogTable: Dexie.Table; - /** Table for persisting interaction logs. */ - private _interactionLogTable: Dexie.Table; + /** Table for persisting DRES submission logs */ + private _dresSubmissionLogTable: Dexie.Table; + + /** Table for persisting DRES interaction logs. */ + private _dresInteractionLogTable: Dexie.Table; /** Internal flag used to determine if VBS competition is running. */ private _vbs = false; @@ -63,11 +67,11 @@ export class VbsSubmissionService { /** Internal flag used to determine if LSC competition is running. */ private _lsc = false; - /** SessionID retrieved from DRES endpoint, automatically connected via second tab. Does not support private mode */ - private _sessionId:string = undefined; + /** Internal flag used to determine whether interactions, submissions and results should be logged. */ + private _log = false; - /** Observable used to query the DRES status.*/ - private _status: BehaviorSubject = new BehaviorSubject(null) + /** SessionID retrieved from DRES endpoint, automatically connected via second tab. Does not support private mode */ + private _sessionId: string = undefined; constructor(private _config: AppConfig, private _eventbus: EventBusService, @@ -79,36 +83,35 @@ export class VbsSubmissionService { private _dresSubmit: SubmissionService, private _dresLog: LogService, private _dresUser: UserService, - _db: DatabaseService) { + _db: DatabaseService, + private _filterService: FilterService, + private _dresService: DresService) { /* This subscription registers the event-mapping, recording and submission stream if the VBS mode is active and un-registers it, if it is switched off! */ - this._configSubscription = _config.configAsObservable.subscribe(config => { - if (config?.dresEndpointRest) { + _config.configAsObservable.subscribe(config => { + if (!config) { + return + } + this._log = config._config.competition.log + if (this._log) { + this._dresResultsLogTable = _db.db.table('log_results_dres'); this._resultsLogTable = _db.db.table('log_results'); - this._interactionLogTable = _db.db.table('log_interaction'); - this._submissionLogTable = _db.db.table('log_submission'); + this._queryLogTable = _db.db.table('log_queries'); + this._dresInteractionLogTable = _db.db.table('log_interaction_dres'); + this._dresSubmissionLogTable = _db.db.table('log_submission_dres'); this.reset(config) - this._dresUser.getApiV1User().subscribe( - { - next: (user) => { - this._status.next(user) - }, - error: (error) => this._status.error(error) - }) - this._status.subscribe({ - next: (user) => { - if (user) { - this._sessionId = user.sessionId; - } - }, - error: (e) => { - console.error('failed to connect to DRES', e) - } - }) - } else { - this.cleanup() } }); + this._dresService.statusObservable().subscribe({ + next: (user) => { + if (user) { + this._sessionId = user.sessionId; + } + }, + error: (e) => { + console.error('failed to connect to DRES', e) + } + }) } @@ -118,7 +121,9 @@ export class VbsSubmissionService { * @return {boolean} */ get isOn(): Observable { - return this._config.configAsObservable.pipe(map(c => c.get('competition.host'))); + return this._config.configAsObservable.pipe( + map(c => c.dresEndpointRest == null) + ) } /** @@ -143,8 +148,8 @@ export class VbsSubmissionService { } } - public submitText(text: string){ - if(this.isOn){ + public submitText(text: string) { + if (this.isOn) { // TODO how to log textual submissions? console.log(`Submitting text ${text}`); this._submitTextSubject.next(text); @@ -158,10 +163,12 @@ export class VbsSubmissionService { * @param time The video timestamp to submit. */ public submit(segment: MediaSegmentScoreContainer, time: number) { - this._submissionLogTable.add([segment.segmentId, time]) + if (this._log) { + this._dresSubmissionLogTable.add([segment.segmentId, time]) + } console.debug(`Submitting segment ${segment.segmentId} @ ${time}`); this._submitSubject.next([segment, time]); - this._selection.add(this._selection._available[0], segment.segmentId); + this._selection.add(this._selection._available[1], segment.segmentId); } /** @@ -169,142 +176,180 @@ export class VbsSubmissionService { */ public reset(config: Config) { /* Update local flags. */ - this._lsc = config.get('competition.lsc'); - this._vbs = config.get('competition.vbs'); + this._lsc = config._config.competition.lsc + this._vbs = config._config.competition.vbs; /* Run cleanup. */ this.cleanup(); /* Setup interaction log subscription, which runs in a regular interval. */ - if (config.get('competition.log') === true) { + if (this._log) { this._interactionlogSubscription = DresTypeConverter.mapEventStream(this._eventbus.observable()).pipe( - bufferTime(config.get('competition.loginterval')), - map((events: QueryEventLog[], index: number) => { - if (events && events.length > 0) { - const composite = {timestamp: Date.now(), events: []} - for (const e of events) { - composite.events.push(...e.events) - } - return composite - } else { - return null - } - }), - filter(submission => submission != null), - mergeMap((submission: QueryEventLog) => { - this._interactionLogTable.add(submission); - - /* Stop if no sessionId is set */ - if (!this._sessionId) { - return EMPTY + bufferTime(config._config.competition.loginterval), + map((events: QueryEventLog[]) => { + if (events && events.length > 0) { + const composite = {timestamp: Date.now(), events: []} + for (const e of events) { + composite.events.push(...e.events) } + return composite + } else { + return null + } + }), + filter(submission => submission != null), + mergeMap((submission: QueryEventLog) => { + this._dresInteractionLogTable.add(submission); + + /* Stop if no sessionId is set */ + if (!this._sessionId) { + return EMPTY + } - /* Submit Log entry to DRES. */ - console.log(`Submitting interaction log to DRES.`); - return this._dresLog.postApiV1LogQuery(this._sessionId, submission).pipe( - tap(o => { - console.log(`Successfully submitted interaction log to DRES.`); - }), - catchError((err) => { - return of(`Failed to submit segment to DRES due to a HTTP error (${err}).`) - }) - ); - }) + /* Submit Log entry to DRES. */ + console.log(`Submitting interaction log to DRES.`); + return this._dresLog.postApiV1LogQuery(this._sessionId, submission).pipe( + tap(o => { + console.log(`Successfully submitted interaction log to DRES.`); + }), + catchError((err) => { + return of(`Failed to submit segment to DRES due to a HTTP error (${err}).`) + }) + ); + }) ).subscribe(); /* Setup results subscription, which is triggered upon change to the result set. */ - const resultSubscription = this._queryService.observable.pipe( - filter(f => f === 'ENDED'), - mergeMap(f => this._queryService.results.segmentsAsObservable), - debounceTime(1000) + const resultSubscription: Observable = this._queryService.observable.pipe( + filter(f => f === 'ENDED'), + mergeMap(f => this._queryService.results.segmentsAsObservable), + debounceTime(1000) ); /* IMPORTANT: Limits the number of submissions to one per second. */ /* Setup results subscription, which is triggered upon change to the result set. */ const temporalResultsSubscription = this._queryService.observable.pipe( - filter(f => f === 'ENDED'), - mergeMap(f => this._queryService.results.temporalObjectsAsObservable), - debounceTime(1000) + filter(f => f === 'ENDED'), + mergeMap(f => this._queryService.results.temporalObjectsAsObservable), + debounceTime(1000) ); /* IMPORTANT: Limits the number of submissions to one per second. */ + /* Setup results subscription, which is triggered upon change to the result set. */ + const filterSubscription = this._filterService.filterSubject.pipe( + debounceTime(1000) + ); /* IMPORTANT: Limits the number of filter updates to one per second. */ + + this._queryService.observable.pipe( + filter(el => el == 'STARTED'), + tap(() => { + const task = this._dresService.activeTask() + const run = this._dresService.activeRun() + const query = this._queryService.lastQueryIssued() + const logItem: QueryLogItem = { + query: query, + dresTask: task, + dresRun: run, + } + console.log('logging query') + this._queryLogTable.add(logItem) + }) + ).subscribe() + + this._resultsSubscription = combineLatest([resultSubscription, temporalResultsSubscription, this._eventbus.currentView(), filterSubscription]).pipe( + debounceTime(200), + filter(() => { + if (this._eventbus.lastQueryInteractionEvent() === null) { + console.error('no query logged for interaction logging, not logging anything') + return false + } + if (this._queryService.lastQueryIssued() === null) { + console.error('no query logged in query service, not logging anything') + return false + } + return true + }), + tap(([results, temporalResults, context, filterInfo]) => { + console.log(`logging results`); + const query = this._queryService.lastQueryIssued() + let logResults: SegmentScoreLogContainer[] + switch (context) { + case TemporalListComponent.COMPONENT_NAME: + logResults = temporalResults.flatMap(seq => seq.segments.map(c => new SegmentScoreLogContainer(seq.object.objectid, c.segmentId, c.startabs, c.endabs, seq.score))) + break; + default: + logResults = results.map(c => new SegmentScoreLogContainer(c.objectId, c.segmentId, c.startabs, c.endabs, c.score)) + } + const logItem: ResultLogItem = { + filter: filterInfo, + query: query, + results: logResults + }; + this._resultsLogTable.add(logItem); + }), + map(([results, temporalResults, context, filterInfo]) => { + const query = this._eventbus.lastQueryInteractionEvent() + switch (context) { + case TemporalListComponent.COMPONENT_NAME: + return DresTypeConverter.mapTemporalScoreContainer(context, temporalResults, query) + default: + return DresTypeConverter.mapSegmentScoreContainer(context, results, query) + } + }), + filter(submission => submission != null), + mergeMap((submission: QueryResultLog) => { - this._resultsSubscription = combineLatest([resultSubscription, this._eventbus.currentView(), this._eventbus.lastQuery()]).pipe( - filter(([results, context, queryInfo]) => context !== TemporalListComponent.COMPONENT_NAME), - map(([results, context, queryInfo]) => DresTypeConverter.mapSegmentScoreContainer(context, results, queryInfo)), - filter(submission => submission != null), - mergeMap((submission: QueryResultLog) => { - this._resultsLogTable.add(submission) - - /* Stop if no sessionId is set */ - if (!this._sessionId) { - return EMPTY - } - - /* Do some logging and catch HTTP errors. */ - console.log(`Submitting result log to DRES...`); - return this._dresLog.postApiV1LogResult(this._sessionId, submission).pipe( - tap(o => { - console.log(`Successfully submitted result log to DRES!`); - }), - catchError((err) => { - return of(`Failed to submit segment to DRES due to a HTTP error (${err.status}).`) - }) - ); - }) - ).subscribe(); - - /* Heavily duplicated code from above */ - this._temporalResultsSubscription = combineLatest([temporalResultsSubscription, this._eventbus.currentView(), this._eventbus.lastQuery()]).pipe( - filter(([results, context, queryInfo]) => context === TemporalListComponent.COMPONENT_NAME), - map(([results, context, queryInfo]) => DresTypeConverter.mapTemporalScoreContainer(context, results, queryInfo)), - filter(submission => submission != null), - mergeMap((submission: QueryResultLog) => { - this._resultsLogTable.add(submission) - - /* Stop if no sessionId is set */ - if (!this._sessionId) { - return EMPTY - } + /* Stop if no sessionId is set */ + if (!this._sessionId) { + return EMPTY + } + this._dresResultsLogTable.add(submission) - /* Do some logging and catch HTTP errors. */ - console.log(`Submitting temporal result log to DRES...`); - return this._dresLog.postApiV1LogResult(this._sessionId, submission).pipe( - tap(o => { - console.log(`Successfully submitted result log to DRES!`); - }), - catchError((err) => { - return of(`Failed to submit segment to DRES due to a HTTP error (${err.status}).`) - }) - ); - }) + /* Do some logging and catch HTTP errors. */ + console.log(`Submitting result log to DRES...`); + return this._dresLog.postApiV1LogResult(this._sessionId, submission).pipe( + tap(o => { + console.log(`Successfully submitted result log to DRES!`); + }), + catchError((err) => { + return of(`Failed to submit segment to DRES due to a HTTP error (${err.status}).`) + }) + ); + }) ).subscribe(); } /* Setup submission subscription, which is triggered manually. */ this._submitSubscription = this._submitSubject.pipe( - map(([segment, time]): [string, number?] => this.convertToAppropriateRepresentation(segment, time)), - mergeMap(([segment, frame]) => { - /* Submit, do some logging and catch HTTP errors. */ - return this._dresSubmit.getApiV1Submit(null, segment, null, frame).pipe( - tap((status: SuccessfulSubmissionsStatus) => { - this.handleSubmissionResponse(status); - }), - catchError(err => { - return this.handleSubmissionError(err); - }) - ) - }) - ).subscribe() + map(([segment, time]): [string, number, string] => this.convertToAppropriateRepresentation(segment, time)), + mergeMap(([segment, frame, segmentId]) => { + /* Stop if no sessionId is set */ + if (!this._sessionId) { + return EMPTY + } + + this._dresSubmissionLogTable.add([segment, frame]) + /* Submit, do some logging and catch HTTP errors. */ + return this._dresSubmit.getApiV1Submit(null, segment, null, frame).pipe( + tap((status: SuccessfulSubmissionsStatus) => { + this.handleSubmissionResponse(status, segmentId); + }), + catchError(err => { + return this.handleSubmissionError(err, segmentId); + }) + ) + }) + ).subscribe(); /* Setup submission subscription, which is triggered manually. */ this._submitTextSubscription = this._submitTextSubject.pipe( mergeMap((text) => { + this._dresSubmissionLogTable.add(text) /* Submit, do some logging and catch HTTP errors. */ return this._dresSubmit.getApiV1Submit(null, null, text).pipe( tap((status: SuccessfulSubmissionsStatus) => { - this.handleSubmissionResponse(status); + this.handleSubmissionResponse(status, null); }), catchError(err => { - return this.handleSubmissionError(err); + return this.handleSubmissionError(err, null); }) ) }) @@ -312,7 +357,8 @@ export class VbsSubmissionService { } - private handleSubmissionError(err) { + private handleSubmissionError(err, segment) { + this._selection.add(this._selection._available[3], segment); if (err.error) { this._snackBar.open(`Submissions error: ${err.error.description}`, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-error'}) } else { @@ -321,12 +367,14 @@ export class VbsSubmissionService { return of(null) } - private handleSubmissionResponse(status: SuccessfulSubmissionsStatus) { + private handleSubmissionResponse(status: SuccessfulSubmissionsStatus, segment: string) { switch (status.submission) { case 'CORRECT': + this._selection.add(this._selection._available[2], segment); this._snackBar.open(status.description, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-success'}); break; case 'WRONG': + this._selection.add(this._selection._available[0], segment); this._snackBar.open(status.description, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-warning'}); break; default: @@ -335,33 +383,26 @@ export class VbsSubmissionService { } } - /** - * - */ - get statusObservable(): Observable { - return this._status - } - /** * Converts the given {MediaSegmentScoreContainer} and an optional timestamp to the exact form required by the respective * competition. DO YOUR CONVERSION and PRE-PROCESSING HERE please :-) * * @param segment The {MediaSegmentScoreContainer} to convert. * @param time The timepoint to convert. - * @return Tuple of ID and optional frame number. + * @return Tuple of ID, optional frame number and original segment id. */ - private convertToAppropriateRepresentation(segment: MediaSegmentScoreContainer, time?: number): [string, number?] { + private convertToAppropriateRepresentation(segment: MediaSegmentScoreContainer, time?: number): [string, number, string] { if (this._vbs) { let fps = Number.parseFloat(segment.objectScoreContainer._metadata.get('technical.fps')); if (Number.isNaN(fps) || !Number.isFinite(fps)) { fps = VideoUtil.bestEffortFPS(segment); } - return [segment.objectId.replace('v_', ''), VbsSubmissionService.timeToFrame(time, fps)] + return [segment.objectId.replace('v_', ''), VbsSubmissionService.timeToFrame(time, fps), segment.segmentId] } if (this._lsc) { - return [segment.segmentId.replace('is_', ''), time]; + return [segment.segmentId.replace('is_', ''), time, segment.segmentId]; } - return [segment.segmentId, time]; + return [segment.segmentId, time, segment.segmentId]; } /** diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index e589fac5..85651e8c 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -1,8 +1,8 @@ import {NgModule} from '@angular/core'; import {LookupModule} from './lookup/lookup.module'; import {BasicModule} from './basics/basic.module'; -import {VbsSubmissionService} from './vbs/vbs-submission.service'; -import {VbsModule} from './vbs/vbs.module'; +import {VbsSubmissionService} from './competition/vbs-submission.service'; +import {CompetitionModule} from './competition/competition.module'; import {SelectionModule} from './selection/selection.module'; import {SelectionService} from './selection/selection.service'; import {WebSocketFactoryService} from './api/web-socket-factory.service'; @@ -16,8 +16,8 @@ import {AppConfig} from '../app.config'; return new Configuration({ basePath: `${AppConfig.settings.cineastEndpointRest}` }) - }), LookupModule, BasicModule, VbsModule, SelectionModule, QueryModule], - exports: [ApiModule, LookupModule, BasicModule, VbsModule, SelectionModule, QueryModule], + }), LookupModule, BasicModule, CompetitionModule, SelectionModule, QueryModule], + exports: [ApiModule, LookupModule, BasicModule, CompetitionModule, SelectionModule, QueryModule], declarations: [], providers: [WebSocketFactoryService, VbsSubmissionService, SelectionService, PreviousRouteService] }) diff --git a/src/app/core/queries/filter.service.ts b/src/app/core/queries/filter.service.ts index 01c4c1fb..334ea5d2 100644 --- a/src/app/core/queries/filter.service.ts +++ b/src/app/core/queries/filter.service.ts @@ -6,6 +6,7 @@ import {ColorLabel, ColorLabels} from '../../shared/model/misc/colorlabel.model' import {SelectionService} from '../selection/selection.service'; import {Tag} from '../selection/tag.model'; import {MediaObjectDescriptor} from '../../../../openapi/cineast'; +import {FilterInformation} from "../competition/logging/filter-information"; /** @@ -15,11 +16,6 @@ import {MediaObjectDescriptor} from '../../../../openapi/cineast'; */ @Injectable() export class FilterService { - /** - * When set to true, objects who have metadata matching for any of the categories are displayed. - */ - public _useOrForMetadataCategoriesFilter = false; - _id: string; /** A BehaviorSubject that publishes changes to the filters affecting SegmentScoreContainers. */ _segmentFilters: BehaviorSubject<((v: MediaSegmentScoreContainer) => boolean)[]> = new BehaviorSubject([]); @@ -27,87 +23,58 @@ export class FilterService { /** A BehaviorSubject that publishes changes to the filters affecting MediaObjectScoreContainers. */ _objectFilters: BehaviorSubject<((v: MediaObjectScoreContainer) => boolean)[]> = new BehaviorSubject([]); - /** - * A filter by MediaType. Affects both MediaObjectScoreContainers and MediaSegmentScoreContainers. If non-empty, only objects - * that match one of the MediaTypes contained in this array will pass the filter. - */ - private _mediatypes: Map = new Map(); - - /** - * A filter by dominant color. Affects only MediaSegmentScoreContainers. If non-empty, only segments - * that match at least one of the dominant colors contained in this array will pass the filter. - */ - private _dominant: Map = new Map(); + _filters: FilterInformation = new FilterInformation(); - /** - * A filter by metadata. For each metadata category (e.g. day), a list of allowed values is kept. - * If empty, all results are displayed. If non-empty, only results are displayed where for every key in the filter, the metadata value of the object matches an allowed value in the list. - * Behavior across categories is determined by a different boolean. - * If the object does not have one of the metadata keys, it is filtered. - */ - private _filterMetadata: Map> = new Map(); - - /** - * A filter for tags. This is the list of allowed tag names. If the set is empty, no filter is applied. - */ - private _filterTags: Set = new Set(); - - /** - * A filter by metadata for numeric values. - * For each category, a min and max number is kept (or null) - */ - private _filterRangeMetadata: Map = new Map(); + filterSubject: BehaviorSubject = new BehaviorSubject(this._filters); - /** Threshold for score filtering. */ - private _threshold = 0.0; constructor(private _selectionService: SelectionService) { - Object.keys(MediaObjectDescriptor.MediatypeEnum).map(key => MediaObjectDescriptor.MediatypeEnum[key]).forEach(v => this._mediatypes.set(v, false)); - ColorLabels.forEach(v => this._dominant.set(v, false)); + Object.keys(MediaObjectDescriptor.MediatypeEnum).map(key => MediaObjectDescriptor.MediatypeEnum[key]).forEach(v => this._filters.mediatypes.set(v, false)); + ColorLabels.forEach(v => this._filters.dominant.set(v, false)); } /** * Returns an editable map of the mediatypes that should be used for filtering */ get mediatypes(): Map { - return this._mediatypes; + return this._filters.mediatypes; } /** * Returns an editable map of the colorlabels that should be used for filtering */ get dominant(): Map { - return this._dominant; + return this._filters.dominant; } /** * Returns an editable map of the metadata that should be used for filtering */ get filterMetadata(): Map> { - return this._filterMetadata + return this._filters.filterMetadata } /** * Returns the editable set of tags used for filtering */ get filterTags(): Set { - return this._filterTags; + return this._filters.filterTags; } /** * Returns an editable map of the metadata that should be used for filtering with ranges */ get filterRangeMetadata(): Map { - return this._filterRangeMetadata + return this._filters.filterRangeMetadata } get threshold(): number { - return this._threshold; + return this._filters.threshold; } set threshold(value: number) { if (value >= 0.0 && value <= 1.0) { - this._threshold = value; + this._filters.threshold = value; } } @@ -115,27 +82,27 @@ export class FilterService { * Returns a copy of the list of MediaTypes that should be used for filtering. */ get mediatypeKeys(): MediaObjectDescriptor.MediatypeEnum[] { - return Array.from(this._mediatypes.keys()); + return Array.from(this._filters.mediatypes.keys()); } /** * Returns a copy of the list of colors that should be used for filtering. */ get dominantKeys(): ColorLabel[] { - return Array.from(this._dominant.keys()); + return Array.from(this._filters.dominant.keys()); } /** * Clears all filters. Causes an update to be published. */ public clear() { - this._mediatypes.forEach((v, k) => this._mediatypes.set(k, false)); - this._dominant.forEach((v, k) => this._dominant.set(k, false)); - this._filterMetadata.clear(); - this._filterRangeMetadata.clear(); - this._filterTags.clear(); - this._threshold = 0.0; - this._id = null + this._filters.mediatypes.forEach((v, k) => this._filters.mediatypes.set(k, false)); + this._filters.dominant.forEach((v, k) => this._filters.dominant.set(k, false)); + this._filters.filterMetadata.clear(); + this._filters.filterRangeMetadata.clear(); + this._filters.filterTags.clear(); + this._filters.threshold = 0.0; + this._filters.id = null this.update() } @@ -144,8 +111,8 @@ export class FilterService { * Clear metadata filters. Causes an update to be published */ public clearMetadata() { - this._filterMetadata.clear(); - this._filterRangeMetadata.clear(); + this._filters.filterMetadata.clear(); + this._filters.filterRangeMetadata.clear(); this.update(); } @@ -157,9 +124,9 @@ export class FilterService { const objectFilters: ((v: MediaObjectScoreContainer) => boolean)[] = []; const segmentFilters: ((v: MediaSegmentScoreContainer) => boolean)[] = []; - if (this._id) { - objectFilters.push((o) => o.objectid === this._id) - segmentFilters.push((s) => s.objectId === this._id || s.segmentId === this._id) + if (this._filters.id) { + objectFilters.push((o) => o.objectid === this._filters.id) + segmentFilters.push((s) => s.objectId === this._filters.id || s.segmentId === this._filters.id) } /* Inline function for range metadata filters @@ -192,7 +159,7 @@ export class FilterService { return true } - if (!(this._filterMetadata.size === 0 && this._filterRangeMetadata.size === 0 && this._filterTags.size === 0)) { + if (!(this._filters.filterMetadata.size === 0 && this._filters.filterRangeMetadata.size === 0 && this._filters.filterTags.size === 0)) { console.debug(`updating filters`); // of course, the AND filter can only be falsified by non-matching filter criteria while the OR filter can only be set to true if one of the conditions match @@ -204,7 +171,7 @@ export class FilterService { let andFilter = Boolean(true); let orFilter = Boolean(false); let tagFilter = Boolean(false); - this._filterMetadata.forEach((mdAllowedValuesSet, mdKey) => { + this._filters.filterMetadata.forEach((mdAllowedValuesSet, mdKey) => { // check if either one of the underlying segments or the object itself has appropriate metadata if (obj.segments.findIndex(seg => mdAllowedValuesSet.has(seg.metadata.get(mdKey))) >= 0 || mdAllowedValuesSet.has(obj._metadata.get(mdKey))) { orFilter = true; @@ -212,7 +179,7 @@ export class FilterService { } andFilter = false; }); - this._filterRangeMetadata.forEach((range, mdKey) => { + this._filters.filterRangeMetadata.forEach((range, mdKey) => { // check if one of the segments fulfills both range conditions if (obj.segments.findIndex(seg => checkRange(range, seg.metadata.get(mdKey))) >= 0) { orFilter = true; @@ -225,46 +192,46 @@ export class FilterService { } andFilter = false; }); - if (this._filterTags.size === 0) { + if (this._filters.filterTags.size === 0) { tagFilter = true; } - this._filterTags.forEach(tag => { + this._filters.filterTags.forEach(tag => { if (obj.segments.findIndex(seg => this._selectionService.hasTag(seg.segmentId, tag)) >= 0) { tagFilter = true; } }); - return this._useOrForMetadataCategoriesFilter ? orFilter && tagFilter : andFilter && tagFilter; + return this._filters.useOrForMetadataCategoriesFilter ? orFilter && tagFilter : andFilter && tagFilter; }); segmentFilters.push((seg) => { let andFilter = Boolean(true); let orFilter = Boolean(false); // check whether the segment or the corresponding object has appropriate metadata - this._filterMetadata.forEach((mdAllowedValuesSet, mdKey) => { + this._filters.filterMetadata.forEach((mdAllowedValuesSet, mdKey) => { if (mdAllowedValuesSet.has(seg.metadata.get(mdKey)) || mdAllowedValuesSet.has(seg.objectScoreContainer._metadata.get(mdKey))) { orFilter = true; return; } andFilter = false; }); - this._filterRangeMetadata.forEach((range, mdKey) => { + this._filters.filterRangeMetadata.forEach((range, mdKey) => { if (checkRange(range, seg.metadata.get(mdKey)) || checkRange(range, seg.objectScoreContainer._metadata.get(mdKey))) { orFilter = true; return; } andFilter = false; }); - return this._useOrForMetadataCategoriesFilter ? orFilter : andFilter; + return this._filters.useOrForMetadataCategoriesFilter ? orFilter : andFilter; }); } - if (!this.mediatypeKeys.every(v => this._mediatypes.get(v) === false)) { - objectFilters.push((obj) => this._mediatypes.get(obj.mediatype) === true); - segmentFilters.push((seg) => this._mediatypes.get(seg.objectScoreContainer.mediatype) === true); + if (!this.mediatypeKeys.every(v => this._filters.mediatypes.get(v) === false)) { + objectFilters.push((obj) => this._filters.mediatypes.get(obj.mediatype) === true); + segmentFilters.push((seg) => this._filters.mediatypes.get(seg.objectScoreContainer.mediatype) === true); } - if (!this.dominantKeys.every(v => this._dominant.get(v) === false)) { - segmentFilters.push((seg) => seg.metadata.has('dominantcolor.color') && this._dominant.get(seg.metadata.get('dominantcolor.color').toUpperCase()) === true); + if (!this.dominantKeys.every(v => this._filters.dominant.get(v) === false)) { + segmentFilters.push((seg) => seg.metadata.has('dominantcolor.color') && this._filters.dominant.get(seg.metadata.get('dominantcolor.color').toUpperCase()) === true); } /* Filter for score threshold. */ @@ -276,5 +243,6 @@ export class FilterService { /* Publish changes. */ this._objectFilters.next(objectFilters); this._segmentFilters.next(segmentFilters); + this.filterSubject.next(this._filters) } } diff --git a/src/app/core/queries/history.service.ts b/src/app/core/queries/history.service.ts index 9e9ed19e..1f57fbb6 100644 --- a/src/app/core/queries/history.service.ts +++ b/src/app/core/queries/history.service.ts @@ -2,8 +2,8 @@ import {Inject, Injectable} from '@angular/core'; import {ResultsContainer} from '../../shared/model/results/scores/results-container.model'; import {HistoryContainer} from '../../shared/model/internal/history-container.model'; import Dexie from 'dexie'; -import {first, map, mergeMap} from 'rxjs/operators'; -import {EMPTY, from, Observable} from 'rxjs'; +import {first, map} from 'rxjs/operators'; +import {from, Observable} from 'rxjs'; import {DatabaseService} from '../basics/database.service'; import * as JSZip from 'jszip'; import {AppConfig} from '../../app.config'; @@ -99,7 +99,7 @@ export class HistoryService { */ public download() { from(this._historyTable.orderBy('id').toArray()) - .pipe( + .pipe( first(), map(h => { const zip = new JSZip(); @@ -107,17 +107,17 @@ export class HistoryService { zip.file('vitrivrng-history.json', JSON.stringify(h, null, 2), options); return zip }) - ) - .subscribe(zip => { - zip.generateAsync({type: 'blob'}).then( + ) + .subscribe(zip => { + zip.generateAsync({type: 'blob'}).then( (result) => { window.open(window.URL.createObjectURL(result)); }, (error) => { console.log(error); } - ) - }); + ) + }); } /** @@ -125,16 +125,12 @@ export class HistoryService { */ private ommitOldest() { from(this._historyTable.count()).pipe( - mergeMap(c => { - if (c > this._keep) { - return from(this._historyTable.limit(c - this._keep).keys()); - } else { - return EMPTY; - } - }), - mergeMap((a, i) => { - return from(this._historyTable.bulkDelete(a)); - }) + map(c => { + if (c > this._keep) { + // default order is asc + this._historyTable.orderBy("timestamp").limit(c - this.keep).delete() + } + }) ).subscribe(); } } diff --git a/src/app/core/queries/query.service.ts b/src/app/core/queries/query.service.ts index db3b9e32..b76e248d 100644 --- a/src/app/core/queries/query.service.ts +++ b/src/app/core/queries/query.service.ts @@ -10,7 +10,7 @@ import {ResultsContainer} from '../../shared/model/results/scores/results-contai import {NeighboringSegmentQuery} from '../../shared/model/messages/queries/neighboring-segment-query.model'; import {FeatureCategories} from '../../shared/model/results/feature-categories.model'; import {QueryContainerInterface} from '../../shared/model/queries/interfaces/query-container.interface'; -import {filter, first} from 'rxjs/operators'; +import {filter} from 'rxjs/operators'; import {WebSocketFactoryService} from '../api/web-socket-factory.service'; import {SegmentMetadataQueryResult} from '../../shared/model/messages/interfaces/responses/query-result-segment-metadata.interface'; import {ObjectMetadataQueryResult} from '../../shared/model/messages/interfaces/responses/query-result-object-metadata.interface'; @@ -30,8 +30,8 @@ import {AppConfig} from '../../app.config'; import {MediaObjectDescriptor, MediaObjectQueryResult, MediaSegmentDescriptor, MediaSegmentQueryResult, QueryConfig} from '../../../../openapi/cineast'; import {TemporalQuery} from '../../shared/model/messages/queries/temporal-query.model'; import {TemporalQueryResult} from '../../shared/model/messages/interfaces/responses/query-result-temporal.interface'; -import MediatypeEnum = MediaObjectDescriptor.MediatypeEnum; import {ReadableTemporalQueryConfig} from '../../shared/model/messages/queries/readable-temporal-query-config.model'; +import MediatypeEnum = MediaObjectDescriptor.MediatypeEnum; /** * Types of changes that can be emitted from the QueryService. @@ -63,6 +63,9 @@ export class QueryService { /** Flag indicating whether a query is currently being executed. */ private _running = 0; + /** last query which was issued */ + private _lastQuery = null; + constructor(@Inject(HistoryService) private _history, @Inject(WebSocketFactoryService) _factory: WebSocketFactoryService, @Inject(AppConfig) private _config: AppConfig, @@ -70,7 +73,7 @@ export class QueryService { _factory.asObservable().pipe(filter(ws => ws != null)).subscribe(ws => { this._socket = ws; this._socket.pipe( - filter(msg => ['QR_START', 'QR_END', 'QR_ERROR', 'QR_SIMILARITY', 'QR_OBJECT', 'QR_SEGMENT', 'QR_TEMPORAL', 'QR_METADATA_S', 'QR_METADATA_O'].indexOf(msg.messageType) > -1) + filter(msg => ['QR_START', 'QR_END', 'QR_ERROR', 'QR_SIMILARITY', 'QR_OBJECT', 'QR_SEGMENT', 'QR_TEMPORAL', 'QR_METADATA_S', 'QR_METADATA_O'].indexOf(msg.messageType) > -1) ).subscribe((msg: Message) => this.onApiMessage(msg)); }); this._config.configAsObservable.subscribe(config => { @@ -109,73 +112,6 @@ export class QueryService { return this._subject.asObservable(); } - /** - * Starts a new similarity query. Success is indicated by the return value. - * - * Note: Similarity queries can only be started if no query is currently running. - * - * @param containers The list of QueryContainers used to create the query. - * @returns {boolean} true if query was issued, false otherwise. - */ - public findSimilar(containers: QueryContainerInterface[]): boolean { - if (!this._socket) { - console.warn('No socket available, not executing similarity query'); - return false; - } - if (this._running > 0) { - console.warn('There is already a query running'); - } - this._config.configAsObservable.pipe(first()).subscribe(config => { - const query = new TemporalQuery( - containers.map(container => new StagedSimilarityQuery(container.stages, null)), - new ReadableTemporalQueryConfig(null, [], - null, -1), - config.metadataAccessSpec); - this._socket.next(query) - }); - - /** Log Interaction */ - const _components: InteractionEventComponent[] = [] - containers.forEach(container => { - _components.push(new InteractionEventComponent(InteractionEventType.NEW_QUERY_CONTAINER)) - container.stages.forEach(s => { - _components.push(new InteractionEventComponent(InteractionEventType.NEW_QUERY_STAGE)) - s.terms.forEach(t => { - const context: Map = new Map(); - context.set('q:categories', t.categories); - context.set('q:value', 'null') - switch (t.type) { - case 'IMAGE': - _components.push(new InteractionEventComponent(InteractionEventType.QUERY_IMAGE, context)); - return; - case 'AUDIO': - _components.push(new InteractionEventComponent(InteractionEventType.QUERY_AUDIO, context)); - return; - case 'MODEL3D': - _components.push(new InteractionEventComponent(InteractionEventType.QUERY_MODEL3D, context)); - return; - case 'SEMANTIC': - _components.push(new InteractionEventComponent(InteractionEventType.QUERY_SEMANTIC, context)); - return; - case 'TEXT': - context.set('q:value', (t as TextQueryTerm).data); // data = plaintext - _components.push(new InteractionEventComponent(InteractionEventType.QUERY_FULLTEXT, context)); - return; - case 'BOOLEAN': - context.set('q:value', (t as BoolQueryTerm).terms) - _components.push(new InteractionEventComponent(InteractionEventType.QUERY_BOOLEAN, context)); - return; - case 'TAG': - context.set('q:value', (t as TagQueryTerm).tags); - _components.push(new InteractionEventComponent(InteractionEventType.QUERY_TAG, context)); - return; - } - }) - }) - }); - this._eventBusService.publish(new InteractionEvent(..._components)) - } - /** * Starts a new temporal query. Success is indicated by the return value. * @@ -195,11 +131,12 @@ export class QueryService { console.warn('There is already a query running'); } const query = new TemporalQuery(containers.map(container => new StagedSimilarityQuery(container.stages, null)), - new ReadableTemporalQueryConfig(null, - [], - timeDistances, - maxLength), - this._config.config.metadataAccessSpec); + new ReadableTemporalQueryConfig(null, + [], + timeDistances, + maxLength), + this._config.config.metadataAccessSpec); + this._lastQuery = query; this._socket.next(query) /** Log Interaction */ @@ -287,10 +224,12 @@ export class QueryService { return; } _cat - .filter(c => categories.indexOf(c) === -1) - .forEach(c => categories.push(c)); + .filter(c => categories.indexOf(c) === -1) + .forEach(c => categories.push(c)); if (categories.length > 0) { - this._socket.next(new MoreLikeThisQuery(segment.segmentId, categories, {}, config.metadataAccessSpec)); + const query = new MoreLikeThisQuery(segment.segmentId, categories, {}, config.metadataAccessSpec) + this._lastQuery = query; + this._socket.next(query); } return true; @@ -452,6 +391,7 @@ export class QueryService { */ private startNewQuery(queryId: string) { /* Start the actual query. */ + console.debug('received QR_START') if (!this._results || (this._results && this._results.queryId !== queryId)) { this._results = new ResultsContainer(queryId); this._interval_map.set(queryId, window.setInterval(() => this._results.checkUpdate(), 2500)); @@ -494,4 +434,8 @@ export class QueryService { this._subject.next('ERROR' as QueryChange); console.log('QueryService received error: ' + message.message); } + + public lastQueryIssued() { + return this._lastQuery + } } diff --git a/src/app/core/selection/selection.service.ts b/src/app/core/selection/selection.service.ts index f1818ab8..b1f9cfa0 100644 --- a/src/app/core/selection/selection.service.ts +++ b/src/app/core/selection/selection.service.ts @@ -1,7 +1,7 @@ import {Injectable} from '@angular/core'; import {Tag} from './tag.model'; -import {BehaviorSubject} from 'rxjs'; -import {CollabordinatorService} from '../vbs/collabordinator.service'; +import {BehaviorSubject, Observable, Subject} from 'rxjs'; +import {CollabordinatorService} from '../competition/collabordinator.service'; import {CollabordinatorMessage} from '../../shared/model/messages/collaboration/collabordinator-message.model'; import {AppConfig} from '../../app.config'; @@ -10,12 +10,15 @@ import {AppConfig} from '../../app.config'; * issuing findSimilar requests, processing incoming responses and ranking of the requests. */ @Injectable() -export class SelectionService extends BehaviorSubject>> { +export class SelectionService extends BehaviorSubject> { /** List of available Tag objects. */ readonly _available: Tag[] = []; /** A map of selected items identified by a string and the associated Tag objects. */ - private readonly _selections: Map> = new Map(); + private readonly _selections: Map = new Map(); + + /** Caches all subscriptions to updates*/ + private _cache: Map> = new Map() /** * Constructor; injects the ConfigService. @@ -30,6 +33,18 @@ export class SelectionService extends BehaviorSubject>> { c.get('tags').forEach(t => this._available.push(new Tag(t.name, t.hue))); }); + _collabordinator._online.subscribe(online => { + console.debug(`new collabordinator status: ${online}`) + if (online) { + if (this._cache == null) { + this._cache = new Map() + } + } + if (!online) { + this._cache = null + } + }) + /* Register listener for Collabordinator. */ _collabordinator.subscribe(msg => this.synchronize(msg)); } @@ -43,11 +58,11 @@ export class SelectionService extends BehaviorSubject>> { public add(tag: Tag, ...identifiers: string[]) { for (const identifier of identifiers) { if (!this._selections.has(identifier)) { - this._selections.set(identifier, new Set([tag])); + this._selections.set(identifier, []); } - this._selections.get(identifier).add(tag); - this._collabordinator.add(tag, identifier); + this._selections.get(identifier).push(tag); this.next(this._selections); + this._cache?.get(identifier)?.next(this._selections.get(identifier)) } this._collabordinator.add(tag, ...identifiers) } @@ -64,8 +79,9 @@ export class SelectionService extends BehaviorSubject>> { for (const identifier of identifiers) { if (this._selections.has(identifier)) { const entry = this._selections.get(identifier); - entry.delete(tag); - if (entry.size === 0) { + this._selections.set(identifier, entry.filter(t => t != tag)); + this._cache?.get(identifier)?.next(this._selections.get(identifier)) + if (entry.length === 0) { this._selections.delete(identifier); } this.next(this._selections); @@ -77,20 +93,18 @@ export class SelectionService extends BehaviorSubject>> { /** * * @param {Tag} tag The tag to toggle. - * @param {string} identifiers The identifiers for which to toggle the tags. + * @param {string} identifier The identifier for which to toggle the tags. */ - public toggle(tag: Tag, ...identifiers: string[]) { - const active = []; - const inactive = []; - for (const identifier of identifiers) { - if (this._selections.has(identifier) && this._selections.get(identifier).has(tag)) { - active.push(identifier); - } else { - inactive.push(identifier); - } + public toggle(tag: Tag, identifier: string) { + if (!this._selections.has(identifier)) { + this.add(tag, identifier) + return + } + if (this._selections.get(identifier).findIndex(t => t == tag) == -1) { + this.add(tag, identifier) + } else { + this.remove(tag, identifier) } - this.remove(tag, ...active); - this.add(tag, ...inactive); } /** @@ -108,11 +122,11 @@ export class SelectionService extends BehaviorSubject>> { * @param {string} identifier The identifier to check. * @param {tag} tag The Tag that should be checked. */ - public hasTag(identifier: string, tag: Tag) { + public hasTag(identifier: string, tag: Tag): boolean { if (this._selections.has(identifier)) { - return this._selections.get(identifier).has(tag); + return this._selections.get(identifier).findIndex(t => t == tag) > -1; } - return false; + return false } /** @@ -122,35 +136,21 @@ export class SelectionService extends BehaviorSubject>> { */ public getTags(identifier: string): Tag[] { const tags: Tag[] = []; - if (this._selections.has(identifier)) { - this._selections.get(identifier).forEach(t => tags.push(t)); - } + this._selections.get(identifier)?.forEach(t => tags.push(t)); return tags; } /** * Clears all Tags and identifiers stored in this SelectionService. - * - * @param tag Optional Tag to remove. If null, all tags will be removed. */ - public clear(tag?: Tag) { - if (tag) { - this._selections.forEach((v, k) => { - if (v.has(tag)) { - v.delete(tag); - } - if (v.size === 0) { - this._selections.delete(k); - } - }); - this._collabordinator.clear(tag); - } else { - this._selections.clear(); + public clear(broadcast = true) { + this._selections.clear(); + if (broadcast) { for (const availableTag of this._available) { this._collabordinator.clear(availableTag); } } - + this._cache?.forEach(s => s.next([])) this.next(this._selections); } @@ -178,32 +178,34 @@ export class SelectionService extends BehaviorSubject>> { switch (msg.action) { case 'ADD': msg.attribute.forEach(v => { - if (!this._selections.has(v)) { - this._selections.set(v, new Set()); + if (this._selections.has(v)) { + if (this._selections.get(v).findIndex(t => t == tag) == -1) { + this.add(tag, v) + } + return } - this._selections.get(v).add(tag) + this.add(tag, v) }); break; case 'REMOVE': msg.attribute.forEach(v => { - if (this._selections.has(v)) { - this._selections.get(v).delete(tag); - } else if (this._selections.get(v).size === 0) { - this._selections.delete(v); - } + this.remove(tag, v) }); break; case 'CLEAR': - this._selections.forEach((v, k) => { - if (v.has(tag)) { - v.delete(tag); - } - if (v.size === 0) { - this._selections.delete(k); - } - }); + this.clear(false) break; } this.next(this._selections); } + + register(segmentId: string): Observable { + const subj = new Subject(); + this._cache?.set(segmentId, subj) + return subj.asObservable() + } + + deregister(segmentId: string) { + this._cache?.delete(segmentId) + } } diff --git a/src/app/objectdetails/objectdetails.component.ts b/src/app/objectdetails/objectdetails.component.ts index 2a6e64ea..9f8a071a 100644 --- a/src/app/objectdetails/objectdetails.component.ts +++ b/src/app/objectdetails/objectdetails.component.ts @@ -20,7 +20,7 @@ import {ObjectviewerComponent} from './objectviewer.component'; import {AppConfig} from '../app.config'; import {MediaSegmentDescriptor, MetadataService, ObjectService, SegmentService, TagService} from '../../../openapi/cineast'; import {SegmentFeaturesComponent} from '../segmentdetails/segment-features.component'; -import {VbsSubmissionService} from '../core/vbs/vbs-submission.service'; +import {VbsSubmissionService} from '../core/competition/vbs-submission.service'; @Component({ diff --git a/src/app/objectdetails/quick-viewer.component.ts b/src/app/objectdetails/quick-viewer.component.ts index 23f35c1e..dd6c4171 100644 --- a/src/app/objectdetails/quick-viewer.component.ts +++ b/src/app/objectdetails/quick-viewer.component.ts @@ -3,7 +3,7 @@ import {MAT_DIALOG_DATA} from '@angular/material/dialog'; import {MediaObjectScoreContainer} from '../shared/model/results/scores/media-object-score-container.model'; import {MediaSegmentScoreContainer} from '../shared/model/results/scores/segment-score-container.model'; import {ResolverService} from '../core/basics/resolver.service'; -import {VbsSubmissionService} from '../core/vbs/vbs-submission.service'; +import {VbsSubmissionService} from '../core/competition/vbs-submission.service'; import * as openseadragon from 'openseadragon'; import {ConfigService} from '../core/basics/config.service'; diff --git a/src/app/query/containers/query-container.component.html b/src/app/query/containers/query-container.component.html index 66db4e83..a9cf7b62 100644 --- a/src/app/query/containers/query-container.component.html +++ b/src/app/query/containers/query-container.component.html @@ -1,5 +1,4 @@ -
+
diff --git a/src/app/results/abstract-results-view.component.ts b/src/app/results/abstract-results-view.component.ts index eefb711e..193e8427 100644 --- a/src/app/results/abstract-results-view.component.ts +++ b/src/app/results/abstract-results-view.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectorRef, OnDestroy, OnInit, Directive} from '@angular/core'; +import {ChangeDetectorRef, Directive, OnDestroy, OnInit} from '@angular/core'; import {ResultsContainer} from '../shared/model/results/scores/results-container.model'; import {QueryChange, QueryService} from '../core/queries/query.service'; import {MediaSegmentScoreContainer} from '../shared/model/results/scores/segment-score-container.model'; @@ -46,7 +46,7 @@ export abstract class AbstractResultsViewComponent implements OnInit, OnDestr public static staticBackgroundForScore(score: number, segment: MediaSegmentScoreContainer, tags: Tag[], temporalObject?: TemporalObjectSegments): string { const _score = temporalObject === undefined ? score : temporalObject.score - if (tags.length === 0) { + if (tags == null || tags.length === 0) { const v = Math.round(255.0 - (_score * 255.0)); return ColorUtil.rgbToHex(v, 255, v); } else if (tags.length === 1) { @@ -95,6 +95,7 @@ export abstract class AbstractResultsViewComponent implements OnInit, OnDestr const tags: Tag[] = this._selectionService.getTags(segment.segmentId); return AbstractResultsViewComponent.staticBackgroundForScore(score, segment, tags, temporalObject) } + /** * Lifecycle Hook (onInit): Subscribes to the QueryService and the SelectionService */ diff --git a/src/app/results/abstract-segment-results-view.component.ts b/src/app/results/abstract-segment-results-view.component.ts index 818a5eb0..8b303327 100644 --- a/src/app/results/abstract-segment-results-view.component.ts +++ b/src/app/results/abstract-segment-results-view.component.ts @@ -11,7 +11,7 @@ import {Router} from '@angular/router'; import {MatSnackBar} from '@angular/material/snack-bar'; import {ResolverService} from '../core/basics/resolver.service'; import {MatDialog} from '@angular/material/dialog'; -import {VbsSubmissionService} from '../core/vbs/vbs-submission.service'; +import {VbsSubmissionService} from '../core/competition/vbs-submission.service'; import {AppConfig} from '../app.config'; /** diff --git a/src/app/results/gallery/gallery.component.html b/src/app/results/gallery/gallery.component.html index ba6f24d4..16d3dfc4 100644 --- a/src/app/results/gallery/gallery.component.html +++ b/src/app/results/gallery/gallery.component.html @@ -25,8 +25,7 @@ *ngFor="let tag of _selectionService._available" mat-icon-button matTooltip="Toggle '{{tag.name}}' tag"> - + album diff --git a/src/app/results/gallery/gallery.module.ts b/src/app/results/gallery/gallery.module.ts index d5bd4e07..fa0cb365 100644 --- a/src/app/results/gallery/gallery.module.ts +++ b/src/app/results/gallery/gallery.module.ts @@ -7,13 +7,13 @@ import {MaterialModule} from '../../material.module'; import {FlexLayoutModule} from '@angular/flex-layout'; import {MiniGalleryComponent} from './mini-gallery.component'; import {PipesModule} from '../../shared/pipes/pipes.module'; -import {VbsModule} from '../../core/vbs/vbs.module'; +import {CompetitionModule} from '../../core/competition/competition.module'; import {InfiniteScrollModule} from 'ngx-infinite-scroll'; import {ResultSegmentPreviewTileModule} from '../result-segment-preview-tile/result-segment-preview-tile.module'; import {VgCoreModule} from '@videogular/ngx-videogular/core'; @NgModule({ - imports: [MaterialModule, BrowserModule, FormsModule, AppRoutingModule, FlexLayoutModule, PipesModule, InfiniteScrollModule, VbsModule, VgCoreModule, ResultSegmentPreviewTileModule], + imports: [MaterialModule, BrowserModule, FormsModule, AppRoutingModule, FlexLayoutModule, PipesModule, InfiniteScrollModule, CompetitionModule, VgCoreModule, ResultSegmentPreviewTileModule], declarations: [GalleryComponent, MiniGalleryComponent], exports: [GalleryComponent, MiniGalleryComponent] }) diff --git a/src/app/results/list/list.module.ts b/src/app/results/list/list.module.ts index cb3ea9c7..594fdc18 100644 --- a/src/app/results/list/list.module.ts +++ b/src/app/results/list/list.module.ts @@ -6,13 +6,13 @@ import {MaterialModule} from '../../material.module'; import {FlexLayoutModule} from '@angular/flex-layout'; import {ListComponent} from './list.component'; import {PipesModule} from '../../shared/pipes/pipes.module'; -import {VbsModule} from '../../core/vbs/vbs.module'; +import {CompetitionModule} from '../../core/competition/competition.module'; import {InfiniteScrollModule} from 'ngx-infinite-scroll'; import {ResultSegmentPreviewTileModule} from '../result-segment-preview-tile/result-segment-preview-tile.module'; import {VgCoreModule} from '@videogular/ngx-videogular/core'; @NgModule({ - imports: [MaterialModule, BrowserModule, FormsModule, AppRoutingModule, FlexLayoutModule, PipesModule, VbsModule, InfiniteScrollModule, VgCoreModule, ResultSegmentPreviewTileModule], + imports: [MaterialModule, BrowserModule, FormsModule, AppRoutingModule, FlexLayoutModule, PipesModule, CompetitionModule, InfiniteScrollModule, VgCoreModule, ResultSegmentPreviewTileModule], declarations: [ListComponent], exports: [ListComponent] }) diff --git a/src/app/results/result-segment-preview-tile/result-segment-preview-tile.component.html b/src/app/results/result-segment-preview-tile/result-segment-preview-tile.component.html index eff9f108..f4bdc866 100644 --- a/src/app/results/result-segment-preview-tile/result-segment-preview-tile.component.html +++ b/src/app/results/result-segment-preview-tile/result-segment-preview-tile.component.html @@ -1,9 +1,8 @@ -
- @@ -11,15 +10,14 @@