Merge branch 'develop'
This commit is contained in:
commit
b5c9fe289c
36
README.md
36
README.md
|
|
@ -94,6 +94,21 @@ Preferences -> Tools -> Actions on Save
|
|||
* Run eslint --fix
|
||||
* Run prettier
|
||||
|
||||
## Translations
|
||||
|
||||
We use (vue-i18n)[https://kazupon.github.io/vue-i18n/] for translations
|
||||
and (vue-i18n-extract)[https://github.com/Spittal/vue-i18n-extract] for helper
|
||||
scripts.
|
||||
|
||||
```
|
||||
# will create a report on command line with missing translations
|
||||
npm run vue-i18n-extract
|
||||
|
||||
# add missing translations to files, see docs for more options
|
||||
cd client
|
||||
npx vue-i18n-extract --add
|
||||
```
|
||||
|
||||
## Deployment to CapRover
|
||||
|
||||
### CapRover Dev (vbv-lernwelt.control.iterativ.ch)
|
||||
|
|
@ -131,3 +146,24 @@ Preferences -> Tools -> Actions on Save
|
|||

|
||||
|
||||
#### Install the tailwind css Plugin from Jetbrains
|
||||
|
||||
## currents.dev
|
||||
|
||||
This project uses [currents.dev](https://currents.dev) to run the Cypress tests concurrently.
|
||||
The following steps were taken to set it up:
|
||||
|
||||
- Create a new project on currents.dev
|
||||
- Add the generated `projectId` to the cypress configuration file
|
||||
- Install `@currents/cli` as a dev dependency
|
||||
- Add the following script to the `package.json` file:
|
||||
```json
|
||||
"cypress:ci": "currents run --parallel --record --key $CURRENTS_KEY",
|
||||
```
|
||||
- Create a new Bitbucket pipelines job that exports the `CURRENTS_KEY` and runs the `cypress:ci` script
|
||||
- Refactor the pipeline steps so that the dependencies are installed first and then the other steps are run in
|
||||
parallel.
|
||||
You can then run multiple instances of the previously created job in parallel.
|
||||
See `.bitbucket-pipelines.yml` for an example.
|
||||
|
||||
> 💡 The number of cypress worker jobs depends on the number of cypress tests.
|
||||
> Too many workers for too few tests will result in a lot of idle workers.
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
dist
|
||||
node_modules
|
||||
**/__tests__/*.json
|
||||
src/colors.json
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
{
|
||||
"htmlWhitespaceSensitivity": "ignore",
|
||||
"jsonRecursiveSort": true,
|
||||
"organizeImportsSkipDestructiveCodeActions": true,
|
||||
"printWidth": 88,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"printWidth": 88,
|
||||
"organizeImportsSkipDestructiveCodeActions": true,
|
||||
"htmlWhitespaceSensitivity": "ignore"
|
||||
"tabWidth": 2
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
"pinia": "^2.0.21",
|
||||
"vue": "^3.2.38",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-i18n-extract": "^2.0.7",
|
||||
"vue-router": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -51,6 +52,7 @@
|
|||
"postcss-import": "^14.1.0",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier-plugin-organize-imports": "^3.1.1",
|
||||
"prettier-plugin-sort-json": "^1.0.0",
|
||||
"prettier-plugin-tailwindcss": "^0.2.1",
|
||||
"replace-in-file": "^6.3.5",
|
||||
"sass": "^1.54.6",
|
||||
|
|
@ -3345,6 +3347,12 @@
|
|||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/prettier": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
|
||||
"integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
|
|
@ -4225,8 +4233,7 @@
|
|||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
},
|
||||
"node_modules/aria-query": {
|
||||
"version": "5.1.3",
|
||||
|
|
@ -4409,8 +4416,7 @@
|
|||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
|
|
@ -4467,7 +4473,6 @@
|
|||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
|
|
@ -4569,6 +4574,14 @@
|
|||
"node": ">=10.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cac": {
|
||||
"version": "6.7.14",
|
||||
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
||||
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||
|
|
@ -4942,8 +4955,7 @@
|
|||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/constant-case": {
|
||||
"version": "3.0.4",
|
||||
|
|
@ -5725,6 +5737,26 @@
|
|||
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dot-object": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/dot-object/-/dot-object-2.1.4.tgz",
|
||||
"integrity": "sha512-7FXnyyCLFawNYJ+NhkqyP9Wd2yzuo+7n9pGiYpkmXCTYa8Ci2U0eUNDVg5OuO5Pm6aFXI2SWN8/N/w7SJWu1WA==",
|
||||
"dependencies": {
|
||||
"commander": "^4.0.0",
|
||||
"glob": "^7.1.5"
|
||||
},
|
||||
"bin": {
|
||||
"dot-object": "bin/dot-object"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-object/node_modules/commander": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
|
||||
|
|
@ -6953,8 +6985,7 @@
|
|||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
|
|
@ -7046,7 +7077,6 @@
|
|||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
|
|
@ -7084,7 +7114,6 @@
|
|||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -7094,7 +7123,6 @@
|
|||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
|
|
@ -7552,7 +7580,6 @@
|
|||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
|
|
@ -7561,8 +7588,7 @@
|
|||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/inquirer": {
|
||||
"version": "8.2.5",
|
||||
|
|
@ -7946,6 +7972,14 @@
|
|||
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-valid-glob": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz",
|
||||
"integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-weakmap": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
|
||||
|
|
@ -8062,7 +8096,6 @@
|
|||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
|
|
@ -8675,7 +8708,6 @@
|
|||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
|
||||
"integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
|
|
@ -8965,7 +8997,6 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -9205,7 +9236,6 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -9522,6 +9552,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-sort-json": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-sort-json/-/prettier-plugin-sort-json-1.0.0.tgz",
|
||||
"integrity": "sha512-XgcaF/Sojax1vD6j53wNIByx0rp7ecang+A8W0eM+Ks3yBFu/qXjJNvUtC1lEWeYbNfmRs/d8FyYJCYozAVENw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/prettier": "^2.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prettier": "^2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-tailwindcss": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.1.tgz",
|
||||
|
|
@ -11125,6 +11170,39 @@
|
|||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-i18n-extract": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-i18n-extract/-/vue-i18n-extract-2.0.7.tgz",
|
||||
"integrity": "sha512-i1NW5R58S720iQ1BEk+6ILo3hT6UA8mtYNNolSH4rt9345qvXdvA6GHy2+jHozdDAKHwlu9VvS/+vIMKs1UYQw==",
|
||||
"dependencies": {
|
||||
"cac": "^6.7.12",
|
||||
"dot-object": "^2.1.4",
|
||||
"glob": "^8.0.1",
|
||||
"is-valid-glob": "^1.0.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"vue-i18n-extract": "bin/vue-i18n-extract.js"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-i18n-extract/node_modules/glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-router": {
|
||||
"version": "4.1.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz",
|
||||
|
|
@ -11460,8 +11538,7 @@
|
|||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.11.0",
|
||||
|
|
@ -14317,6 +14394,12 @@
|
|||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prettier": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
|
||||
"integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/semver": {
|
||||
"version": "7.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
|
||||
|
|
@ -15009,8 +15092,7 @@
|
|||
"argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
},
|
||||
"aria-query": {
|
||||
"version": "5.1.3",
|
||||
|
|
@ -15149,8 +15231,7 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.5.1",
|
||||
|
|
@ -15190,7 +15271,6 @@
|
|||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
|
|
@ -15256,6 +15336,11 @@
|
|||
"streamsearch": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"cac": {
|
||||
"version": "6.7.14",
|
||||
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
|
||||
"integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="
|
||||
},
|
||||
"call-bind": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||
|
|
@ -15544,8 +15629,7 @@
|
|||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"constant-case": {
|
||||
"version": "3.0.4",
|
||||
|
|
@ -16143,6 +16227,22 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"dot-object": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/dot-object/-/dot-object-2.1.4.tgz",
|
||||
"integrity": "sha512-7FXnyyCLFawNYJ+NhkqyP9Wd2yzuo+7n9pGiYpkmXCTYa8Ci2U0eUNDVg5OuO5Pm6aFXI2SWN8/N/w7SJWu1WA==",
|
||||
"requires": {
|
||||
"commander": "^4.0.0",
|
||||
"glob": "^7.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "16.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
|
||||
|
|
@ -16977,8 +17077,7 @@
|
|||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
|
|
@ -17042,7 +17141,6 @@
|
|||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
|
|
@ -17056,7 +17154,6 @@
|
|||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -17066,7 +17163,6 @@
|
|||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
|
@ -17416,7 +17512,6 @@
|
|||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
|
|
@ -17425,8 +17520,7 @@
|
|||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "8.2.5",
|
||||
|
|
@ -17703,6 +17797,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"is-valid-glob": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz",
|
||||
"integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA=="
|
||||
},
|
||||
"is-weakmap": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
|
||||
|
|
@ -17801,7 +17900,6 @@
|
|||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^2.0.1"
|
||||
}
|
||||
|
|
@ -18274,7 +18372,6 @@
|
|||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
|
||||
"integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
}
|
||||
|
|
@ -18490,7 +18587,6 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -18678,8 +18774,7 @@
|
|||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
|
|
@ -18847,6 +18942,15 @@
|
|||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"prettier-plugin-sort-json": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-sort-json/-/prettier-plugin-sort-json-1.0.0.tgz",
|
||||
"integrity": "sha512-XgcaF/Sojax1vD6j53wNIByx0rp7ecang+A8W0eM+Ks3yBFu/qXjJNvUtC1lEWeYbNfmRs/d8FyYJCYozAVENw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/prettier": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"prettier-plugin-tailwindcss": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.1.tgz",
|
||||
|
|
@ -19980,6 +20084,32 @@
|
|||
"@vue/devtools-api": "^6.2.1"
|
||||
}
|
||||
},
|
||||
"vue-i18n-extract": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-i18n-extract/-/vue-i18n-extract-2.0.7.tgz",
|
||||
"integrity": "sha512-i1NW5R58S720iQ1BEk+6ILo3hT6UA8mtYNNolSH4rt9345qvXdvA6GHy2+jHozdDAKHwlu9VvS/+vIMKs1UYQw==",
|
||||
"requires": {
|
||||
"cac": "^6.7.12",
|
||||
"dot-object": "^2.1.4",
|
||||
"glob": "^8.0.1",
|
||||
"is-valid-glob": "^1.0.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "4.1.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz",
|
||||
|
|
@ -20233,8 +20363,7 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.11.0",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
"coverage": "vitest run --coverage",
|
||||
"typecheck": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"vue-i18n-extract": "vue-i18n-extract report",
|
||||
"prettier": "prettier . --write",
|
||||
"prettier:check": "prettier . --check",
|
||||
"tailwind": "tailwindcss -i tailwind.css -o ../server/vbv_lernwelt/static/css/tailwind.css --watch"
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
"pinia": "^2.0.21",
|
||||
"vue": "^3.2.38",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-i18n-extract": "^2.0.7",
|
||||
"vue-router": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -58,6 +60,7 @@
|
|||
"postcss-import": "^14.1.0",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier-plugin-organize-imports": "^3.1.1",
|
||||
"prettier-plugin-sort-json": "^1.0.0",
|
||||
"prettier-plugin-tailwindcss": "^0.2.1",
|
||||
"replace-in-file": "^6.3.5",
|
||||
"sass": "^1.54.6",
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import type { availableLanguages } from "@/stores/user";
|
||||
import { SUPPORT_LOCALES } from "@/i18n";
|
||||
import type { AvailableLanguages } from "@/stores/user";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/vue";
|
||||
import * as log from "loglevel";
|
||||
|
||||
log.debug("AppFooter created");
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
async function changeLocale(event: Event) {
|
||||
const target = event.target as HTMLSelectElement;
|
||||
userStore.setUserLanguages(target.value as availableLanguages);
|
||||
async function changeLocale(language: AvailableLanguages) {
|
||||
userStore.setUserLanguages(language);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -21,19 +22,27 @@ async function changeLocale(event: Event) {
|
|||
<div class="lg:ml-8">{{ $t("footer.imprint") }}</div>
|
||||
<div class="flex-grow"></div>
|
||||
<div>VBV_VERSION_BUILD_NUMBER_VBV</div>
|
||||
<div class="lg:ml-8">Deutsch</div>
|
||||
<!--div class="locale-changer">
|
||||
<select @change="changeLocale($event)">
|
||||
<option
|
||||
v-for="locale in ['de', 'fr']"
|
||||
:key="`locale-${locale}`"
|
||||
:value="locale"
|
||||
:selected="locale === userStore.language"
|
||||
<Menu>
|
||||
<MenuButton class="lg:ml-8" data-cy="language-switch-button">
|
||||
<it-icon-globe class="relative top-[2px] h-4 w-4" />
|
||||
<span class="ml-2 inline">{{ $t(`language.${userStore.language}`) }}</span>
|
||||
</MenuButton>
|
||||
<div class="relative">
|
||||
<MenuItems
|
||||
class="lg:right- absolute -top-24 -right-2/3 w-40 bg-white px-4 py-4 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
|
||||
>
|
||||
{{ locale }}
|
||||
</option>
|
||||
</select>
|
||||
</div -->
|
||||
<MenuItem v-for="locale in SUPPORT_LOCALES" :key="locale" class="py-1">
|
||||
<button
|
||||
class=""
|
||||
@click="changeLocale(locale)"
|
||||
:data-cy="`language-selector-${locale}`"
|
||||
>
|
||||
<span class="ml-2 inline">{{ $t(`language.${locale}`) }}</span>
|
||||
</button>
|
||||
</MenuItem>
|
||||
</MenuItems>
|
||||
</div>
|
||||
</Menu>
|
||||
<div class="lg:ml-8">{{ $t("footer.contact") }}</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<p class="mb-4 font-bold">Nächste Termine</p>
|
||||
<ul>
|
||||
<li class="border-b border-t py-3">
|
||||
<p class="pr-12">24. November 2022, 11 Uhr - Austausch mit Trainer</p>
|
||||
</li>
|
||||
<li class="border-b py-3">
|
||||
<p class="pr-12">4. Dezember 2022, 10.30 Uhr - Vernetzen - Live Session</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="pt-2 underline">Alle Termine anzeigen</p>
|
||||
</template>
|
||||
|
|
@ -51,9 +51,17 @@ const pieData = computed(() => {
|
|||
.reverse() as CircleSector[];
|
||||
});
|
||||
|
||||
const width = 450;
|
||||
const height = 450;
|
||||
const radius = Math.min(width, height) / 2.4;
|
||||
const width = 100;
|
||||
const height = 100;
|
||||
const radius = 50;
|
||||
|
||||
const svgId = computed(() => {
|
||||
// Generate a random id for the svg element like 'circle-visualization-ziurxxmp'
|
||||
return `circle-visualization-${Math.random()
|
||||
.toString(36)
|
||||
.replace(/[^a-z]+/g, "")
|
||||
.substring(2, 10)}`;
|
||||
});
|
||||
|
||||
function getColor(sector: CircleSector) {
|
||||
let color = colors.gray[300];
|
||||
|
|
@ -67,7 +75,7 @@ function getColor(sector: CircleSector) {
|
|||
}
|
||||
|
||||
function render() {
|
||||
const svg = d3.select(".circle-visualization");
|
||||
const svg = d3.select("#" + svgId.value);
|
||||
// Clean svg before adding new stuff.
|
||||
svg.selectAll("*").remove();
|
||||
|
||||
|
|
@ -124,10 +132,10 @@ function render() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="svg-container h-full content-center">
|
||||
<div class="svg-container content-center">
|
||||
<pre hidden>{{ pieData }}</pre>
|
||||
<pre hidden>{{ render() }}</pre>
|
||||
<svg class="circle-visualization h-full">
|
||||
<svg :id="svgId" class="h-full">
|
||||
<circle :cx="width / 2" :cy="height / 2" :r="radius" :color="colors.gray[300]" />
|
||||
<circle :cx="width / 2" :cy="height / 2" :r="radius / 2.5" color="white" />
|
||||
</svg>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<script setup lang="ts">
|
||||
import type { CircleSectorData } from "@/components/learningPath/page/LearningPathCircle.vue";
|
||||
import LearningPathCircle from "@/components/learningPath/page/LearningPathCircle.vue";
|
||||
import LearningPathContinueButton from "@/components/learningPath/page/LearningPathContinueButton.vue";
|
||||
import { calculateCircleSectorData } from "@/components/learningPath/page/utils";
|
||||
import type { Circle } from "@/services/circle";
|
||||
import type { LearningPath } from "@/services/learningPath";
|
||||
import type { Topic } from "@/types";
|
||||
|
||||
const props = defineProps<{
|
||||
learningPath: LearningPath | undefined;
|
||||
circle: Circle;
|
||||
topic: Topic;
|
||||
isFirstCircle: boolean;
|
||||
isLastCircle: boolean;
|
||||
isCurrentCircle: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-row items-center pb-2">
|
||||
<div class="w-12">
|
||||
<hr v-if="!props.isFirstCircle" class="h-[1.6px] w-full border-0 bg-gray-500" />
|
||||
</div>
|
||||
<LearningPathCircle
|
||||
:sectors="calculateCircleSectorData(circle)"
|
||||
class="h-24 w-24 snap-center"
|
||||
></LearningPathCircle>
|
||||
<div class="w-12">
|
||||
<hr v-if="!props.isLastCircle" class="h-[1.6px] w-full border-0 bg-gray-500" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span v-if="props.isCurrentCircle" class="text-sm text-gray-800">
|
||||
{{ $t("learningPathPage.currentCircle") }}
|
||||
</span>
|
||||
|
||||
<div class="w-36 text-center text-lg font-bold text-blue-900">
|
||||
{{ props.circle.title }}
|
||||
</div>
|
||||
|
||||
<div v-if="props.isCurrentCircle" class="whitespace-nowrap">
|
||||
<LearningPathContinueButton
|
||||
:has-progress="!props.learningPath?.continueData?.has_no_progress"
|
||||
:url="props.learningPath?.continueData?.url"
|
||||
></LearningPathContinueButton>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<script setup lang="ts">
|
||||
interface Props {
|
||||
hasProgress: boolean;
|
||||
url: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
hasProgress: false,
|
||||
url: "",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-link
|
||||
class="btn-blue mt-2 pl-6"
|
||||
:to="props.url"
|
||||
data-cy="lp-continue-button"
|
||||
translate
|
||||
>
|
||||
<span>
|
||||
{{ props.hasProgress ? $t("general.nextStep") : $t("general.start") }}
|
||||
</span>
|
||||
</router-link>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<script setup lang="ts">
|
||||
import type { CircleSectorData } from "@/components/learningPath/page/LearningPathCircle.vue";
|
||||
import LearningPathCircle from "@/components/learningPath/page/LearningPathCircle.vue";
|
||||
import LearningPathContinueButton from "@/components/learningPath/page/LearningPathContinueButton.vue";
|
||||
import { calculateCircleSectorData } from "@/components/learningPath/page/utils";
|
||||
import type { Circle } from "@/services/circle";
|
||||
import type { LearningPath } from "@/services/learningPath";
|
||||
import { computed, onMounted } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
learningPath: LearningPath | undefined;
|
||||
}>();
|
||||
|
||||
onMounted(() => {
|
||||
const initialCircle = props.learningPath?.nextLearningContent?.parentCircle;
|
||||
if (initialCircle) {
|
||||
scrollToCircle(initialCircle);
|
||||
}
|
||||
});
|
||||
|
||||
const topics = computed(() => props.learningPath?.topics ?? []);
|
||||
|
||||
const shouldContinueHere = (circle: Circle) =>
|
||||
props.learningPath?.nextLearningContent?.parentCircle === circle;
|
||||
|
||||
const scrollToCircle = (circle: Circle) => {
|
||||
const id = `circle-${circle.slug}`;
|
||||
const el = document.getElementById(id);
|
||||
el?.scrollIntoView({ behavior: "smooth", inline: "center", block: "end" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-for="topic in topics" :key="topic.title">
|
||||
<div class="pb-2 font-bold text-gray-700">
|
||||
{{ topic.title }}
|
||||
</div>
|
||||
<router-link
|
||||
v-for="circle in topic.circles"
|
||||
:id="`circle-${circle.slug}`"
|
||||
:key="circle.id"
|
||||
:to="circle.frontend_url"
|
||||
class="flex flex-row items-center pb-2"
|
||||
>
|
||||
<LearningPathCircle
|
||||
:sectors="calculateCircleSectorData(circle)"
|
||||
class="h-12 w-12"
|
||||
></LearningPathCircle>
|
||||
<div class="pl-3 font-bold text-blue-900">
|
||||
{{ circle.title }}
|
||||
</div>
|
||||
|
||||
<div v-if="shouldContinueHere(circle)" class="whitespace-nowrap pl-4">
|
||||
<LearningPathContinueButton
|
||||
:has-progress="!props.learningPath?.continueData?.has_no_progress"
|
||||
:url="props.learningPath?.continueData?.url"
|
||||
></LearningPathContinueButton>
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
<script setup lang="ts">
|
||||
import type { CircleSectorData } from "@/components/learningPath/page/LearningPathCircle.vue";
|
||||
import LearningPathCircleColumn from "@/components/learningPath/page/LearningPathCircleColumn.vue";
|
||||
import LearningPathScrollButton from "@/components/learningPath/page/LearningPathScrollButton.vue";
|
||||
import type { Circle } from "@/services/circle";
|
||||
import type { LearningPath } from "@/services/learningPath";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
learningPath: LearningPath | undefined;
|
||||
useMobileLayout: boolean;
|
||||
}>();
|
||||
|
||||
// Scroll bounds
|
||||
const isAtLeftEnd = ref(true);
|
||||
const isAtRightEnd = ref(false);
|
||||
|
||||
// Constants
|
||||
const scrollIncrement = 600;
|
||||
const learnPathDiagramId = "learnpath-diagram";
|
||||
|
||||
onMounted(async () => {
|
||||
watchScrollBounds();
|
||||
|
||||
const initialCircle = props.learningPath?.nextLearningContent?.parentCircle;
|
||||
if (initialCircle) {
|
||||
scrollToCircle(initialCircle);
|
||||
}
|
||||
});
|
||||
|
||||
const isFirstCircle = (topicIndex: number, circleIndex: number) =>
|
||||
topicIndex === 0 && circleIndex === 0;
|
||||
|
||||
const isLastCircle = (topicIndex: number, circleIndex: number, numCircles: number) =>
|
||||
topicIndex === (props.learningPath?.topics ?? []).length - 1 &&
|
||||
circleIndex === numCircles - 1;
|
||||
|
||||
const isCurrentCircle = (circle: Circle) =>
|
||||
props.learningPath?.nextLearningContent?.parentCircle === circle;
|
||||
|
||||
const watchScrollBounds = () => {
|
||||
// We need to monitor the scroll bounds of the diagram to hide the scroll buttons when we're at the end
|
||||
const el = document.getElementById(learnPathDiagramId);
|
||||
el?.addEventListener("scroll", () => recalculateScrollBounds());
|
||||
};
|
||||
|
||||
const recalculateScrollBounds = () => {
|
||||
const el = document.getElementById(learnPathDiagramId);
|
||||
const scrollLeft = el?.scrollLeft ?? 0;
|
||||
const scrollWidth = el?.scrollWidth ?? 0;
|
||||
isAtLeftEnd.value = scrollLeft === 0;
|
||||
isAtRightEnd.value = scrollLeft > scrollWidth - (el?.clientWidth ?? 0) - 1;
|
||||
};
|
||||
|
||||
const scrollRight = () => scrollLearnPathDiagram(scrollIncrement);
|
||||
|
||||
const scrollLeft = () => scrollLearnPathDiagram(-scrollIncrement);
|
||||
|
||||
const scrollLearnPathDiagram = (offset: number) => {
|
||||
const el = document.getElementById(learnPathDiagramId);
|
||||
const newScrollOffset = (el?.scrollLeft ?? 0) + offset;
|
||||
el?.scroll({
|
||||
left: newScrollOffset,
|
||||
top: 0,
|
||||
behavior: "smooth",
|
||||
});
|
||||
};
|
||||
|
||||
const scrollToCircle = (circle: Circle) => {
|
||||
const id = `circle-${circle.slug}`;
|
||||
const el = document.getElementById(id);
|
||||
el?.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative flex flex-row items-center">
|
||||
<LearningPathScrollButton
|
||||
v-show="!isAtLeftEnd"
|
||||
direction="left"
|
||||
:hidden="props.useMobileLayout"
|
||||
@click="scrollLeft"
|
||||
></LearningPathScrollButton>
|
||||
<div
|
||||
:id="learnPathDiagramId"
|
||||
class="flex h-96 snap-x flex-row overflow-auto py-5 sm:overflow-hidden sm:py-10"
|
||||
>
|
||||
<div
|
||||
v-for="(topic, topicIndex) in props.learningPath?.topics ?? []"
|
||||
:key="topic.title"
|
||||
class="border-l border-gray-500"
|
||||
:class="topicIndex == 0 ? 'ml-6 sm:ml-12' : ''"
|
||||
>
|
||||
<p
|
||||
:id="`topic-${topic.slug}`"
|
||||
class="inline-block h-12 self-start px-4 font-bold text-gray-800"
|
||||
>
|
||||
{{ topic.title }}
|
||||
</p>
|
||||
<div class="flex flex-row pt-6">
|
||||
<router-link
|
||||
v-for="(circle, circleIndex) in topic.circles"
|
||||
:id="`circle-${circle.slug}`"
|
||||
:key="circle.id"
|
||||
:to="circle.frontend_url"
|
||||
:data-cy="`circle-${circle.title}`"
|
||||
class="flex flex-col items-center pb-6"
|
||||
>
|
||||
<LearningPathCircleColumn
|
||||
:learning-path="learningPath"
|
||||
:circle="circle"
|
||||
:topic="topic"
|
||||
:is-first-circle="isFirstCircle(topicIndex, circleIndex)"
|
||||
:is-last-circle="
|
||||
isLastCircle(topicIndex, circleIndex, topic.circles.length)
|
||||
"
|
||||
:is-current-circle="isCurrentCircle(circle)"
|
||||
></LearningPathCircleColumn>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<LearningPathScrollButton
|
||||
v-show="!isAtRightEnd"
|
||||
direction="right"
|
||||
:hidden="props.useMobileLayout"
|
||||
@click="scrollRight"
|
||||
></LearningPathScrollButton>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps<{ allCount: number; inProgressCount: number }>();
|
||||
|
||||
const progress = computed(() => {
|
||||
if (props.allCount === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (props.inProgressCount / props.allCount) * 100;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<span class="relative inline-block h-2 w-full bg-white">
|
||||
<div
|
||||
v-if="progress > 0"
|
||||
class="absolute h-full bg-green-500"
|
||||
:style="{ width: `${progress}%` }"
|
||||
></div>
|
||||
</span>
|
||||
<p>
|
||||
{{
|
||||
$t("learningPathPage.progressText", {
|
||||
inProgressCount: props.inProgressCount,
|
||||
allCount: props.allCount,
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<script setup lang="ts">
|
||||
export type Direction = "right" | "left";
|
||||
|
||||
const emit = defineEmits(["click"]);
|
||||
|
||||
const props = defineProps<{
|
||||
direction: Direction;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<transition
|
||||
leave-active-class="transition ease-out duration-600"
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0"
|
||||
enter-active-class="transition ease-in duration-600"
|
||||
enter-from-class="opacity-0"
|
||||
enter-to-class="opacity-100"
|
||||
>
|
||||
<button
|
||||
class="absolute h-full w-32 from-white"
|
||||
:class="
|
||||
props.direction === 'right'
|
||||
? 'right-0 bg-gradient-to-l'
|
||||
: 'left-0 bg-gradient-to-r'
|
||||
"
|
||||
@click="emit('click')"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col"
|
||||
:class="props.direction === 'right' ? 'items-end' : 'items-start'"
|
||||
>
|
||||
<component
|
||||
:is="`it-icon-arrow-${props.direction}`"
|
||||
class="mb-16 h-20 w-20 text-gray-600"
|
||||
></component>
|
||||
</div>
|
||||
</button>
|
||||
</transition>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<script setup lang="ts">
|
||||
import type { Topic } from "@/types";
|
||||
|
||||
const props = defineProps<{
|
||||
topics: Topic[];
|
||||
}>();
|
||||
|
||||
const scrollToTopic = (topic: Topic) => {
|
||||
const id = `topic-${topic.slug}`;
|
||||
const el = document.getElementById(id);
|
||||
el?.scrollIntoView({ behavior: "smooth", inline: "center", block: "nearest" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="text-sm text-gray-800">
|
||||
<span>{{ $t("learningPathPage.topics") }}</span>
|
||||
<button
|
||||
v-for="topic in props.topics"
|
||||
:key="topic.slug"
|
||||
class="pl-2 underline sm:pl-4"
|
||||
@click="scrollToTopic(topic)"
|
||||
>
|
||||
{{ topic.title }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<script setup lang="ts">
|
||||
import ItToggleSwitch from "@/components/ui/ItToggleSwitch.vue";
|
||||
import { computed, ref } from "vue";
|
||||
|
||||
export type ViewType = "path" | "list";
|
||||
|
||||
const props = defineProps<{
|
||||
initialView: ViewType;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "selectView", value: ViewType): void;
|
||||
}>();
|
||||
|
||||
const selectedView = ref<ViewType>(props.initialView);
|
||||
|
||||
const activeStyle = "text-black";
|
||||
const inactiveStyle = "text-gray-700";
|
||||
|
||||
const pathViewLabelStyle = computed(() =>
|
||||
selectedView.value == "path" ? activeStyle : inactiveStyle
|
||||
);
|
||||
|
||||
const listViewLabelStyle = computed(() =>
|
||||
selectedView.value == "list" ? activeStyle : inactiveStyle
|
||||
);
|
||||
|
||||
const onToggle = () => {
|
||||
if (selectedView.value == "path") {
|
||||
selectedView.value = "list";
|
||||
} else {
|
||||
selectedView.value = "path";
|
||||
}
|
||||
emit("selectView", selectedView.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-row items-center space-x-2 text-sm">
|
||||
<span :class="pathViewLabelStyle">
|
||||
{{ $t("learningPathPage.pathView") }}
|
||||
</span>
|
||||
<ItToggleSwitch
|
||||
data-cy="view-switch"
|
||||
:initially-switched-left="selectedView == 'list'"
|
||||
@click="onToggle"
|
||||
></ItToggleSwitch>
|
||||
<span :class="listViewLabelStyle">
|
||||
{{ $t("learningPathPage.listView") }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import type {
|
||||
CircleSectorData,
|
||||
CircleSectorProgress,
|
||||
} from "@/components/learningPath/page/LearningPathCircle.vue";
|
||||
import type { Circle } from "@/services/circle";
|
||||
|
||||
export function calculateCircleSectorData(circle: Circle): CircleSectorData[] {
|
||||
const sectors = circle.learningSequences.map((ls) => {
|
||||
let progress: CircleSectorProgress = "none";
|
||||
if (circle.allFinishedInLearningSequence(ls.translation_key)) {
|
||||
progress = "finished";
|
||||
} else if (circle.someFinishedInLearningSequence(ls.translation_key)) {
|
||||
progress = "in_progress";
|
||||
}
|
||||
return {
|
||||
progress: progress,
|
||||
};
|
||||
});
|
||||
return sectors;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<script setup lang="ts">
|
||||
import { Switch } from "@headlessui/vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
interface Props {
|
||||
initiallySwitchedLeft: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
initiallySwitchedLeft: false,
|
||||
});
|
||||
|
||||
const isSwitchedLeft = ref(props.initiallySwitchedLeft);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Switch
|
||||
v-model="isSwitchedLeft"
|
||||
class="relative inline-flex h-5 w-11 min-w-[44px] items-center rounded-full bg-gray-200"
|
||||
>
|
||||
<span
|
||||
:class="isSwitchedLeft ? 'translate-x-6' : 'translate-x-0'"
|
||||
class="inline-block h-5 w-5 transform rounded-full bg-black transition"
|
||||
/>
|
||||
</Switch>
|
||||
</template>
|
||||
|
|
@ -29,6 +29,7 @@ export const itPost = (url: RequestInfo, data: unknown, options: RequestInit = {
|
|||
},
|
||||
options?.headers
|
||||
) as HeadersInit;
|
||||
options.headers = headers;
|
||||
|
||||
options = Object.assign(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import type { AvailableLanguages } from "@/stores/user";
|
||||
import dayjs from "dayjs";
|
||||
import { nextTick } from "vue";
|
||||
import { createI18n } from "vue-i18n";
|
||||
|
||||
// https://vue-i18n.intlify.dev/guide/advanced/lazy.html
|
||||
export const SUPPORT_LOCALES = ["de", "fr", "it"];
|
||||
export const SUPPORT_LOCALES: AvailableLanguages[] = ["de", "fr"];
|
||||
let i18n: any = null;
|
||||
|
||||
export function setupI18n(
|
||||
|
|
|
|||
|
|
@ -1,170 +1,179 @@
|
|||
{
|
||||
"circlePage": {
|
||||
"circleContentBoxTitle": "Das lernst du in diesem Circle.",
|
||||
"contactExpertButton": "Fachexpertin kontaktieren",
|
||||
"contactExpertDescription": "Tausche dich mit der Fachexpertin für den Circle {circleName} aus.",
|
||||
"documents": {
|
||||
"action": "Unterlagen hochladen",
|
||||
"chooseLearningSequence": "Bitte wähle eine Lernsequenz aus",
|
||||
"chooseName": "Bitte wähle einen Namen",
|
||||
"chooseSequence": "Wähle eine Lernsequenz aus",
|
||||
"expertDescription": "Stelle deinen Lernenden zusätzliche Inhalte zur Verfügung.",
|
||||
"fileLabel": "Datei",
|
||||
"maxFileSize": "Maximale Dateigrösse: 20 MB",
|
||||
"modalAction": "Datei auswählen",
|
||||
"modalFileName": "Name",
|
||||
"modalNameInformation": "Max. 70 Zeichen",
|
||||
"selectFile": "Bitte wähle eine Datei aus",
|
||||
"title": "Unterlagen",
|
||||
"uploadErrorMessage": "Beim Hochladen ist ein Fehler aufgetreten. Bitte versuche es erneut.",
|
||||
"userDescription": "Hier findest du die Unterlagen, die dir die Fachexpertin zur Verfügung gestellt hat."
|
||||
},
|
||||
"duration": "Dauer",
|
||||
"gotQuestions": "Hast du Fragen?",
|
||||
"learnMore": "Erfahre mehr dazu"
|
||||
},
|
||||
"cockpit": {
|
||||
"examsDone": "Abgelegte Prüfungen von Teilnehmer.",
|
||||
"feedbacksDone": "Abgeschickte Feedbacks von Teilnehmer.",
|
||||
"notifyTask": "Benachrichtigen",
|
||||
"notifyTaskDescription": "Teilnehmer benachrichtigen",
|
||||
"profileLink": "Profil anzeigen",
|
||||
"progress": "Fortschritt",
|
||||
"tasksDone": "Erledigte Transferaufträge von Teilnehmer.",
|
||||
"title": "Cockpit"
|
||||
},
|
||||
"competences": {
|
||||
"assessAgain": "Sich nochmals einschätzen",
|
||||
"assessment": "Einschätzungen",
|
||||
"competences": "Kompetenzen",
|
||||
"lastImprovements": "Letzte verbesserte Kompetenzen",
|
||||
"notAssessed": "Nicht eingeschätzt",
|
||||
"title": "KompetenzNavi"
|
||||
},
|
||||
"constants": {
|
||||
"no": "Nein",
|
||||
"satisfied": "zufrieden",
|
||||
"unsatisfied": "unzufrieden",
|
||||
"verySatisfied": "sehr zufrieden",
|
||||
"veryUnsatisfied": "sehr unzufrieden",
|
||||
"yes": "Ja"
|
||||
},
|
||||
"dashboard": {
|
||||
"welcome": "Willkommen, {name}"
|
||||
},
|
||||
"feedback": {
|
||||
"answers": "Antworten",
|
||||
"areYouSatisfied": "Wie zufrieden bist du?",
|
||||
"average": "Durchschnitt",
|
||||
"circleFeedback": "Feedback zum Circle",
|
||||
"completionDescription": "Dein Feedback ist anonym. Dein Vor- und Nachname werden bei deiner Trainer/-in nicht angezeigt.",
|
||||
"completionTitle": "Schicke dein Feedback an {name}",
|
||||
"courseNegativeFeedbackLabel": "Wo sehen Sie Verbesserungspotenzial?",
|
||||
"coursePositiveFeedbackLabel": "Was hat Ihnen besonders gut gefallen?",
|
||||
"feedbackPageInfo": "Teilnehmer haben das Feedback ausgefüllt",
|
||||
"feedbackPageTitle": "Feedback zum Lehrgang",
|
||||
"feedbackSent": "Dein Feedback wurde abgeschickt",
|
||||
"goalAttainmentLabel": "Zielerreichung insgesamt",
|
||||
"happy": "Zufrieden",
|
||||
"instructorCompetenceLabel": "Der Kursleiter war themenstark, fachkompetent.",
|
||||
"instructorOpenFeedbackLabel": "Was ich dem Kursleiter sonst noch sagen wollte:",
|
||||
"instructorRespectLabel": "Fragen und Anregungen der Kursteilnehmenden wurden ernst genommen und aufgegriffen.",
|
||||
"intro": "{name}, dein/e Trainer/-in, bittet dich, ihm/ihr Feedback zu geben. Das ist freiwillig, würde aber ihm/ihr helfen, deine Lernerlebniss zu verbessern.",
|
||||
"materialsRatingLabel": "Falls ja: Wie beurteilen Sie die Vorbereitungsunterlagen (z.B. eLearning)?",
|
||||
"noFeedbacks": "Es wurden noch keine Feedbacks abgegeben",
|
||||
"proficiencyLabel": "Wie beurteilen Sie Ihre Sicherheit bezüglichen den Themen nach dem Kurs?",
|
||||
"questionTitle": "Frage",
|
||||
"receivedMaterialsLabel": "Haben Sie Vorbereitungsunterlagen (z.B. eLearning) erhalten?",
|
||||
"recommendLabel": "Würden Sie den Kurs weiterempfehlen?",
|
||||
"satisfactionLabel": "Zufriedenheit insgesamt",
|
||||
"sendFeedback": "Feedback abschicken",
|
||||
"sentByUsers": "Von {count} Teilnehmern ausgefüllt",
|
||||
"showDetails": "Details anzeigen",
|
||||
"unhappy": "Unzufrieden",
|
||||
"veryHappy": "Sehr zufrieden",
|
||||
"veryUnhappy": "Sehr unzufrieden"
|
||||
},
|
||||
"footer": {
|
||||
"contact": "Kontakt",
|
||||
"dataProtection": "Datenschutzbestimmungen",
|
||||
"faq": "FAQ",
|
||||
"imprint": "Impressum"
|
||||
},
|
||||
"general": {
|
||||
"nextStep": "Weiter geht's",
|
||||
"start": "Los geht's",
|
||||
"backToLearningPath": "zurück zum Lernpfad",
|
||||
"backToCircle": "zurück zum Circle",
|
||||
"next": "Weiter",
|
||||
"back": "zurück",
|
||||
"backCapitalized": "@.capitalize:general.back",
|
||||
"save": "Speichern",
|
||||
"send": "Senden",
|
||||
"learningUnit": "Lerneinheit",
|
||||
"learningPath": "Lernpfad",
|
||||
"learningSequence": "Lernsequenz",
|
||||
"show": "Anschauen",
|
||||
"backToCircle": "zurück zum Circle",
|
||||
"backToLearningPath": "zurück zum Lernpfad",
|
||||
"certificate": "Zertifikat | Zertifikate",
|
||||
"circles": "Circles",
|
||||
"transferTask": "Transferauftrag | Transferaufträge",
|
||||
"feedback": "Feedback | Feedbacks",
|
||||
"exam": "Prüfung | Prüfungen",
|
||||
"examResult": "Prüfungsresultat | Prüfungsresultate",
|
||||
"certificate": "Zertifikat | Zertifikate",
|
||||
"feedback": "Feedback | Feedbacks",
|
||||
"learningPath": "Lernpfad",
|
||||
"learningSequence": "Lernsequenz",
|
||||
"learningUnit": "Lerneinheit",
|
||||
"next": "Weiter",
|
||||
"nextStep": "Weiter geht's",
|
||||
"no": "Nein",
|
||||
"notification": "Benachrichtigung | Benachrichtigungen",
|
||||
"profileLink": "Profil anzeigen",
|
||||
"save": "Speichern",
|
||||
"send": "Senden",
|
||||
"settings": "Kontoeinstellungen",
|
||||
"shop": "Shop",
|
||||
"yes": "Ja",
|
||||
"no": "Nein",
|
||||
"show": "Anschauen",
|
||||
"showAll": "Alle anschauen",
|
||||
"settings": "Kontoeinstellungen"
|
||||
"start": "Los geht's",
|
||||
"transferTask": "Transferauftrag | Transferaufträge",
|
||||
"yes": "Ja"
|
||||
},
|
||||
"language": {
|
||||
"de": "Deutsch",
|
||||
"fr": "Französisch"
|
||||
},
|
||||
"learningContent": {
|
||||
"completeAndContinue": "Als erledigt markieren"
|
||||
},
|
||||
"learningPathPage": {
|
||||
"currentCircle": "Aktueller Circle",
|
||||
"listView": "Listenansicht",
|
||||
"nextStep": "Nächster Schritt",
|
||||
"pathView": "Pfadansicht",
|
||||
"progressText": "Du hast { inProgressCount } von { allCount } Circles bearbeitet",
|
||||
"showListView": "Listenansicht anzeigen",
|
||||
"topics": "Themen:",
|
||||
"welcomeBack": "Hallo { name }! Willkommen zurück in deinem Lehrgang:"
|
||||
},
|
||||
"mainNavigation": {
|
||||
"logout": "Abmelden",
|
||||
"profile": "Profil"
|
||||
},
|
||||
"dashboard": {
|
||||
"welcome": "Willkommen, {name}"
|
||||
},
|
||||
"learningPathPage": {
|
||||
"welcomeBack": "Willkommen zurück, {name}",
|
||||
"showListView": "Listenansicht anzeigen",
|
||||
"nextStep": "Nächster Schritt"
|
||||
},
|
||||
"circlePage": {
|
||||
"duration": "Dauer",
|
||||
"circleContentBoxTitle": "Das lernst du in diesem Circle.",
|
||||
"gotQuestions": "Hast du Fragen?",
|
||||
"contactExpertButton": "Fachexpertin kontaktieren",
|
||||
"contactExpertDescription": "Tausche dich mit der Fachexpertin für den Circle {circleName} aus.",
|
||||
"learnMore": "Erfahre mehr dazu",
|
||||
"documents": {
|
||||
"title": "Unterlagen",
|
||||
"expertDescription": "Stelle deinen Lernenden zusätzliche Inhalte zur Verfügung.",
|
||||
"userDescription": "Hier findest du die Unterlagen, die dir die Fachexpertin zur Verfügung gestellt hat.",
|
||||
"action": "Unterlagen hochladen",
|
||||
"modalAction": "Datei auswählen",
|
||||
"fileLabel": "Datei",
|
||||
"modalFileName": "Name",
|
||||
"modalNameInformation": "Max. 70 Zeichen",
|
||||
"chooseSequence": "Wähle eine Lernsequenz aus",
|
||||
"selectFile": "Bitte wähle eine Datei aus",
|
||||
"chooseName": "Bitte wähle einen Namen",
|
||||
"chooseLearningSequence": "Bitte wähle eine Lernsequenz aus",
|
||||
"uploadErrorMessage": "Beim Hochladen ist ein Fehler aufgetreten. Bitte versuche es erneut.",
|
||||
"maxFileSize": "Maximale Dateigrösse: 20 MB"
|
||||
}
|
||||
},
|
||||
"learningContent": {
|
||||
"completeAndContinue": "Als erledigt markieren"
|
||||
},
|
||||
"selfEvaluation": {
|
||||
"selfEvaluation": "Selbsteinschätzung",
|
||||
"title": "@:selfEvaluation.selfEvaluation {title}",
|
||||
"steps": "Schritt {current} von {max}",
|
||||
"instruction": [
|
||||
"Überprüfe, ob du in der Lernheinheit",
|
||||
"alles verstanden hast.",
|
||||
"Lies die folgende Aussage und bewerte sie:"
|
||||
],
|
||||
"yes": "Ja, ich kann das",
|
||||
"no": "Das muss ich nochmals anschauen",
|
||||
"progressText": "Schau dein Fortschritt in deinem KompetenzNavi:",
|
||||
"progressLink": "KompetenzNavi öffnen",
|
||||
"selfEvaluationYes": "@:selfEvaluation: Ich kann das.",
|
||||
"selfEvaluationNo": "@:selfEvaluation: Muss ich nochmals anschauen."
|
||||
},
|
||||
"competences": {
|
||||
"competences": "Kompetenzen",
|
||||
"title": "KompetenzNavi",
|
||||
"lastImprovements": "Letzte verbesserte Kompetenzen",
|
||||
"assessment": "Einschätzungen",
|
||||
"notAssessed": "Nicht eingeschätzt",
|
||||
"assessAgain": "Sich nochmals einschätzen"
|
||||
},
|
||||
"mediaLibrary": {
|
||||
"title": "Mediathek",
|
||||
"learningMedia": {
|
||||
"titel": "Lernmedien",
|
||||
"description": "Finde eine vollständige Liste der Bücher und anderen Medien, auf die im Kurs verwiesen wird."
|
||||
},
|
||||
"handlungsfelder": {
|
||||
"title": "Handlungsfeld | Handlungsfelder",
|
||||
"description": "Finde alle Ressourcen der Handlungsfelder wie Lernmedien, Links und andere nützliche Informationen."
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"dataProtection": "Datenschutzbestimmungen",
|
||||
"imprint": "Impressum",
|
||||
"contact": "Kontakt",
|
||||
"faq": "FAQ"
|
||||
},
|
||||
"cockpit": {
|
||||
"title": "Cockpit",
|
||||
"tasksDone": "Erledigte Transferaufträge von Teilnehmer.",
|
||||
"feedbacksDone": "Abgeschickte Feedbacks von Teilnehmer.",
|
||||
"examsDone": "Abgelegte Prüfungen von Teilnehmer.",
|
||||
"progress": "Fortschritt",
|
||||
"profileLink": "Profil anzeigen",
|
||||
"notifyTaskDescription": "Teilnehmer benachrichtigen",
|
||||
"notifyTask": "Benachrichtigen"
|
||||
"description": "Finde alle Ressourcen der Handlungsfelder wie Lernmedien, Links und andere nützliche Informationen.",
|
||||
"title": "Handlungsfeld | Handlungsfelder"
|
||||
},
|
||||
"learningMedia": {
|
||||
"description": "Finde eine vollständige Liste der Bücher und anderen Medien, auf die im Kurs verwiesen wird.",
|
||||
"titel": "Lernmedien"
|
||||
},
|
||||
"title": "Mediathek"
|
||||
},
|
||||
"messages": {
|
||||
"sendMessage": "Nachricht schreiben"
|
||||
},
|
||||
"feedback": {
|
||||
"intro": "{name}, dein/e Trainer/-in, bittet dich, ihm/ihr Feedback zu geben. Das ist freiwillig, würde aber ihm/ihr helfen, deine Lernerlebniss zu verbessern.",
|
||||
"areYouSatisfied": "Wie zufrieden bist du?",
|
||||
"recommendLabel": "Würden Sie den Kurs weiterempfehlen?",
|
||||
"satisfactionLabel": "Zufriedenheit insgesamt",
|
||||
"goalAttainmentLabel": "Zielerreichung insgesamt",
|
||||
"proficiencyLabel": "Wie beurteilen Sie Ihre Sicherheit bezüglichen den Themen nach dem Kurs?",
|
||||
"receivedMaterialsLabel": "Haben Sie Vorbereitungsunterlagen (z.B. eLearning) erhalten?",
|
||||
"materialsRatingLabel": "Falls ja: Wie beurteilen Sie die Vorbereitungsunterlagen (z.B. eLearning)?",
|
||||
"instructorCompetenceLabel": "Der Kursleiter war themenstark, fachkompetent.",
|
||||
"instructorRespectLabel": "Fragen und Anregungen der Kursteilnehmenden wurden ernst genommen und aufgegriffen.",
|
||||
"instructorOpenFeedbackLabel": "Was ich dem Kursleiter sonst noch sagen wollte:",
|
||||
"courseNegativeFeedbackLabel": "Wo sehen Sie Verbesserungspotenzial?",
|
||||
"coursePositiveFeedbackLabel": "Was hat Ihnen besonders gut gefallen?",
|
||||
"completionTitle": "Schicke dein Feedback an {name}",
|
||||
"completionDescription": "Dein Feedback ist anonym. Dein Vor- und Nachname werden bei deiner Trainer/-in nicht angezeigt.",
|
||||
"sendFeedback": "Feedback abschicken",
|
||||
"feedbackSent": "Dein Feedback wurde abgeschickt",
|
||||
"circleFeedback": "Feedback zum Circle",
|
||||
"showDetails": "Details anzeigen",
|
||||
"sentByUsers": "Von {count} Teilnehmern ausgefüllt",
|
||||
"feedbackPageTitle": "Feedback zum Lehrgang",
|
||||
"feedbackPageInfo": "Teilnehmer haben das Feedback ausgefüllt",
|
||||
"questionTitle": "Frage",
|
||||
"veryUnhappy": "Sehr unzufrieden",
|
||||
"unhappy": "Unzufrieden",
|
||||
"happy": "Zufrieden",
|
||||
"veryHappy": "Sehr zufrieden",
|
||||
"average": "Durchschnitt",
|
||||
"answers": "Antworten",
|
||||
"noFeedbacks": "Es wurden noch keine Feedbacks abgegeben"
|
||||
},
|
||||
"notifications": {
|
||||
"load_more": "Mehr laden",
|
||||
"no_notifications": "Du hast derzeit keine Benachrichtigungen"
|
||||
},
|
||||
"selfEvaluation": {
|
||||
"instruction": [
|
||||
"Überprüfe, ob du in der Lernheinheit",
|
||||
"alles verstanden hast.",
|
||||
"Lies die folgende Aussage und bewerte sie:"
|
||||
],
|
||||
"no": "Das muss ich nochmals anschauen",
|
||||
"progressLink": "KompetenzNavi öffnen",
|
||||
"progressText": "Schau dein Fortschritt in deinem KompetenzNavi:",
|
||||
"selfEvaluation": "Selbsteinschätzung",
|
||||
"selfEvaluationNo": "@:selfEvaluation: Muss ich nochmals anschauen.",
|
||||
"selfEvaluationYes": "@:selfEvaluation: Ich kann das.",
|
||||
"steps": "Schritt {current} von {max}",
|
||||
"title": "@:selfEvaluation.selfEvaluation {title}",
|
||||
"yes": "Ja, ich kann das"
|
||||
},
|
||||
"settings": {
|
||||
"emailNotifications": "Email Benachrichtigungen"
|
||||
},
|
||||
"constants": {
|
||||
"yes": "Ja",
|
||||
"no": "Nein",
|
||||
"verySatisfied": "sehr zufrieden",
|
||||
"satisfied": "zufrieden",
|
||||
"unsatisfied": "unzufrieden",
|
||||
"veryUnsatisfied": "sehr unzufrieden"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,159 +1,174 @@
|
|||
{
|
||||
"general": {
|
||||
"nextStep": "Prochaine étape",
|
||||
"start": "Commencer",
|
||||
"backToLearningPath": "zurück zum Lernpfad",
|
||||
"backToCircle": "zurück zum Circle",
|
||||
"next": "Weiter",
|
||||
"back": "zurück",
|
||||
"backCapitalized": "@.capitalize:general.back",
|
||||
"save": "Speichern",
|
||||
"learningUnit": "Lerneinheit",
|
||||
"learningPath": "Lernpfad",
|
||||
"learningSequence": "Lernsequenz",
|
||||
"show": "Anschauen",
|
||||
"circles": "Circles",
|
||||
"transferTask": "Transferauftrag | Transferaufträge",
|
||||
"feedback": "Feedback | Feedbacks",
|
||||
"exam": "Prüfung | Prüfungen",
|
||||
"examResult": "Prüfungsresultat | Prüfungsresultate",
|
||||
"certificate": "Zertifikat | Zertifikate",
|
||||
"notification": "Benachrichtigung | Benachrichtigungen",
|
||||
"profileLink": "Profil anzeigen",
|
||||
"shop": "Shop",
|
||||
"yes": "Ja",
|
||||
"no": "Nein"
|
||||
},
|
||||
"mainNavigation": {
|
||||
"logout": "Abmelden",
|
||||
"settings": "Kontoeinstellungen"
|
||||
},
|
||||
"dashboard": {
|
||||
"welcome": "Willkommen, {name}"
|
||||
},
|
||||
"learningPathPage": {
|
||||
"welcomeBack": "Willkommen zurück, {name}",
|
||||
"showListView": "Listenansicht anzeigen",
|
||||
"nextStep": "Nächster Schritt"
|
||||
},
|
||||
"circlePage": {
|
||||
"duration": "Dauer",
|
||||
"circleContentBoxTitle": "Das lernst du in diesem Circle.",
|
||||
"gotQuestions": "Hast du Fragen?",
|
||||
"contactExpertButton": "Fachexpertin kontaktieren",
|
||||
"contactExpertDescription": "Tausche dich mit der Fachexpertin für den Circle {circleName} aus.",
|
||||
"learnMore": "Erfahre mehr dazu",
|
||||
"circleContentBoxTitle": "C'est ce que tu apprends dans ce Cercle.",
|
||||
"contactExpertButton": "Contacter l'expert",
|
||||
"contactExpertDescription": "Echange avec l'experte du cercle {circleName} .",
|
||||
"documents": {
|
||||
"title": "Unterlagen",
|
||||
"expertDescription": "Stelle deinen Lernenden zusätzliche Inhalte zur Verfügung.",
|
||||
"userDescription": "Hier findest du die Unterlagen, die dir die Fachexpertin zur Verfügung gestellt hat.",
|
||||
"action": "Unterlagen hochladen",
|
||||
"modalAction": "Datei auswählen",
|
||||
"fileLabel": "Datei",
|
||||
"modalFileName": "Name",
|
||||
"modalNameInformation": "Max. 70 Zeichen",
|
||||
"chooseSequence": "Wähle eine Lernsequenz aus",
|
||||
"selectFile": "Bitte wähle eine Datei aus",
|
||||
"chooseName": "Bitte wähle einen Namen",
|
||||
"chooseLearningSequence": "Bitte wähle eine Lernsequenz aus",
|
||||
"uploadErrorMessage": "Beim Hochladen ist ein Fehler aufgetreten. Bitte versuche es erneut.",
|
||||
"maxFileSize": "Maximale Dateigrösse: 20 MB"
|
||||
}
|
||||
},
|
||||
"learningContent": {
|
||||
"completeAndContinue": "Als erledigt markieren"
|
||||
},
|
||||
"selfEvaluation": {
|
||||
"selfEvaluation": "Selbsteinschätzung",
|
||||
"title": "@:selfEvaluation.selfEvaluation {title}",
|
||||
"steps": "Schritt {current} von {max}",
|
||||
"instruction": [
|
||||
"Überprüfe, ob du in der Lernheinheit",
|
||||
"alles verstanden hast.",
|
||||
"Lies die folgende Aussage und bewerte sie:"
|
||||
],
|
||||
"yes": "Ja, ich kann das",
|
||||
"no": "Das muss ich nochmals anschauen",
|
||||
"progressText": "Schau dein Fortschritt in deinem KompetenzNavi:",
|
||||
"progressLink": "KompetenzNavi öffnen",
|
||||
"selfEvaluationYes": "@:selfEvaluation: Ich kann das.",
|
||||
"selfEvaluationNo": "@:selfEvaluation: Muss ich nochmals anschauen."
|
||||
},
|
||||
"competences": {
|
||||
"competences": "Kompetenzen",
|
||||
"title": "KompetenzNavi",
|
||||
"lastImprovements": "Letzte verbesserte Kompetenzen",
|
||||
"showAll": "Alle anschauen",
|
||||
"assessment": "Einschätzungen",
|
||||
"notAssessed": "Nicht eingeschätzt",
|
||||
"assessAgain": "Sich nochmals einschätzen"
|
||||
},
|
||||
"mediaLibrary": {
|
||||
"title": "Mediathek",
|
||||
"learningMedia": {
|
||||
"titel": "Lernmedien",
|
||||
"description": "Finde eine vollständige Liste der Bücher und anderen Medien, auf die im Kurs verwiesen wird."
|
||||
"action": "Télécharger des documents",
|
||||
"chooseLearningSequence": "Choisis une séquence d'apprentissage",
|
||||
"chooseName": "Choisis un nom",
|
||||
"chooseSequence": "Choisis une séquence d'apprentissage",
|
||||
"expertDescription": "Mettre à disposition de tes apprenants des contenus supplémentaires",
|
||||
"fileLabel": "Fichier",
|
||||
"maxFileSize": "Taille maximale du fichier : 20 Mo",
|
||||
"modalAction": "Choisir un fichier",
|
||||
"modalFileName": "Nom",
|
||||
"modalNameInformation": "Max. 70 caractères",
|
||||
"selectFile": "Choisis un fichier",
|
||||
"title": "Documents",
|
||||
"uploadErrorMessage": "Une erreur est survenue lors du téléchargement. Veuillez réessayer.",
|
||||
"userDescription": "Tu trouveras ici les documents que l'experte en la matière a mis à ta disposition."
|
||||
},
|
||||
"handlungsfelder": {
|
||||
"title": "Handlungsfeld | Handlungsfelder",
|
||||
"description": "Finde alle Ressourcen der Handlungsfelder wie Lernmedien, Links und andere nützliche Informationen."
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"dataProtection": "Datenschutzbestimmungen",
|
||||
"imprint": "Impressum",
|
||||
"contact": "Kontakt",
|
||||
"faq": "FAQ"
|
||||
"duration": "Durée",
|
||||
"gotQuestions": "Tu as des questions ?",
|
||||
"learnMore": "En savoir plus sur ce sujet"
|
||||
},
|
||||
"cockpit": {
|
||||
"title": "Cockpit",
|
||||
"tasksDone": "Erledigte Transferaufträge von Teilnehmer.",
|
||||
"feedbacksDone": "Abgeschickte Feedbacks von Teilnehmer.",
|
||||
"examsDone": "Abgelegte Prüfungen von Teilnehmer.",
|
||||
"progress": "Fortschritt",
|
||||
"profileLink": "Profil anzeigen"
|
||||
"examsDone": "Examens passés par les participants.",
|
||||
"feedbacksDone": "Feedbacks envoyés par les participants.",
|
||||
"notifyTask": "notifier",
|
||||
"notifyTaskDescription": "Notifier les participants",
|
||||
"profileLink": "Voir le profil",
|
||||
"progress": "Progrès",
|
||||
"tasksDone": "Ordres de transfert terminés par le participant.",
|
||||
"title": "Cockpit"
|
||||
},
|
||||
"messages": {
|
||||
"sendMessage": "Nachricht schreiben"
|
||||
},
|
||||
"feedback": {
|
||||
"intro": "{name}, dein/e Trainer/-in, bittet dich, ihm/ihr Feedback zu geben. Das ist freiwillig, würde aber ihm/ihr helfen, deine Lernerlebniss zu verbessern.",
|
||||
"areYouSatisfied": "Wie zufrieden bist du?",
|
||||
"recommendLabel": "Würden Sie den Kurs weiterempfehlen?",
|
||||
"satisfactionLabel": "Zufriedenheit insgesamt",
|
||||
"goalAttainmentLabel": "Zielerreichung insgesamt",
|
||||
"proficiencyLabel": "Wie beurteilen Sie Ihre Sicherheit bezüglichen den Themen nach dem Kurs?",
|
||||
"receivedMaterialsLabel": "Haben Sie Vorbereitungsunterlagen (z.B. eLearning) erhalten?",
|
||||
"materialsRatingLabel": "Falls ja: Wie beurteilen Sie die Vorbereitungsunterlagen (z.B. eLearning)?",
|
||||
"instructorCompetenceLabel": "Der Kursleiter war themenstark, fachkompetent.",
|
||||
"instructorRespectLabel": "Fragen und Anregungen der Kursteilnehmenden wurden ernst genommen und aufgegriffen.",
|
||||
"instructorOpenFeedbackLabel": "Was ich dem Kursleiter sonst noch sagen wollte:",
|
||||
"courseNegativeFeedbackLabel": "Wo sehen Sie Verbesserungspotenzial?",
|
||||
"coursePositiveFeedbackLabel": "Was hat Ihnen besonders gut gefallen?",
|
||||
"completionTitle": "Schicke dein Feedback an {name}",
|
||||
"completionDescription": "Dein Feedback ist anonym. Dein Vor- und Nachname werden bei deiner Trainer/-in nicht angezeigt.",
|
||||
"sendFeedback": "Feedback abschicken",
|
||||
"feedbackSent": "Dein Feedback wurde abgeschickt",
|
||||
"circleFeedback": "Feedback zum Circle",
|
||||
"showDetails": "Details anzeigen",
|
||||
"sentByUsers": "Von {count} Teilnehmern ausgefüllt",
|
||||
"feedbackPageTitle": "Feedback zum Lehrgang",
|
||||
"feedbackPageInfo": "Teilnehmer haben das Feedback ausgefüllt",
|
||||
"questionTitle": "Frage",
|
||||
"veryUnhappy": "Sehr unzufrieden",
|
||||
"unhappy": "Unzufrieden",
|
||||
"happy": "Zufrieden",
|
||||
"veryHappy": "Sehr zufrieden",
|
||||
"average": "Durchschnitt",
|
||||
"answers": "Antworten",
|
||||
"noFeedbacks": "Es wurden noch keine Feedbacks abgegeben"
|
||||
"competences": {
|
||||
"assessAgain": "S'évaluer à nouveau",
|
||||
"assessment": "évaluation",
|
||||
"competences": "Compétences",
|
||||
"lastImprovements": "Dernières compétences améliorées",
|
||||
"notAssessed": "Non évalué",
|
||||
"title": "CompetenceNavi"
|
||||
},
|
||||
"constants": {
|
||||
"yes": "Ja",
|
||||
"no": "Nein",
|
||||
"verySatisfied": "sehr zufrieden",
|
||||
"satisfied": "zufrieden",
|
||||
"unsatisfied": "unzufrieden",
|
||||
"veryUnsatisfied": "sehr unzufrieden"
|
||||
"no": "Non",
|
||||
"satisfied": "satisfait",
|
||||
"unsatisfied": "insatisfait",
|
||||
"verySatisfied": "très satisfait",
|
||||
"veryUnsatisfied": "très insatisfait",
|
||||
"yes": "Our"
|
||||
},
|
||||
"dashboard": {
|
||||
"welcome": "Bienvenue, {name}"
|
||||
},
|
||||
"feedback": {
|
||||
"answers": "Réponses",
|
||||
"areYouSatisfied": "A quel point es-tu satisfait ?",
|
||||
"average": "Moyenne",
|
||||
"circleFeedback": "Feedback sur le Cercle",
|
||||
"completionDescription": "Ton feedback est anonyme. Ton prénom et ton nom n'apparaissent pas sur le site de ton formateur.",
|
||||
"completionTitle": "Envoie ton feedback à {name}",
|
||||
"courseNegativeFeedbackLabel": "Où voyez-vous un potentiel d'amélioration ?",
|
||||
"coursePositiveFeedbackLabel": "Qu'avez-vous particulièrement apprécié ?",
|
||||
"feedbackPageInfo": "Les participants ont complété le feedback",
|
||||
"feedbackPageTitle": "Feedback sur la formation",
|
||||
"feedbackSent": "Ton feedback a été envoyé",
|
||||
"goalAttainmentLabel": "Total des objectifs réalisés",
|
||||
"happy": "Satisfait",
|
||||
"instructorCompetenceLabel": "Le formateur était très compétent.",
|
||||
"instructorOpenFeedbackLabel": "Ce que je voulais dire d'autre au formateur :",
|
||||
"instructorRespectLabel": "Les questions et les suggestions des participants au cours ont été prises au sérieux et traitées.",
|
||||
"intro": "{name}, ton formateur te demande de lui donner un feedback. C'est facultatif, mais cela l'aidera à améliorer ton expérience d'apprentissage.",
|
||||
"materialsRatingLabel": "Si oui, comment jugez-vous les documents de préparation (par exemple, eLearning) ?",
|
||||
"noFeedbacks": "Aucun feedback n'a encore été donné",
|
||||
"proficiencyLabel": "Comment évaluez-vous votre sécurité par rapport aux thèmes après le cours ?",
|
||||
"questionTitle": "Question",
|
||||
"receivedMaterialsLabel": "Avez-vous reçu des documents de préparation (par ex. eLearning) ?",
|
||||
"recommendLabel": "Recommanderiez-vous ce cours?",
|
||||
"satisfactionLabel": "Satisfaction totale",
|
||||
"sendFeedback": "Envoyer le feedback",
|
||||
"sentByUsers": "Rempli par {count} participants",
|
||||
"showDetails": "Voir les détails",
|
||||
"unhappy": "insatisfait",
|
||||
"veryHappy": "très satisfait",
|
||||
"veryUnhappy": "très insatisfait"
|
||||
},
|
||||
"footer": {
|
||||
"contact": "Contact",
|
||||
"dataProtection": "Politique de confidentialité",
|
||||
"faq": "FAQ",
|
||||
"imprint": "Impressum"
|
||||
},
|
||||
"general": {
|
||||
"back": "retour",
|
||||
"backCapitalized": "@.capitalize:general.back",
|
||||
"backToCircle": "retour au Cercle",
|
||||
"backToLearningPath": "retour au parcours d'apprentissage",
|
||||
"certificate": "Certificat | Certificats",
|
||||
"circles": "Cercles",
|
||||
"exam": "Examen | Examens",
|
||||
"examResult": "Résultat de l'examen | Résultats de l'examen",
|
||||
"feedback": "Feedback | Feedbacks",
|
||||
"learningPath": "Parcours d'apprentissage",
|
||||
"learningSequence": "Séquence d'apprentissage",
|
||||
"learningUnit": "Unité d'apprentissage",
|
||||
"next": "Suivant",
|
||||
"nextStep": "A suivre",
|
||||
"no": "Non",
|
||||
"notification": "Notification | Notifications",
|
||||
"profileLink": "Voir le profil",
|
||||
"save": "Sauvegarde",
|
||||
"send": "Envoyer",
|
||||
"settings": "Configuration du compte",
|
||||
"shop": "Shop",
|
||||
"show": "Montrer",
|
||||
"showAll": "Montrer tous",
|
||||
"start": "On y va",
|
||||
"transferTask": "Ordre de transfert | Ordres de transfert",
|
||||
"yes": "Our"
|
||||
},
|
||||
"language": {
|
||||
"de": "Allemand",
|
||||
"fr": "Français"
|
||||
},
|
||||
"learningContent": {
|
||||
"completeAndContinue": "Marquer comme fait"
|
||||
},
|
||||
"learningPathPage": {
|
||||
"nextStep": "Prochaine étape",
|
||||
"showListView": "Voir la liste",
|
||||
"welcomeBack": "Bienvenue, {name}"
|
||||
},
|
||||
"mainNavigation": {
|
||||
"logout": "Fermer la session",
|
||||
"profile": "Profil"
|
||||
},
|
||||
"mediaLibrary": {
|
||||
"handlungsfelder": {
|
||||
"description": "Trouve toutes les ressources des domaines d'action comme les médias d'apprentissage, les liens et autres informations utiles.",
|
||||
"title": "Domaine d'action | Domaines d'action"
|
||||
},
|
||||
"learningMedia": {
|
||||
"description": "Trouve une liste complète des livres et autres supports auxquels il est fait référence dans le cours.",
|
||||
"titel": "Médias d'apprentissage"
|
||||
},
|
||||
"title": "Médiathèque"
|
||||
},
|
||||
"messages": {
|
||||
"sendMessage": "Envoyer un message"
|
||||
},
|
||||
"notifications": {
|
||||
"load_more": "Plus de détails",
|
||||
"no_notifications": "Tu n'as pas de notifications pour le moment"
|
||||
},
|
||||
"selfEvaluation": {
|
||||
"instruction": [
|
||||
"Vérifie que dans l'unité d'apprentissage",
|
||||
"tu as tout compris.",
|
||||
"Lis et évalue l'affirmation suivante :"
|
||||
],
|
||||
"no": "Je dois regarder à nouveau",
|
||||
"progressLink": "Ouvrir CompetenceNavi",
|
||||
"progressText": "Regarde ta progression dans ton CompetenceNavi :",
|
||||
"selfEvaluation": "Évaluation personnelle",
|
||||
"selfEvaluationNo": "@:selfEvaluation: Je dois le regarder à nouveau.",
|
||||
"selfEvaluationYes": "@:selfEvaluation: Je peux faire ça.",
|
||||
"steps": "Etape {current} de {max}",
|
||||
"title": "@:selfEvaluation.selfEvaluation {title}",
|
||||
"yes": "Oui, je peux faire ça"
|
||||
},
|
||||
"settings": {
|
||||
"emailNotifications": "Notifications par e-mail"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@ onMounted(async () => {
|
|||
></LearningPathDiagramSmall>
|
||||
</div>
|
||||
<div>
|
||||
<router-link class="btn-blue" :to="courseSession.learning_path_url">
|
||||
<router-link
|
||||
class="btn-blue"
|
||||
:to="courseSession.learning_path_url"
|
||||
:data-cy="`continue-course-${courseSession.course.id}`"
|
||||
>
|
||||
{{ $t("general.nextStep") }}
|
||||
</router-link>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import IconLogout from "@/components/icons/IconLogout.vue";
|
||||
import IconSettings from "@/components/icons/IconSettings.vue";
|
||||
import LearningPathCircle from "@/components/learningPath/LearningPathCircle.vue";
|
||||
import LearningPathCircle from "@/components/learningPath/page/LearningPathCircle.vue";
|
||||
import HorizontalBarChart from "@/components/ui/HorizontalBarChart.vue";
|
||||
import ItCheckbox from "@/components/ui/ItCheckbox.vue";
|
||||
import ItCheckboxGroup from "@/components/ui/ItCheckboxGroup.vue";
|
||||
|
|
@ -9,6 +9,7 @@ import ItDropdown from "@/components/ui/ItDropdown.vue";
|
|||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||
import ItRadioGroup from "@/components/ui/ItRadioGroup.vue";
|
||||
import ItTextarea from "@/components/ui/ItTextarea.vue";
|
||||
import ItToggleSwitch from "@/components/ui/ItToggleSwitch.vue";
|
||||
import RatingScale from "@/components/ui/RatingScale.vue";
|
||||
import VerticalBarChart from "@/components/ui/VerticalBarChart.vue";
|
||||
import logger from "loglevel";
|
||||
|
|
@ -517,6 +518,10 @@ function log(data: any) {
|
|||
},
|
||||
]"
|
||||
></LearningPathCircle>
|
||||
|
||||
<h2 class="mt-8 mb-8">ItToggleSwitch</h2>
|
||||
|
||||
<ItToggleSwitch></ItToggleSwitch>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -26,23 +26,23 @@
|
|||
:text="question.question"
|
||||
/>
|
||||
<VerticalBarChart
|
||||
class="mb-8 bg-white"
|
||||
v-else-if="verticalChartKyes.includes(question.key)"
|
||||
class="mb-8 bg-white"
|
||||
:title="`${$t('feedback.questionTitle')} ${i + 1}`"
|
||||
:ratings="feedbackData.questions[question.key]"
|
||||
:text="question.question"
|
||||
:ratio="0.2"
|
||||
/>
|
||||
<OpenFeedback
|
||||
class="mb-8 bg-white"
|
||||
v-else-if="openKeys.includes(question.key)"
|
||||
class="mb-8 bg-white"
|
||||
:title="`${$t('feedback.questionTitle')} ${i + 1}`"
|
||||
:text="question.question"
|
||||
:answers="feedbackData.questions[question.key].filter((a: string) => a !== '')"
|
||||
></OpenFeedback>
|
||||
<HorizontalBarChart
|
||||
class="mb-8 bg-white"
|
||||
v-else-if="horizontalChartKeys.includes(question.key)"
|
||||
class="mb-8 bg-white"
|
||||
:title="`${$t('feedback.questionTitle')} ${i}`"
|
||||
:text="question.question"
|
||||
:items="feedbackData.questions[question.key].map((a: string) => `${a}%`)"
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import * as log from "loglevel";
|
||||
|
||||
import LearningPathAppointmentsMock from "@/components/learningPath/page/LearningPathAppointmentsMock.vue";
|
||||
import LearningPathListView from "@/components/learningPath/page/LearningPathListView.vue";
|
||||
import LearningPathPathView from "@/components/learningPath/page/LearningPathPathView.vue";
|
||||
import CircleProgress from "@/components/learningPath/page/LearningPathProgress.vue";
|
||||
import LearningPathTopics from "@/components/learningPath/page/LearningPathTopics.vue";
|
||||
import type { ViewType } from "@/components/learningPath/page/LearningPathViewSwitch.vue";
|
||||
import LearningPathViewSwitch from "@/components/learningPath/page/LearningPathViewSwitch.vue";
|
||||
import { useLearningPathStore } from "@/stores/learningPath";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { computed, onMounted } from "vue";
|
||||
|
||||
import LearningPathDiagram from "@/components/learningPath/LearningPathDiagram.vue";
|
||||
import LearningPathViewVertical from "@/components/learningPath/LearningPathViewVertical.vue";
|
||||
import type { LearningPath } from "@/services/learningPath";
|
||||
|
||||
log.debug("LearningPathView created");
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
|
|
@ -18,108 +19,136 @@ const props = defineProps<{
|
|||
const learningPathStore = useLearningPathStore();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const learningPath = computed(() => {
|
||||
if (userStore.loggedIn && learningPathStore.learningPaths.size > 0) {
|
||||
const learningPathKey = `${props.courseSlug}-lp-${userStore.id}`;
|
||||
return learningPathStore.learningPaths.get(learningPathKey);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
// Layout state
|
||||
const useMobileLayout = ref(false);
|
||||
const selectedView = ref<ViewType>(
|
||||
(window.localStorage.getItem("learningPathView") as ViewType) || "path"
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
log.debug("LearningPathView mounted");
|
||||
log.debug("LearningPathPage mounted");
|
||||
|
||||
try {
|
||||
await learningPathStore.loadLearningPath(props.courseSlug + "-lp");
|
||||
} catch (error) {
|
||||
log.error(error);
|
||||
}
|
||||
|
||||
// Detect if we're on a mobile layout
|
||||
watchLayoutChanges();
|
||||
});
|
||||
|
||||
const createContinueUrl = (learningPath: LearningPath): [string, boolean] => {
|
||||
if (learningPath?.nextLearningContent) {
|
||||
const circle = learningPath.nextLearningContent.parentCircle;
|
||||
const url =
|
||||
learningPath.nextLearningContent.parentLearningSequence?.frontend_url ||
|
||||
circle.frontend_url;
|
||||
const isFirst =
|
||||
learningPath.nextLearningContent.translation_key ===
|
||||
learningPath.circles[0].flatLearningContents[0].translation_key;
|
||||
return [url, isFirst];
|
||||
const learningPath = computed(() => {
|
||||
if (userStore.loggedIn && learningPathStore.learningPaths.size > 0) {
|
||||
const learningPathKey = `${props.courseSlug}-lp-${userStore.id}`;
|
||||
return learningPathStore.learningPaths.get(learningPathKey);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
|
||||
return ["", false];
|
||||
const circlesCount = computed(() => {
|
||||
if (learningPath.value) {
|
||||
return learningPath.value.circles.length;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const inProgressCirclesCount = computed(() => {
|
||||
if (learningPath.value) {
|
||||
return learningPath.value.circles.filter(
|
||||
(circle) =>
|
||||
circle.learningSequences.filter((ls) =>
|
||||
circle.someFinishedInLearningSequence(ls.translation_key)
|
||||
).length
|
||||
).length;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const watchLayoutChanges = () => {
|
||||
const mobileLayoutQuery = window.matchMedia("(min-width: 640px)");
|
||||
useMobileLayout.value = !mobileLayoutQuery.matches;
|
||||
mobileLayoutQuery.onchange = (event) => {
|
||||
useMobileLayout.value = !event.matches;
|
||||
};
|
||||
};
|
||||
|
||||
const changeViewType = (viewType: ViewType) => {
|
||||
selectedView.value = viewType;
|
||||
window.localStorage.setItem("learningPathView", viewType);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="learningPath" class="bg-gray-200">
|
||||
<Teleport to="body">
|
||||
<LearningPathViewVertical
|
||||
:show="learningPathStore.page === 'OVERVIEW'"
|
||||
:learning-path="learningPath"
|
||||
@closemodal="learningPathStore.page = 'INDEX'"
|
||||
/>
|
||||
</Teleport>
|
||||
|
||||
<div class="learningpath flex flex-col">
|
||||
<div class="flex h-max flex-col">
|
||||
<div class="flex flex-col bg-white lg:py-8">
|
||||
<div class="flex justify-end lg:p-4">
|
||||
<button
|
||||
class="btn-text inline-flex items-center px-3 lg:py-2"
|
||||
data-cy="show-list-view"
|
||||
@click="learningPathStore.page = 'OVERVIEW'"
|
||||
>
|
||||
<it-icon-list />
|
||||
{{ $t("learningPathPage.showListView") }}
|
||||
</button>
|
||||
</div>
|
||||
<LearningPathDiagram
|
||||
class="mx-auto max-h-[90px] w-full max-w-[1920px] px-4 lg:max-h-[380px]"
|
||||
diagram-type="horizontal"
|
||||
:learning-path="learningPath"
|
||||
></LearningPathDiagram>
|
||||
<div class="flex flex-col">
|
||||
<!-- Top -->
|
||||
<div class="flex flex-row justify-between space-x-8 bg-gray-200 p-6 sm:p-12">
|
||||
<!-- Left -->
|
||||
<div class="flex flex-col justify-between">
|
||||
<div>
|
||||
<p class="font-bold">
|
||||
{{ $t("learningPathPage.welcomeBack", { name: userStore.first_name }) }}
|
||||
</p>
|
||||
<h2 data-cy="learning-path-title">
|
||||
{{ learningPath?.title }}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="container-large pt-0 lg:pt-4">
|
||||
<h1 data-cy="learning-path-title" class="mt-6 mb-6 lg:mt-12">
|
||||
{{ learningPath.title }}
|
||||
</h1>
|
||||
<div
|
||||
class="flex flex-col justify-start divide-y divide-gray-500 bg-white p-4 lg:mb-16 lg:flex-row lg:divide-y-0 lg:divide-x"
|
||||
>
|
||||
<div class="flex-auto p-2 lg:p-8">
|
||||
<h2>
|
||||
{{ $t("learningPathPage.welcomeBack", { name: userStore.first_name }) }}
|
||||
</h2>
|
||||
<p class="mt-4 text-xl"></p>
|
||||
</div>
|
||||
<div v-if="learningPath.nextLearningContent" class="flex-2 p-4 lg:p-8">
|
||||
{{ $t("learningPathPage.nextStep") }}
|
||||
<h3>
|
||||
{{ learningPath.nextLearningContent.parentCircle.title }}:
|
||||
{{ learningPath.nextLearningContent.parentLearningSequence?.title }}
|
||||
</h3>
|
||||
<router-link
|
||||
class="btn-blue mt-4"
|
||||
:to="createContinueUrl(learningPath)[0]"
|
||||
data-cy="lp-continue-button"
|
||||
translate
|
||||
>
|
||||
<span v-if="createContinueUrl(learningPath)[1]">
|
||||
{{ $t("general.start") }}
|
||||
</span>
|
||||
<span v-else>{{ $t("general.nextStep") }}</span>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<CircleProgress
|
||||
:all-count="circlesCount"
|
||||
:in-progress-count="inProgressCirclesCount"
|
||||
></CircleProgress>
|
||||
</div>
|
||||
|
||||
<!-- Right -->
|
||||
<div v-if="!useMobileLayout" class="max-w-md">
|
||||
<LearningPathAppointmentsMock></LearningPathAppointmentsMock>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom -->
|
||||
<div class="bg-white">
|
||||
<div class="flex flex-col justify-between px-6 sm:flex-row sm:px-12">
|
||||
<!-- Topics -->
|
||||
<div
|
||||
v-if="selectedView == 'path'"
|
||||
class="order-2 pb-8 sm:order-1 sm:pb-0 sm:pt-4"
|
||||
>
|
||||
<LearningPathTopics :topics="learningPath?.topics ?? []"></LearningPathTopics>
|
||||
</div>
|
||||
<div class="topic"></div>
|
||||
<div v-else class="flex-grow"></div>
|
||||
|
||||
<!-- View switch -->
|
||||
<LearningPathViewSwitch
|
||||
class="order-1 py-8 sm:order-2 sm:py-0 sm:pt-4"
|
||||
:initial-view="selectedView"
|
||||
@select-view="changeViewType($event)"
|
||||
></LearningPathViewSwitch>
|
||||
</div>
|
||||
|
||||
<!-- Path view -->
|
||||
<div v-if="selectedView == 'path'" class="flex flex-col" data-cy="lp-path-view">
|
||||
<LearningPathPathView
|
||||
:learning-path="learningPath"
|
||||
:use-mobile-layout="useMobileLayout"
|
||||
></LearningPathPathView>
|
||||
</div>
|
||||
|
||||
<!-- List view -->
|
||||
<div
|
||||
v-if="selectedView == 'list'"
|
||||
class="flex flex-col pl-6 sm:pl-24"
|
||||
data-cy="lp-list-view"
|
||||
>
|
||||
<LearningPathListView :learning-path="learningPath"></LearningPathListView>
|
||||
</div>
|
||||
<div
|
||||
v-if="useMobileLayout"
|
||||
class="p-6"
|
||||
:class="useMobileLayout ? 'bg-gray-200' : ''"
|
||||
>
|
||||
<LearningPathAppointmentsMock></LearningPathAppointmentsMock>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { beforeEach, describe, expect, vi } from "vitest";
|
||||
import * as courseSessions from "../../stores/courseSessions";
|
||||
import { expertRequired } from "../guards";
|
||||
|
||||
describe("Guards", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// creates a fresh pinia and make it active so it's automatically picked
|
||||
// up by any useStore() call without having to pass it to it:
|
||||
// `useStore(pinia)`
|
||||
setActivePinia(createPinia());
|
||||
});
|
||||
|
||||
it("cannot route to cockpit", () => {
|
||||
vi.spyOn(courseSessions, "useCourseSessionsStore").mockReturnValue({
|
||||
hasCockpit: false,
|
||||
});
|
||||
const slug = "test";
|
||||
expect(expertRequired({ params: { courseSlug: "test" } })).toEqual(
|
||||
`/course/${slug}/learn`
|
||||
);
|
||||
});
|
||||
|
||||
it("can route to cockpit", () => {
|
||||
vi.spyOn(courseSessions, "useCourseSessionsStore").mockReturnValue({
|
||||
hasCockpit: true,
|
||||
});
|
||||
const to = {
|
||||
params: {
|
||||
courseSlug: "test",
|
||||
},
|
||||
};
|
||||
expect(expertRequired(to)).toEqual(to);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import type { NavigationGuardWithThis, RouteLocationNormalized } from "vue-router";
|
||||
import type { NavigationGuard, RouteLocationNormalized } from "vue-router";
|
||||
|
||||
export const updateLoggedIn: NavigationGuardWithThis<undefined> = async () => {
|
||||
export const updateLoggedIn: NavigationGuard = async () => {
|
||||
const loggedIn = getCookieValue("loginStatus") === "true";
|
||||
const userStore = useUserStore();
|
||||
|
||||
|
|
@ -11,7 +12,7 @@ export const updateLoggedIn: NavigationGuardWithThis<undefined> = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
export const redirectToLoginIfRequired: NavigationGuardWithThis<undefined> = (to) => {
|
||||
export const redirectToLoginIfRequired: NavigationGuard = (to) => {
|
||||
const userStore = useUserStore();
|
||||
if (loginRequired(to) && !userStore.loggedIn) {
|
||||
return `/login?next=${to.fullPath}`;
|
||||
|
|
@ -32,3 +33,13 @@ export const getCookieValue = (cookieName: string): string => {
|
|||
const loginRequired = (to: RouteLocationNormalized) => {
|
||||
return !to.meta?.public;
|
||||
};
|
||||
|
||||
export const expertRequired: NavigationGuard = (to: RouteLocationNormalized) => {
|
||||
const courseSessionsStore = useCourseSessionsStore();
|
||||
if (courseSessionsStore.hasCockpit) {
|
||||
return to;
|
||||
} else {
|
||||
const courseSlug = to.params.courseSlug as string;
|
||||
return `/course/${courseSlug}/learn`;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import DashboardPage from "@/pages/DashboardPage.vue";
|
||||
import LoginPage from "@/pages/LoginPage.vue";
|
||||
import { redirectToLoginIfRequired, updateLoggedIn } from "@/router/guards";
|
||||
import {
|
||||
expertRequired,
|
||||
redirectToLoginIfRequired,
|
||||
updateLoggedIn,
|
||||
} from "@/router/guards";
|
||||
import { useAppStore } from "@/stores/app";
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
|
||||
|
|
@ -103,6 +107,7 @@ const router = createRouter({
|
|||
path: "/course/:courseSlug/cockpit",
|
||||
props: true,
|
||||
component: () => import("@/pages/cockpit/CockpitParentPage.vue"),
|
||||
beforeEnter: [expertRequired],
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
|
|
|
|||
|
|
@ -222,6 +222,12 @@ export class Circle implements WagtailCircle {
|
|||
return false;
|
||||
}
|
||||
|
||||
public isComplete(): boolean {
|
||||
return this.learningSequences.every((ls) =>
|
||||
this.allFinishedInLearningSequence(ls.translation_key)
|
||||
);
|
||||
}
|
||||
|
||||
public parseCompletionData(completionData: CourseCompletion[]) {
|
||||
this.flatChildren.forEach((page) => {
|
||||
const pageIndex = completionData.findIndex((e) => {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ import type {
|
|||
WagtailLearningPath,
|
||||
} from "@/types";
|
||||
|
||||
export interface ContinueData {
|
||||
url: string;
|
||||
has_no_progress: boolean;
|
||||
}
|
||||
|
||||
function getLastCompleted(courseId: number, completionData: CourseCompletion[]) {
|
||||
return orderBy(completionData, ["updated_at"], "desc").find((c: CourseCompletion) => {
|
||||
return (
|
||||
|
|
@ -125,4 +130,25 @@ export class LearningPath implements WagtailLearningPath {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get continueData(): ContinueData {
|
||||
if (this.nextLearningContent) {
|
||||
const circle = this.nextLearningContent.parentCircle;
|
||||
const url =
|
||||
this.nextLearningContent.parentLearningSequence?.frontend_url ||
|
||||
circle.frontend_url;
|
||||
const isFirst =
|
||||
this.nextLearningContent.translation_key ===
|
||||
this.circles[0].flatLearningContents[0].translation_key;
|
||||
return {
|
||||
url,
|
||||
has_no_progress: isFirst,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
url: "",
|
||||
has_no_progress: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
import { itGetCached, itPost } from "@/fetchHelpers";
|
||||
import type { CourseSession } from "@/types";
|
||||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { beforeEach, describe, expect, vi } from "vitest";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useCourseSessionsStore } from "../courseSessions";
|
||||
import { useUserStore } from "../user";
|
||||
|
||||
let user = {};
|
||||
let courseSessions: CourseSession[] = [];
|
||||
|
||||
describe("CourseSession Store", () => {
|
||||
vi.mock("vue-router", () => ({
|
||||
useRoute: () => ({
|
||||
path: "/course/test-course/learn/",
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("@/fetchHelpers", () => {
|
||||
const itGetCached = () => Promise.resolve([]);
|
||||
const itPost = () => Promise.resolve([]);
|
||||
|
||||
return {
|
||||
itGetCached,
|
||||
itPost,
|
||||
};
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// creates a fresh pinia and make it active so it's automatically picked
|
||||
// up by any useStore() call without having to pass it to it:
|
||||
// `useStore(pinia)`
|
||||
setActivePinia(createPinia());
|
||||
user = {
|
||||
is_superuser: false,
|
||||
course_session_expert: [],
|
||||
};
|
||||
courseSessions = [
|
||||
{
|
||||
id: 1,
|
||||
created_at: "2021-05-11T10:00:00.000000Z",
|
||||
updated_at: "2023-05-11T10:00:00.000000Z",
|
||||
course: {
|
||||
id: 1,
|
||||
title: "Test Course",
|
||||
category_name: "Test Category",
|
||||
slug: "test-course",
|
||||
},
|
||||
title: "Test Course Session",
|
||||
start_date: "2022-05-11T10:00:00.000000Z",
|
||||
end_date: "2023-05-11T10:00:00.000000Z",
|
||||
learning_path_url: "/course/test-course/learn/",
|
||||
competence_url: "/course/test-course/competence/",
|
||||
course_url: "/course/test-course/",
|
||||
media_library_url: "/course/test-course/media/",
|
||||
additional_json_data: {},
|
||||
documents: [],
|
||||
users: [],
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
it("normal user has no cockpit", () => {
|
||||
const userStore = useUserStore();
|
||||
const courseSessionsStore = useCourseSessionsStore();
|
||||
userStore.$patch(user);
|
||||
courseSessionsStore.$patch({ courseSessions });
|
||||
|
||||
expect(courseSessionsStore.hasCockpit).toBeFalsy();
|
||||
});
|
||||
|
||||
it("superuser has cockpit", () => {
|
||||
const userStore = useUserStore();
|
||||
const courseSessionsStore = useCourseSessionsStore();
|
||||
userStore.$patch(Object.assign(user, { is_superuser: true }));
|
||||
courseSessionsStore.$patch({ courseSessions });
|
||||
|
||||
expect(courseSessionsStore.hasCockpit).toBeTruthy();
|
||||
});
|
||||
|
||||
it("expert has cockpit", () => {
|
||||
const userStore = useUserStore();
|
||||
const courseSessionsStore = useCourseSessionsStore();
|
||||
userStore.$patch(
|
||||
Object.assign(user, { course_session_experts: [courseSessions[0].id] })
|
||||
);
|
||||
courseSessionsStore.$patch({ courseSessions });
|
||||
|
||||
expect(courseSessionsStore.hasCockpit).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
import { itGet } from "@/fetchHelpers";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import type { Notification } from "@/types";
|
||||
import log from "loglevel";
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { ref, watch } from "vue";
|
||||
|
||||
type NotificationListData = {
|
||||
all_count: number;
|
||||
|
|
@ -29,8 +31,18 @@ export const useNotificationsStore = defineStore("notifications", () => {
|
|||
hasUnread.value = data.unread_count !== 0;
|
||||
}
|
||||
|
||||
updateUnreadCount();
|
||||
setInterval(async () => await updateUnreadCount(), 30000);
|
||||
const userStore = useUserStore();
|
||||
let timerHandle: number | null = null;
|
||||
watch(userStore, () => {
|
||||
if (userStore.loggedIn && timerHandle === null) {
|
||||
log.debug("Notification polling started");
|
||||
updateUnreadCount();
|
||||
timerHandle = setInterval(async () => await updateUnreadCount(), 30000);
|
||||
} else if (!userStore.loggedIn) {
|
||||
log.debug("Notification polling stopped");
|
||||
timerHandle = null;
|
||||
}
|
||||
});
|
||||
|
||||
return { loadNotifications, hasUnread, allCount };
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { defineStore } from "pinia";
|
|||
const logoutRedirectUrl = import.meta.env.VITE_LOGOUT_REDIRECT;
|
||||
// typed state https://stackoverflow.com/questions/71012513/when-using-pinia-and-typescript-how-do-you-use-an-action-to-set-the-state
|
||||
|
||||
export type availableLanguages = "de" | "fr" | "it";
|
||||
export type AvailableLanguages = "de" | "fr" | "it";
|
||||
|
||||
export type UserState = {
|
||||
id: number;
|
||||
|
|
@ -20,7 +20,7 @@ export type UserState = {
|
|||
is_superuser: boolean;
|
||||
course_session_experts: number[];
|
||||
loggedIn: boolean;
|
||||
language: availableLanguages;
|
||||
language: AvailableLanguages;
|
||||
};
|
||||
|
||||
const initialUserState: UserState = {
|
||||
|
|
@ -36,7 +36,7 @@ const initialUserState: UserState = {
|
|||
language: "de",
|
||||
};
|
||||
|
||||
async function setLocale(language: availableLanguages) {
|
||||
async function setLocale(language: AvailableLanguages) {
|
||||
await loadLocaleMessages(language);
|
||||
setI18nLanguage(language);
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ export const useUserStore = defineStore({
|
|||
appStore.userLoaded = true;
|
||||
await setLocale(data.language);
|
||||
},
|
||||
async setUserLanguages(language: availableLanguages) {
|
||||
async setUserLanguages(language: AvailableLanguages) {
|
||||
await setLocale(language);
|
||||
this.$state.language = language;
|
||||
await itPost("/api/core/me/", { language }, { method: "PUT" });
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||
"exclude": ["src/**/__tests__/*"],
|
||||
"compilerOptions": {
|
||||
"lib": ["ES2021", "DOM", "DOM.Iterable"],
|
||||
"composite": true,
|
||||
"strict": true,
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
"composite": true,
|
||||
"lib": ["ES2021", "DOM", "DOM.Iterable"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"strict": true
|
||||
},
|
||||
"exclude": ["src/**/__tests__/*"],
|
||||
"extends": "@vue/tsconfig/tsconfig.web.json",
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||
"include": ["vite.config.*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"types": ["node", "vitest"]
|
||||
}
|
||||
},
|
||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
||||
"include": ["vite.config.*"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"extends": "./tsconfig.app.json",
|
||||
"exclude": [],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"lib": [],
|
||||
"types": ["node", "jsdom", "vitest/globals"]
|
||||
}
|
||||
},
|
||||
"exclude": [],
|
||||
"extends": "./tsconfig.app.json"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// eslint-disable-next-line
|
||||
module.exports = {
|
||||
vueFiles: "./src/**/*.?(js|vue)",
|
||||
languageFiles: "./src/locales/*.json",
|
||||
exclude: ["translation_key_1", "translation_key_2"],
|
||||
output: false,
|
||||
add: false,
|
||||
remove: false,
|
||||
ci: false,
|
||||
separator: ".",
|
||||
noEmptyTranslation: "",
|
||||
};
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {login} from "./helpers";
|
||||
import { login } from "./helpers";
|
||||
|
||||
describe("learningPath page", () => {
|
||||
beforeEach(() => {
|
||||
|
|
@ -19,7 +19,7 @@ describe("learningPath page", () => {
|
|||
login("admin", "test");
|
||||
cy.visit("/course/versicherungsvermittler-in-alt/learn");
|
||||
|
||||
cy.get('[data-cy="circle-analyse"]').click({force: true});
|
||||
cy.get('[data-cy="circle-Analyse"]').click({ force: true });
|
||||
|
||||
cy.url().should(
|
||||
"include",
|
||||
|
|
@ -28,20 +28,15 @@ describe("learningPath page", () => {
|
|||
cy.get('[data-cy="circle-title"]').should("contain", "Analyse");
|
||||
});
|
||||
|
||||
it("open listView and click on circle will open circle", () => {
|
||||
it("switch between list and path view", () => {
|
||||
login("admin", "test");
|
||||
cy.visit("/course/versicherungsvermittler-in-alt/learn");
|
||||
|
||||
cy.get('[data-cy="show-list-view"]').click();
|
||||
cy.get('[data-cy="full-screen-modal"]').should("be.visible");
|
||||
|
||||
cy.get('[data-cy="circle-analyse-vertical"]').click({force: true});
|
||||
|
||||
cy.url().should(
|
||||
"include",
|
||||
"/course/versicherungsvermittler-in-alt/learn/analyse"
|
||||
);
|
||||
cy.get('[data-cy="circle-title"]').should("contain", "Analyse");
|
||||
cy.get('[data-cy="lp-path-view"]').should("be.visible");
|
||||
cy.get('[data-cy="view-switch"]').click();
|
||||
cy.get('[data-cy="lp-list-view"]').should("be.visible");
|
||||
cy.get('[data-cy="view-switch"]').click();
|
||||
cy.get('[data-cy="lp-path-view"]').should("be.visible");
|
||||
});
|
||||
|
||||
it("weiter gehts button will open next circle", () => {
|
||||
|
|
@ -49,21 +44,25 @@ describe("learningPath page", () => {
|
|||
cy.visit("/course/versicherungsvermittler-in-alt/learn");
|
||||
|
||||
// first click will open first circle
|
||||
cy.get('[data-cy="lp-continue-button"]').should("contain", "Los geht's");
|
||||
cy.get('[data-cy="lp-continue-button"]').click();
|
||||
cy.get('[data-cy="lp-continue-button"]')
|
||||
.filter(":visible")
|
||||
.should("contain", "Los geht's")
|
||||
.click();
|
||||
cy.get('[data-cy="circle-title"]').should("contain", "Basis");
|
||||
cy.get('[data-cy="back-to-learning-path-button"]').click();
|
||||
|
||||
// mark a learning content in second circle
|
||||
cy.get('[data-cy="circle-analyse"]').click({force: true});
|
||||
cy.get('[data-cy="circle-Analyse"]').click({ force: true });
|
||||
cy.get(
|
||||
'[data-cy="versicherungsvermittler-in-alt-lp-circle-analyse-lc-fachcheck-fahrzeug-checkbox"] > .cy-checkbox'
|
||||
).click();
|
||||
cy.get('[data-cy="back-to-learning-path-button"]').click();
|
||||
|
||||
// click on continue should go to unit-test-circle
|
||||
cy.get('[data-cy="lp-continue-button"]').should("contain", "Weiter geht's");
|
||||
cy.get('[data-cy="lp-continue-button"]').click();
|
||||
cy.get('[data-cy="lp-continue-button"]')
|
||||
.filter(":visible")
|
||||
.should("contain", "Weiter geht's")
|
||||
.click();
|
||||
cy.get('[data-cy="circle-title"]').should("contain", "Analyse");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
encrypted: env_secrets/caprover_dev.env
|
||||
encrypted: env_secrets/caprover_prod.env
|
||||
encrypted: env_secrets/caprover_stage.env
|
||||
encrypted: env_secrets/local_chrigu.env
|
||||
encrypted: env_secrets/local_daniel.env
|
||||
encrypted: env_secrets/local_elia.env
|
||||
encrypted: env_secrets/local_lorenz.env
|
||||
encrypted: env_secrets/production.env
|
||||
encrypted: env_secrets/caprover_dev.env
|
||||
encrypted: env_secrets/caprover_prod.env
|
||||
encrypted: env_secrets/caprover_stage.env
|
||||
encrypted: env_secrets/local_chrigu.env
|
||||
encrypted: env_secrets/local_daniel.env
|
||||
encrypted: env_secrets/local_elia.env
|
||||
encrypted: env_secrets/local_lorenz.env
|
||||
encrypted: env_secrets/production.env
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"cypress:open": "cypress open",
|
||||
"cypress:ci": "currents run --parallel --record --key $CURRENTS_KEY",
|
||||
"prettier": "npm run prettier --prefix client"
|
||||
"prettier": "npm run prettier --prefix client",
|
||||
"vue-i18n-extract": "npm run vue-i18n-extract --prefix client"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@currents/cli": "^3.1.3",
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ from vbv_lernwelt.competence.factories import (
|
|||
PerformanceCriteriaFactory,
|
||||
)
|
||||
from vbv_lernwelt.competence.models import CompetencePage
|
||||
from vbv_lernwelt.course.consts import COURSE_UK1
|
||||
from vbv_lernwelt.course.consts import COURSE_UK, COURSE_UK_FR
|
||||
from vbv_lernwelt.course.models import CoursePage
|
||||
from vbv_lernwelt.learnpath.models import LearningPath, LearningUnit
|
||||
|
||||
|
||||
def create_uk_competence_profile(course_id=COURSE_UK1):
|
||||
def create_uk_competence_profile(course_id=COURSE_UK):
|
||||
course_page = CoursePage.objects.get(course_id=course_id)
|
||||
slug_prefix = course_page.get_children().exact_type(LearningPath).first().slug
|
||||
|
||||
|
|
@ -20,104 +20,33 @@ def create_uk_competence_profile(course_id=COURSE_UK1):
|
|||
|
||||
competences = [
|
||||
{
|
||||
"competence_id": "A1",
|
||||
"title": "Weiterempfehlung für Neukunden generieren",
|
||||
"items": [
|
||||
"Verhandlungsgeschick",
|
||||
"Überzeugtes Auftreten",
|
||||
],
|
||||
},
|
||||
{
|
||||
"competence_id": "A2",
|
||||
"title": "Kundengespräche vereinbaren",
|
||||
"items": [
|
||||
"Gesprächsführung / Fragetechniken",
|
||||
"Selbstorganisation",
|
||||
"Arbeitstechniken",
|
||||
"Psychologische Kenntnisse / Kommunikations-psychologie",
|
||||
],
|
||||
},
|
||||
{
|
||||
"competence_id": "A3",
|
||||
"title": "Auftritt in den sozialen Medien zeitgemäss halten",
|
||||
"items": [
|
||||
"Gesetzliche und Compliance-Anforderungen der Versicherer",
|
||||
"Datenschutzgesetz",
|
||||
"Kommunikation in den sozialen Medien",
|
||||
],
|
||||
},
|
||||
{"competence_id": "A4", "title": "Kundendaten erfassen", "items": []},
|
||||
{
|
||||
"competence_id": "B1",
|
||||
"title": "Wünsche, Ziele und Bedürfnisse der Kunden im Gespräch ermitteln",
|
||||
"items": [
|
||||
"Gesprächsführung",
|
||||
"Fragetechniken",
|
||||
"Kundenpsychologie",
|
||||
],
|
||||
},
|
||||
{
|
||||
"competence_id": "B2",
|
||||
"title": "Analyse des Kundenbedarfs und des Kundenbedürfnisses durchführen",
|
||||
"items": [
|
||||
"Fragetechniken",
|
||||
"Visuelle Hilfsmittel / Visualisierungstechniken",
|
||||
],
|
||||
},
|
||||
{
|
||||
"competence_id": "B3",
|
||||
"title": "Individuelle Lösungsvorschläge erarbeiten",
|
||||
"items": [
|
||||
"Fundierte Produktekenntnisse",
|
||||
"Regulatorische Vorschriften",
|
||||
],
|
||||
},
|
||||
{
|
||||
"competence_id": "B4",
|
||||
"title": "Lösungsvorschläge präsentieren und umsetzen",
|
||||
"items": [
|
||||
"Verhandlungsstrategien",
|
||||
"Fundierte Produktkenntnisse",
|
||||
"Visuelle Hilfsmittel / Visualisierungstechniken",
|
||||
],
|
||||
},
|
||||
{
|
||||
"competence_id": "C1",
|
||||
"title": "Cross- und Upselling; bestehende fremdverwaltete Versicherungspolicen prüfen und in das Portfolio aufnehmen",
|
||||
"items": [
|
||||
"Produktkenntnisse",
|
||||
"Gesprächsführung",
|
||||
"Kommunikation",
|
||||
"Fragetechnik",
|
||||
"Verhandlungsgeschick",
|
||||
"Vertragsrecht",
|
||||
"Regulatorische Vorgaben",
|
||||
"UVG, BVG, KVG, VVG",
|
||||
],
|
||||
},
|
||||
{
|
||||
"competence_id": "C2",
|
||||
"title": "Änderungswünsche entgegennehmen und bestehende Verträge anpassen",
|
||||
"items": [
|
||||
"Produktkenntnisse",
|
||||
"Gesprächsführung",
|
||||
"Kommunikation",
|
||||
"Fragetechnik",
|
||||
"Verhandlungsgeschick",
|
||||
"Vertragsrecht",
|
||||
"Regulatorische Vorgaben",
|
||||
"UVG, BVG, KVG, VVG",
|
||||
],
|
||||
},
|
||||
{
|
||||
"competence_id": "C3",
|
||||
"title": "Kunden im Schadenfall unterstützen",
|
||||
"competence_id": "e4",
|
||||
"title": "Betriebsbezogene Inhalte multimedial aufbereiten",
|
||||
"items": [],
|
||||
},
|
||||
{"competence_id": "C4", "title": "Bestehende Kunden pflegen", "items": []},
|
||||
{
|
||||
"competence_id": "C5",
|
||||
"title": "Versicherungsanträge nachbearbeiten",
|
||||
"competence_id": "c3",
|
||||
"title": "Betriebliche Prozesse dokumentieren, koordinieren und umsetzen",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "e2",
|
||||
"title": "Informationen im wirtschaftlichen und kaufmännischen Bereich recherchieren",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "d2",
|
||||
"title": "Informations- und Beratungsgespräche mit Kunden oder Lieferanten führen",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "d3",
|
||||
"title": "Betriebliche Prozesse dokumentieren, koordinieren und umsetzen",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "d1",
|
||||
"title": "Anliegen von Kunden oder Lieferanten entgegennehmen",
|
||||
"items": [],
|
||||
},
|
||||
]
|
||||
|
|
@ -130,165 +59,235 @@ def create_uk_competence_profile(course_id=COURSE_UK1):
|
|||
items=[("item", i) for i in c["items"]],
|
||||
)
|
||||
|
||||
# Daten anhand von WEVM_Version Oktober 2022
|
||||
# Einstieg/Beobachten – Selbsteinschätzung «Einkommenssicherung»
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="e4"
|
||||
),
|
||||
competence_id="A2.1",
|
||||
title="Ich bin fähig je nach (Neu-) Kunde Form und Ort für das Gespräch festzulegen.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-kickoff-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
),
|
||||
competence_id="A2.2",
|
||||
title="Ich bin fähig mir intern und extern die nötigen Informationen über den (Neu-) Kunden zu beschaffen.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-kickoff-lu-arbeits-und-lerntechnik"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
),
|
||||
competence_id="A2.3",
|
||||
title="Ich bin fähig die Terminierung auf das Thema Einkommenssicherung auszurichten.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-kickoff-lu-versicherung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
),
|
||||
competence_id="A2.4",
|
||||
title="Ich bin fähig für das zu führende Gespräch eine Agenda zu erstellen.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-kickoff-lu-beratung-und-verkauf"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
),
|
||||
competence_id="A2.5",
|
||||
title="Ich bin fähig für das Handlungsfeld «Einkommenssicherung» geeignete Hilfsmittel und Unterlagen zusammenzustellen.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-kickoff-lu-sozialer-auftritt"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="B1"
|
||||
),
|
||||
competence_id="B1.1",
|
||||
title="Ich bin fähig dem Kunden den Gesprächsablauf und den Zeitrahmen (mittels Agenda) aufzuzeigen.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-basis-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="B1"
|
||||
),
|
||||
competence_id="B1.2",
|
||||
title="Ich bin fähig mich beim Kunden korrekt zu identifizieren (VAG 45).",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-basis-lu-arbeits-und-lerntechnik"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="B2"
|
||||
),
|
||||
competence_id="B2.3",
|
||||
title="Ich bin fähig alle erforderlichen Unterlagen einzufordern.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-basis-lu-versicherung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A1"
|
||||
),
|
||||
competence_id="A1.6",
|
||||
title="Ich bin fähig im täglichen Kontakt potenzielle Kundinnen und Kunden zu erkennen.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-basis-lu-versicherung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
),
|
||||
competence_id="A2.1",
|
||||
title="Ich bin fähig je nach (Neu-) Kunde Form und Ort für das Gespräch festzulegen.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-basis-lu-beratung-und-verkauf"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
),
|
||||
competence_id="A2.2",
|
||||
title="Ich bin fähig mir intern und extern die nötigen Informationen über den (Neu-) Kunden zu beschaffen.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-basis-lu-sozialer-auftritt"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
),
|
||||
competence_id="A2.3",
|
||||
title="Ich bin fähig die Terminierung auf das Thema Fahrzeug auszurichten.",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-versicherung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
),
|
||||
competence_id="A2.4",
|
||||
title="Ich bin fähig für das zu führende Gespräch eine Agenda zu erstellen.",
|
||||
competence_id="e4.pv.ük1",
|
||||
title="Sie erläutern die Dienstleistungen des Betriebs. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="e4"
|
||||
),
|
||||
competence_id="A2.5",
|
||||
title="Ich bin fähig für das zu führende Gespräch geeignete Hilfsmittel und Unterlagen zusammenzustellen.",
|
||||
competence_id="e4.pv.ük3",
|
||||
title="Sie stellen die Wertschöpfungskette und die verschiedenen organisatorischen Bereiche ihres Betriebs dar. (K2).",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-arbeits-und-lerntechnik"
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="e4"
|
||||
),
|
||||
competence_id="A2.3",
|
||||
title="Ich bin fähig die Terminierung auf das Thema Reisen auszurichten.",
|
||||
competence_id="e4.pv.ük4",
|
||||
title="Sie erläutern die relevanten rechtlichen Grundlagen ihrer Branche situationsgerecht. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-versicherung"
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="A2"
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="d2"
|
||||
),
|
||||
competence_id="A2.4",
|
||||
title="Ich bin fähig für das zu führende Gespräch eine Agenda zu erstellen.",
|
||||
competence_id="d2.pv.ük1",
|
||||
title="Sie beschreiben die wichtigsten gesetzlichen Grundlagen im Versicherungsbereich umfassend. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-sozialer-auftritt"
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="d2"
|
||||
),
|
||||
competence_id="d2.pv.ük2",
|
||||
title="Sie nennen die relevanten Dienstleistungen und Produkte im Versicherungsbereich. (K1)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="d2"
|
||||
),
|
||||
competence_id="d2.pv.ük3",
|
||||
title="Sie erklären die Leistungen und Produkte im Versicherungsbereich. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="d2"
|
||||
),
|
||||
competence_id="d2.pv.ük4",
|
||||
title="Sie erläutern die Prozesse und Abläufe im privaten Versicherungsbereich verständlich. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="c3"
|
||||
),
|
||||
competence_id="c3.pv.ük7",
|
||||
title="Sie erläutern die gesetzlichen Bestimmungen bei Schaden- und Leistungsfällen. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="c3"
|
||||
),
|
||||
competence_id="c3.pv.ük11",
|
||||
title="Sie beurteilen gängige Versicherungslösungen fachkundig. (K3)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-fahrzeug-lu-einführung"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def create_uk_fr_competence_profile(course_id=COURSE_UK_FR):
|
||||
course_page = CoursePage.objects.get(course_id=course_id)
|
||||
slug_prefix = course_page.get_children().exact_type(LearningPath).first().slug
|
||||
|
||||
competence_profile_page = CompetenceProfilePageFactory(
|
||||
title="KompetenzNavi",
|
||||
parent=course_page,
|
||||
)
|
||||
|
||||
competences = [
|
||||
{
|
||||
"competence_id": "e4",
|
||||
"title": "Betriebsbezogene Inhalte multimedial aufbereiten",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "c3",
|
||||
"title": "Betriebliche Prozesse dokumentieren, koordinieren und umsetzen",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "e2",
|
||||
"title": "Informationen im wirtschaftlichen und kaufmännischen Bereich recherchieren",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "d2",
|
||||
"title": "Informations- und Beratungsgespräche mit Kunden oder Lieferanten führen",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "d3",
|
||||
"title": "Betriebliche Prozesse dokumentieren, koordinieren und umsetzen",
|
||||
"items": [],
|
||||
},
|
||||
{
|
||||
"competence_id": "d1",
|
||||
"title": "Anliegen von Kunden oder Lieferanten entgegennehmen",
|
||||
"items": [],
|
||||
},
|
||||
]
|
||||
|
||||
for c in competences:
|
||||
CompetencePageFactory(
|
||||
parent=competence_profile_page,
|
||||
competence_id=c["competence_id"],
|
||||
title=c["title"],
|
||||
items=[("item", i) for i in c["items"]],
|
||||
)
|
||||
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="e4"
|
||||
),
|
||||
competence_id="e4.pv.ük1",
|
||||
title="Sie erläutern die Dienstleistungen des Betriebs. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="e4"
|
||||
),
|
||||
competence_id="e4.pv.ük3",
|
||||
title="Sie stellen die Wertschöpfungskette und die verschiedenen organisatorischen Bereiche ihres Betriebs dar. (K2).",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="e4"
|
||||
),
|
||||
competence_id="e4.pv.ük4",
|
||||
title="Sie erläutern die relevanten rechtlichen Grundlagen ihrer Branche situationsgerecht. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="d2"
|
||||
),
|
||||
competence_id="d2.pv.ük1",
|
||||
title="Sie beschreiben die wichtigsten gesetzlichen Grundlagen im Versicherungsbereich umfassend. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="d2"
|
||||
),
|
||||
competence_id="d2.pv.ük2",
|
||||
title="Sie nennen die relevanten Dienstleistungen und Produkte im Versicherungsbereich. (K1)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="d2"
|
||||
),
|
||||
competence_id="d2.pv.ük3",
|
||||
title="Sie erklären die Leistungen und Produkte im Versicherungsbereich. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="d2"
|
||||
),
|
||||
competence_id="d2.pv.ük4",
|
||||
title="Sie erläutern die Prozesse und Abläufe im privaten Versicherungsbereich verständlich. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="c3"
|
||||
),
|
||||
competence_id="c3.pv.ük7",
|
||||
title="Sie erläutern die gesetzlichen Bestimmungen bei Schaden- und Leistungsfällen. (K2)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
PerformanceCriteriaFactory(
|
||||
parent=CompetencePage.objects.get(
|
||||
slug__startswith=slug_prefix.replace("-lp", ""), competence_id="c3"
|
||||
),
|
||||
competence_id="c3.pv.ük11",
|
||||
title="Sie beurteilen gängige Versicherungslösungen fachkundig. (K3)",
|
||||
learning_unit=LearningUnit.objects.get(
|
||||
slug=f"{slug_prefix}-circle-véhicule-lu-einführung"
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import djclick as click
|
||||
|
||||
from vbv_lernwelt.core.models import User
|
||||
from vbv_lernwelt.course.models import CourseCompletion
|
||||
from vbv_lernwelt.notify.models import Notification
|
||||
|
||||
|
|
@ -9,3 +10,4 @@ def command():
|
|||
print("cypress reset data")
|
||||
CourseCompletion.objects.all().delete()
|
||||
Notification.objects.all().delete()
|
||||
User.objects.all().update(language="de")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
COURSE_TEST_ID = -1
|
||||
COURSE_VERSICHERUNGSVERMITTLERIN_OLD_ID = -2
|
||||
COURSE_UK1 = -3
|
||||
COURSE_UK = -3
|
||||
COURSE_VERSICHERUNGSVERMITTLERIN_ID = -4
|
||||
COURSE_UK_FR = -5
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from wagtail.models import Page
|
|||
|
||||
from vbv_lernwelt.competence.create_uk_competence_profile import (
|
||||
create_uk_competence_profile,
|
||||
create_uk_fr_competence_profile,
|
||||
)
|
||||
from vbv_lernwelt.competence.create_vv_competence_profile import (
|
||||
create_vv_competence_profile,
|
||||
|
|
@ -14,7 +15,8 @@ from vbv_lernwelt.core.create_default_users import default_users
|
|||
from vbv_lernwelt.core.models import User
|
||||
from vbv_lernwelt.course.consts import (
|
||||
COURSE_TEST_ID,
|
||||
COURSE_UK1,
|
||||
COURSE_UK,
|
||||
COURSE_UK_FR,
|
||||
COURSE_VERSICHERUNGSVERMITTLERIN_ID,
|
||||
COURSE_VERSICHERUNGSVERMITTLERIN_OLD_ID,
|
||||
)
|
||||
|
|
@ -23,6 +25,7 @@ from vbv_lernwelt.course.creators.versicherungsvermittlerin import (
|
|||
create_versicherungsvermittlerin_with_categories,
|
||||
)
|
||||
from vbv_lernwelt.course.management.commands.create_uk_course import (
|
||||
create_uk_fr_learning_path,
|
||||
create_uk_learning_path,
|
||||
)
|
||||
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
||||
|
|
@ -66,13 +69,21 @@ def command():
|
|||
create_vv_new_learning_path()
|
||||
create_default_media_library(course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID)
|
||||
|
||||
# Überbetriebliche Kurse
|
||||
# Überbetriebliche Kurse DE
|
||||
create_versicherungsvermittlerin_with_categories(
|
||||
course_id=COURSE_UK1, title="Überbetriebliche Kurse"
|
||||
course_id=COURSE_UK, title="Überbetriebliche Kurse"
|
||||
)
|
||||
create_uk_learning_path(course_id=COURSE_UK1)
|
||||
create_uk_competence_profile(course_id=COURSE_UK1)
|
||||
create_default_media_library(course_id=COURSE_UK1)
|
||||
create_uk_learning_path(course_id=COURSE_UK)
|
||||
create_uk_competence_profile(course_id=COURSE_UK)
|
||||
create_default_media_library(course_id=COURSE_UK)
|
||||
|
||||
# Überbetriebliche Kurse FR
|
||||
create_versicherungsvermittlerin_with_categories(
|
||||
course_id=COURSE_UK_FR, title="Course hors établissement"
|
||||
)
|
||||
create_uk_fr_learning_path(course_id=COURSE_UK_FR)
|
||||
create_uk_fr_competence_profile(course_id=COURSE_UK_FR)
|
||||
create_default_media_library(course_id=COURSE_UK_FR)
|
||||
|
||||
# test course
|
||||
create_test_course()
|
||||
|
|
@ -137,88 +148,120 @@ def command():
|
|||
)
|
||||
|
||||
# course session Überbetriebliche Kurse Lehrjahr 1 - Region Bern
|
||||
cs = CourseSession.objects.create(
|
||||
course_id=COURSE_UK1,
|
||||
title="Überbetriebliche Kurse Lehrjahr 1 - Region Bern",
|
||||
)
|
||||
# for user_data in default_users:
|
||||
# CourseSessionUser.objects.create(
|
||||
# course_session=cs,
|
||||
# user=User.objects.get(username=user_data["email"]),
|
||||
# )
|
||||
# csu = CourseSessionUser.objects.create(
|
||||
# course_session=cs,
|
||||
# user=User.objects.get(username="trainer-uk1.einstieg@eiger-versicherungen.ch"),
|
||||
# )
|
||||
# csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-einstieg"))
|
||||
# csu = CourseSessionUser.objects.create(
|
||||
# course_session=cs,
|
||||
# user=User.objects.get(username="trainer-uk1.analyse@eiger-versicherungen.ch"),
|
||||
# )
|
||||
# csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-analyse"))
|
||||
# csu = CourseSessionUser.objects.create(
|
||||
# course_session=cs,
|
||||
# user=User.objects.get(username="student-uk1-bern@eiger-versicherungen.ch"),
|
||||
# )
|
||||
courses = [
|
||||
{
|
||||
"course_id": COURSE_UK,
|
||||
"title": "Überbetriebliche Kurse Lehrjahr 1 - Region Bern",
|
||||
"basis_slug": "überbetriebliche-kurse-lp-circle-basis",
|
||||
"kickoff_slug": "überbetriebliche-kurse-lp-circle-kickoff",
|
||||
"haushalt1_slug": "überbetriebliche-kurse-lp-circle-haushalt-teil-1",
|
||||
"fahrzeug_slug": "überbetriebliche-kurse-lp-circle-fahrzeug",
|
||||
"haushalt2_slug": "überbetriebliche-kurse-lp-circle-haushalt-teil-2",
|
||||
},
|
||||
{
|
||||
"course_id": COURSE_UK_FR,
|
||||
"title": "Cours hors établissement année 1 - Région Fribourg",
|
||||
"basis_slug": "course-hors-établissement-lp-circle-basis",
|
||||
"kickoff_slug": "course-hors-établissement-lp-circle-kickoff",
|
||||
"haushalt1_slug": "course-hors-établissement-lp-circle-haushalt-teil-1",
|
||||
"fahrzeug_slug": "course-hors-établissement-lp-circle-fahrzeug",
|
||||
"haushalt2_slug": "course-hors-établissement-lp-circle-haushalt-teil-2",
|
||||
},
|
||||
]
|
||||
for course in courses:
|
||||
cs = CourseSession.objects.create(
|
||||
course_id=course["course_id"],
|
||||
title=course["title"],
|
||||
)
|
||||
# for user_data in default_users:
|
||||
# CourseSessionUser.objects.create(
|
||||
# course_session=cs,
|
||||
# user=User.objects.get(username=user_data["email"]),
|
||||
# )
|
||||
# csu = CourseSessionUser.objects.create(
|
||||
# course_session=cs,
|
||||
# user=User.objects.get(username="trainer-uk1.einstieg@eiger-versicherungen.ch"),
|
||||
# )
|
||||
# csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-einstieg"))
|
||||
# csu = CourseSessionUser.objects.create(
|
||||
# course_session=cs,
|
||||
# user=User.objects.get(username="trainer-uk1.analyse@eiger-versicherungen.ch"),
|
||||
# )
|
||||
# csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-analyse"))
|
||||
# csu = CourseSessionUser.objects.create(
|
||||
# course_session=cs,
|
||||
# user=User.objects.get(username="student-uk1-bern@eiger-versicherungen.ch"),
|
||||
# )
|
||||
|
||||
# figma demo users and data
|
||||
csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="patrizia.huggel@eiger-versicherungen.ch"),
|
||||
role=CourseSessionUser.Role.EXPERT,
|
||||
)
|
||||
csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-kickoff"))
|
||||
csu.expert.add(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-haushalt-teil-1")
|
||||
)
|
||||
csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-fahrzeug"))
|
||||
csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="andreas.feuz@eiger-versicherungen.ch"),
|
||||
role=CourseSessionUser.Role.EXPERT,
|
||||
)
|
||||
csu.expert.add(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-haushalt-teil-2")
|
||||
)
|
||||
csu.expert.add(Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-basis"))
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="michael.meier@example.com"),
|
||||
)
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="lina.egger@example.com"),
|
||||
)
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="evelyn.schmid@example.com"),
|
||||
)
|
||||
# figma demo users and data
|
||||
csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="patrizia.huggel@eiger-versicherungen.ch"),
|
||||
role=CourseSessionUser.Role.EXPERT,
|
||||
)
|
||||
csu.expert.add(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-kickoff")
|
||||
)
|
||||
csu.expert.add(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-haushalt-teil-1")
|
||||
)
|
||||
csu.expert.add(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-fahrzeug")
|
||||
)
|
||||
csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="andreas.feuz@eiger-versicherungen.ch"),
|
||||
role=CourseSessionUser.Role.EXPERT,
|
||||
)
|
||||
csu.expert.add(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-haushalt-teil-2")
|
||||
)
|
||||
csu.expert.add(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-basis")
|
||||
)
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="michael.meier@example.com"),
|
||||
)
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="lina.egger@example.com"),
|
||||
)
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="evelyn.schmid@example.com"),
|
||||
)
|
||||
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="christoph.bosshard@vbv-afa.ch"),
|
||||
)
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="christoph.bosshard@vbv-afa.ch"),
|
||||
)
|
||||
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="axel.manderbach@lernetz.ch"),
|
||||
)
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="bianca.muster@eiger-versicherungen.ch"),
|
||||
)
|
||||
|
||||
create_feedback(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-kickoff"), cs, 3
|
||||
)
|
||||
create_feedback(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-haushalt-teil-2"),
|
||||
cs,
|
||||
14,
|
||||
)
|
||||
create_feedback(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-basis"), cs, 4
|
||||
)
|
||||
_csu = CourseSessionUser.objects.create(
|
||||
course_session=cs,
|
||||
user=User.objects.get(username="axel.manderbach@lernetz.ch"),
|
||||
)
|
||||
|
||||
create_feedback(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-kickoff"), cs, 3
|
||||
)
|
||||
create_feedback(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-haushalt-teil-2"),
|
||||
cs,
|
||||
14,
|
||||
)
|
||||
create_feedback(
|
||||
Circle.objects.get(slug="überbetriebliche-kurse-lp-circle-basis"), cs, 4
|
||||
)
|
||||
|
||||
# course session Überbetriebliche Kurse Lehrjahr 1 - Region Zürich
|
||||
cs = CourseSession.objects.create(
|
||||
course_id=COURSE_UK1,
|
||||
course_id=COURSE_UK,
|
||||
title="Überbetriebliche Kurse Lehrjahr 1 - Region Zürich",
|
||||
)
|
||||
# for user_data in default_users:
|
||||
|
|
@ -248,7 +291,7 @@ def command():
|
|||
# initial completion data
|
||||
for slug, status, email in [
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a21-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük4-allgemein",
|
||||
"success",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -273,7 +316,7 @@ def command():
|
|||
"michael.meier@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a22-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük3-allgemein",
|
||||
"success",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -293,7 +336,7 @@ def command():
|
|||
"michael.meier@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük1-allgemein",
|
||||
"success",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -313,7 +356,7 @@ def command():
|
|||
"michael.meier@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a24-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük4-allgemein",
|
||||
"fail",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -338,7 +381,7 @@ def command():
|
|||
"michael.meier@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a25-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük3-allgemein",
|
||||
"success",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -368,7 +411,7 @@ def command():
|
|||
"michael.meier@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a24-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük2-allgemein",
|
||||
"success",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -393,7 +436,7 @@ def command():
|
|||
"michael.meier@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a25-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük1-allgemein",
|
||||
"success",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -413,7 +456,7 @@ def command():
|
|||
"michael.meier@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-c3pvük7-allgemein",
|
||||
"fail",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -433,7 +476,7 @@ def command():
|
|||
"michael.meier@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein-2",
|
||||
"überbetriebliche-kurse-competence-crit-c3pvük11-allgemein",
|
||||
"fail",
|
||||
"michael.meier@example.com",
|
||||
),
|
||||
|
|
@ -498,7 +541,7 @@ def command():
|
|||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a21-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük4-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
|
|
@ -523,7 +566,7 @@ def command():
|
|||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a22-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük3-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
|
|
@ -543,7 +586,7 @@ def command():
|
|||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük1-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
|
|
@ -563,7 +606,7 @@ def command():
|
|||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a24-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük4-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
|
|
@ -583,7 +626,7 @@ def command():
|
|||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a25-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük3-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
|
|
@ -613,7 +656,7 @@ def command():
|
|||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a24-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük2-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
|
|
@ -638,7 +681,7 @@ def command():
|
|||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a25-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük1-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
|
|
@ -658,12 +701,12 @@ def command():
|
|||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-c3pvük7-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein-2",
|
||||
"überbetriebliche-kurse-competence-crit-c3pvük11-allgemein",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
|
|
@ -697,11 +740,6 @@ def command():
|
|||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a24-allgemein-2",
|
||||
"success",
|
||||
"lina.egger@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-lp-circle-fahrzeug-lc-mediathek-4",
|
||||
"success",
|
||||
|
|
@ -773,7 +811,7 @@ def command():
|
|||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a21-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük4-allgemein",
|
||||
"success",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
|
|
@ -798,7 +836,7 @@ def command():
|
|||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a22-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük3-allgemein",
|
||||
"fail",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
|
|
@ -818,7 +856,7 @@ def command():
|
|||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-e4pvük1-allgemein",
|
||||
"fail",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
|
|
@ -838,7 +876,7 @@ def command():
|
|||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a24-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük4-allgemein",
|
||||
"success",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
|
|
@ -858,7 +896,7 @@ def command():
|
|||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a25-allgemein",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük3-allgemein",
|
||||
"success",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
|
|
@ -873,7 +911,7 @@ def command():
|
|||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a24-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük2-allgemein",
|
||||
"success",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
|
|
@ -898,7 +936,7 @@ def command():
|
|||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a25-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-d2pvük1-allgemein",
|
||||
"fail",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
|
|
@ -918,12 +956,12 @@ def command():
|
|||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein-1",
|
||||
"überbetriebliche-kurse-competence-crit-c3pvük7-allgemein",
|
||||
"success",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a23-allgemein-2",
|
||||
"überbetriebliche-kurse-competence-crit-c3pvük11-allgemein",
|
||||
"fail",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
|
|
@ -962,11 +1000,6 @@ def command():
|
|||
"success",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-competence-crit-a24-allgemein-2",
|
||||
"fail",
|
||||
"evelyn.schmid@example.com",
|
||||
),
|
||||
(
|
||||
"überbetriebliche-kurse-lp-circle-fahrzeug-lc-lerninhalt-offen-1",
|
||||
"success",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from wagtail.models import Locale, Page, Site
|
|||
from wagtail_localize.models import LocaleSynchronization
|
||||
|
||||
from vbv_lernwelt.core.admin import User
|
||||
from vbv_lernwelt.course.consts import COURSE_UK1
|
||||
from vbv_lernwelt.course.consts import COURSE_UK, COURSE_UK_FR
|
||||
from vbv_lernwelt.course.models import CoursePage
|
||||
from vbv_lernwelt.learnpath.create_vv_learning_path import (
|
||||
create_learning_content_beenden,
|
||||
|
|
@ -19,11 +19,8 @@ from vbv_lernwelt.learnpath.tests.learning_path_factories import (
|
|||
TopicFactory,
|
||||
)
|
||||
|
||||
# todo: remove when all Handlungsfelder are ready
|
||||
READY_HF = ["Fahrzeug", "Reisen"]
|
||||
|
||||
|
||||
def create_uk_learning_path(course_id=COURSE_UK1, user=None, skip_locales=True):
|
||||
def create_uk_learning_path(course_id=COURSE_UK, user=None, skip_locales=True):
|
||||
if user is None:
|
||||
user = User.objects.get(username="info@iterativ.ch")
|
||||
|
||||
|
|
@ -42,27 +39,26 @@ def create_uk_learning_path(course_id=COURSE_UK1, user=None, skip_locales=True):
|
|||
parent=course_page,
|
||||
)
|
||||
|
||||
TopicFactory(title="Kickoff", is_visible=False, parent=lp)
|
||||
TopicFactory(title="üK1", is_visible=True, parent=lp)
|
||||
create_uk_circle(lp, title="Kickoff")
|
||||
|
||||
TopicFactory(title="Basis", is_visible=False, parent=lp)
|
||||
create_uk_circle(lp, title="Basis")
|
||||
|
||||
TopicFactory(title="Fahrzeug", is_visible=False, parent=lp)
|
||||
create_uk_circle(lp, title="Fahrzeug")
|
||||
|
||||
TopicFactory(title="Haushalt Teil 1", is_visible=False, parent=lp)
|
||||
create_uk_circle(lp, title="Haushalt Teil 1")
|
||||
|
||||
TopicFactory(title="Haushalt Teil 2", is_visible=False, parent=lp)
|
||||
create_uk_circle(lp, title="Haushalt Teil 2")
|
||||
|
||||
# circle_analyse = create_circle("Betreuen", lp)
|
||||
# create_circle_children(circle_analyse, "Betreuen")
|
||||
#
|
||||
# TopicFactory(title="Prüfung", is_visible=True, parent=lp)
|
||||
# circle_analyse = create_circle("Prüfungsvorbereitung", lp)
|
||||
# create_circle_children(circle_analyse, "Prüfungsvorbereitung")
|
||||
TopicFactory(title="üK2", is_visible=True, parent=lp)
|
||||
create_uk_circle(lp, title="Reisen & Rechtsstreitigkeiten")
|
||||
create_uk_circle(lp, title="Wohneigentum")
|
||||
create_uk_circle(lp, title="KMU Teil 1")
|
||||
create_uk_circle(lp, title="KMU Teil 2")
|
||||
create_uk_circle(lp, title="3-Säulenkonzept")
|
||||
create_uk_circle(lp, title="Einkommenssicherung (Invalidität)")
|
||||
create_uk_circle(lp, title="Einkommenssicherung (Todesfall)")
|
||||
create_uk_circle(lp, title="Pensionierung (Todesfall)")
|
||||
TopicFactory(title="üK3", is_visible=True, parent=lp)
|
||||
create_uk_circle(lp, title="Gesundheit")
|
||||
create_uk_circle(lp, title="Prüfungsvorbereitung Teil 1")
|
||||
create_uk_circle(lp, title="Prüfungsvorbereitung Teil 2")
|
||||
|
||||
# locales
|
||||
if not skip_locales:
|
||||
|
|
@ -81,6 +77,62 @@ def create_uk_learning_path(course_id=COURSE_UK1, user=None, skip_locales=True):
|
|||
Page.objects.update(owner=user)
|
||||
|
||||
|
||||
def create_uk_fr_learning_path(course_id=COURSE_UK_FR, user=None, skip_locales=True):
|
||||
if user is None:
|
||||
user = User.objects.get(username="info@iterativ.ch")
|
||||
|
||||
site = Site.objects.filter(is_default_site=True).first()
|
||||
|
||||
if not site:
|
||||
site = wagtail_factories.SiteFactory(is_default_site=True)
|
||||
|
||||
if settings.APP_ENVIRONMENT == "development":
|
||||
site.port = 8000
|
||||
site.save()
|
||||
|
||||
course_page = CoursePage.objects.get(course_id=course_id)
|
||||
lp = LearningPathFactory(
|
||||
title="Lernpfad",
|
||||
parent=course_page,
|
||||
)
|
||||
|
||||
TopicFactory(title="1ère année", is_visible=True, parent=lp)
|
||||
create_uk_circle(lp, title="Coup d'envoi")
|
||||
create_uk_circle(lp, title="Base")
|
||||
create_uk_circle(lp, title="Véhicule")
|
||||
create_uk_circle(lp, title="Budget Partie 1")
|
||||
create_uk_circle(lp, title="Budget Partie 2")
|
||||
|
||||
TopicFactory(title="2ème année", is_visible=True, parent=lp)
|
||||
create_uk_circle(lp, title="Voyages / Protection juridique")
|
||||
create_uk_circle(lp, title="Proprieté du logement")
|
||||
create_uk_circle(lp, title="PME Partie 1")
|
||||
create_uk_circle(lp, title="PME Partie 2")
|
||||
create_uk_circle(lp, title="Concept des 3")
|
||||
create_uk_circle(lp, title="Garantie des revenus, Partie 1")
|
||||
create_uk_circle(lp, title="Garantie des revenus, Partie 2")
|
||||
create_uk_circle(lp, title="Retraite")
|
||||
TopicFactory(title="3ème année", is_visible=True, parent=lp)
|
||||
create_uk_circle(lp, title="Santé")
|
||||
create_uk_circle(lp, title="Préparation à l'examen, Partie 1")
|
||||
create_uk_circle(lp, title="Préparation à l'examen, Partie 2")
|
||||
# locales
|
||||
if not skip_locales:
|
||||
locale_de = Locale.objects.get(language_code="de-CH")
|
||||
locale_fr, _ = Locale.objects.get_or_create(language_code="fr-CH")
|
||||
LocaleSynchronization.objects.get_or_create(
|
||||
locale_id=locale_fr.id, sync_from_id=locale_de.id
|
||||
)
|
||||
locale_it, _ = Locale.objects.get_or_create(language_code="it-CH")
|
||||
LocaleSynchronization.objects.get_or_create(
|
||||
locale_id=locale_it.id, sync_from_id=locale_de.id
|
||||
)
|
||||
call_command("sync_locale_trees")
|
||||
|
||||
# all pages belong to 'admin' by default
|
||||
Page.objects.update(owner=user)
|
||||
|
||||
|
||||
def create_uk_circle(lp, title="Kickoff"):
|
||||
circle = CircleFactory(
|
||||
title=title,
|
||||
|
|
|
|||
|
|
@ -61,15 +61,11 @@ def create_vv_new_learning_path(
|
|||
create_circle_standard(
|
||||
lp, title="Haushalt", lc_title="Rafael und Claudia ziehen zusammen"
|
||||
)
|
||||
create_circle_standard_small(
|
||||
lp,
|
||||
title="Rechtsstreitigkeiten",
|
||||
lc_title="Rafael Fasel hat Ärger mit seinem Vermieter",
|
||||
)
|
||||
|
||||
create_circle_rechtsstreitigkeiten(lp)
|
||||
create_circle_reisen(lp)
|
||||
create_circle_standard(
|
||||
lp, title="Einkommenssicherung", lc_title="Patrizia und Marco sichern sich ab"
|
||||
)
|
||||
create_circle_einkommenssicherung(lp)
|
||||
|
||||
create_circle_standard_small(
|
||||
lp,
|
||||
title="Wohneigentum",
|
||||
|
|
@ -100,17 +96,17 @@ def create_vv_new_learning_path(
|
|||
lc_title="Familie Babic spart auf ein Ziel",
|
||||
lu_title="Sparinstrumente, Idee und Funktionsweise von Anlagefonds",
|
||||
)
|
||||
create_circle_standard(
|
||||
lp,
|
||||
title="KMU",
|
||||
lc_title="Anne Fleur übernimmt den Blumenladen",
|
||||
)
|
||||
create_circle_standard_small(
|
||||
lp,
|
||||
title="Selbstständigkeit",
|
||||
lc_title="Patrizia macht sich selbstständig",
|
||||
lu_title="Selbsständigerwerbende versichern",
|
||||
)
|
||||
create_circle_standard(
|
||||
lp,
|
||||
title="KMU",
|
||||
lc_title="Anne Fleur übernimmt den Blumenladen",
|
||||
)
|
||||
|
||||
TopicFactory(title="Prüfung", parent=lp)
|
||||
create_circle_pruefungsvorbereitung(lp)
|
||||
|
|
@ -386,7 +382,7 @@ def create_circle_fahrzeug(lp, title="Fahrzeug"):
|
|||
parent=circle,
|
||||
category_name="Fahrzeug",
|
||||
competence_id="V1",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-wechselt-sein-auto-einstieg-xapi-yXLHE5Xo/index.html",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-wechselt-sein-auto-einstieg-xapi-L3QlrrCt/index.html",
|
||||
learning_unit_title="Gesprächsvorbereitung und -einstieg",
|
||||
)
|
||||
|
||||
|
|
@ -396,7 +392,7 @@ def create_circle_fahrzeug(lp, title="Fahrzeug"):
|
|||
parent=circle,
|
||||
category_name="Fahrzeug",
|
||||
competence_id="V2",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-wechselt-sein-auto-analyse-xapi-SmrKAa0J/index.html",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-wechselt-sein-auto-analyse-xapi-YtviM_SF/index.html",
|
||||
learning_unit_title="Bedarfsanalyse, Ist- und Soll-Situation",
|
||||
)
|
||||
|
||||
|
|
@ -406,7 +402,7 @@ def create_circle_fahrzeug(lp, title="Fahrzeug"):
|
|||
parent=circle,
|
||||
category_name="Fahrzeug",
|
||||
competence_id="V3",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-wechselt-sein-auto-losung-xapi-3rzf8ySd/index.html",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-wechselt-sein-auto-losung-xapi-jTdlOjOF/index.html",
|
||||
learning_unit_title="Lösungsvorschlag erarbeiten und präsentieren",
|
||||
)
|
||||
|
||||
|
|
@ -416,7 +412,7 @@ def create_circle_fahrzeug(lp, title="Fahrzeug"):
|
|||
parent=circle,
|
||||
category_name="Fahrzeug",
|
||||
competence_id="V4",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-wechselt-sein-auto-abschluss-xapi-WbFBv-4y/index.html",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-wechselt-sein-auto-abschluss-xapi-OBWheB8q/index.html",
|
||||
learning_unit_title="Gesprächszusammenfassung, Abschluss und Nachbereitung",
|
||||
)
|
||||
|
||||
|
|
@ -450,6 +446,46 @@ def create_circle_fahrzeug(lp, title="Fahrzeug"):
|
|||
)
|
||||
|
||||
|
||||
def create_circle_rechtsstreitigkeiten(lp, title="Rechtsstreitigkeiten"):
|
||||
circle = CircleFactory(
|
||||
title=title,
|
||||
parent=lp,
|
||||
)
|
||||
LearningSequenceFactory(title="Einführung", parent=circle, icon="it-icon-ls-start")
|
||||
LearningUnitFactory(title="Einführung", parent=circle)
|
||||
LearningContentFactory(
|
||||
title="Verschaff dir einen Überblick",
|
||||
parent=circle,
|
||||
contents=[
|
||||
(
|
||||
"video",
|
||||
VideoBlockFactory(
|
||||
url="https://player.vimeo.com/video/772512710?h=30f912f15a",
|
||||
description="Willkommen im Lehrgang Versicherungsvermitler VBV",
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
LearningContentFactory(
|
||||
title="Mediathek",
|
||||
parent=circle,
|
||||
)
|
||||
|
||||
LearningSequenceFactory(
|
||||
title="Rechtsstreitigkeiten", parent=circle, icon="it-icon-ls-watch"
|
||||
)
|
||||
create_standard_learning_unit(
|
||||
"Rafael Fasel hat Ärger mit seinem Vermieter",
|
||||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V1",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/rafael-fasel-hat-arger-mit-seinem-vermieter-xapi-qI-Aqj8O/index.html",
|
||||
learning_unit_title="Terminvereinbarung, Vorbereitung und Gesprächseröffnung",
|
||||
)
|
||||
|
||||
create_learning_sequence_transfer(circle, title="Rechtsstreitigkeiten")
|
||||
|
||||
|
||||
def create_circle_reisen(lp, title="Reisen"):
|
||||
circle = CircleFactory(
|
||||
title=title,
|
||||
|
|
@ -481,7 +517,7 @@ def create_circle_reisen(lp, title="Reisen"):
|
|||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V1",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/emma-und-ayla-campen-durch-amerika-einstieg-xapi-_BfVBK8d/index.html",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/emma-und-ayla-campen-durch-amerika-einstieg-xapi-UnxjqXFB/index.html",
|
||||
learning_unit_title="Terminvereinbarung, Vorbereitung und Gesprächseröffnung",
|
||||
)
|
||||
|
||||
|
|
@ -491,7 +527,7 @@ def create_circle_reisen(lp, title="Reisen"):
|
|||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V2",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/emma-und-ayla-campen-durch-amerika-analyse-xapi-mtXA4uBz/index.html",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/emma-und-ayla-campen-durch-amerika-analyse-xapi-FZoZOP9y/index.html",
|
||||
learning_unit_title="Bedarfsanalyse, Ist- und Soll-Situation",
|
||||
)
|
||||
|
||||
|
|
@ -501,7 +537,7 @@ def create_circle_reisen(lp, title="Reisen"):
|
|||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V3",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/emma-und-ayla-campen-durch-amerika-losung-xapi-hn7GwUTn/index.html",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/emma-und-ayla-campen-durch-amerika-losung-xapi-DK5AsZ5M/index.html",
|
||||
learning_unit_title="Lösungsvorschlag erarbeiten und präsentieren",
|
||||
)
|
||||
|
||||
|
|
@ -511,7 +547,7 @@ def create_circle_reisen(lp, title="Reisen"):
|
|||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V4",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/emma-und-ayla-campen-durch-amerika-abschluss-xapi-Qv4X-yua/index.html",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/emma-und-ayla-campen-durch-amerika-abschluss-xapi--4t5XKAf/index.html",
|
||||
learning_unit_title="Gesprächszusammenfassung, Abschluss und Nachbereitung",
|
||||
)
|
||||
|
||||
|
|
@ -520,6 +556,76 @@ def create_circle_reisen(lp, title="Reisen"):
|
|||
)
|
||||
|
||||
|
||||
def create_circle_einkommenssicherung(lp, title="Einkommenssicherung"):
|
||||
circle = CircleFactory(
|
||||
title=title,
|
||||
parent=lp,
|
||||
)
|
||||
LearningSequenceFactory(title="Einführung", parent=circle, icon="it-icon-ls-start")
|
||||
LearningUnitFactory(title="Einführung", parent=circle)
|
||||
LearningContentFactory(
|
||||
title="Verschaff dir einen Überblick",
|
||||
parent=circle,
|
||||
contents=[
|
||||
(
|
||||
"video",
|
||||
VideoBlockFactory(
|
||||
url="https://player.vimeo.com/video/772512710?h=30f912f15a",
|
||||
description="Willkommen im Lehrgang Versicherungsvermitler VBV",
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
LearningContentFactory(
|
||||
title="Mediathek",
|
||||
parent=circle,
|
||||
)
|
||||
|
||||
LearningSequenceFactory(title="Einstieg", parent=circle, icon="it-icon-ls-watch")
|
||||
create_standard_learning_unit(
|
||||
"Patrizia und Marco sichern sich ab - Einstieg",
|
||||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V1",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/patrizia-marco-sichern-sich-ab-einstieg-xapi-jkH97GgC/index.html",
|
||||
learning_unit_title="Terminvereinbarung, Vorbereitung und Gesprächseröffnung",
|
||||
)
|
||||
|
||||
LearningSequenceFactory(title="Analyse", parent=circle, icon="it-icon-ls-watch")
|
||||
create_standard_learning_unit(
|
||||
"Patrizia und Marco sichern sich ab - Analyse",
|
||||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V2",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/patrizia-marco-sichern-sich-ab-analyse-xapi-MGcooCtm/index.html",
|
||||
learning_unit_title="Bedarfsanalyse, Ist- und Soll-Situation",
|
||||
)
|
||||
|
||||
LearningSequenceFactory(title="Lösung", parent=circle, icon="it-icon-ls-watch")
|
||||
create_standard_learning_unit(
|
||||
"Patrizia und Marco sichern sich ab - Lösung",
|
||||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V3",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/patrizia-marco-sichern-sich-ab-losung-xapi-nzoOdKIE/index.html",
|
||||
learning_unit_title="Lösungsvorschlag erarbeiten und präsentieren",
|
||||
)
|
||||
|
||||
LearningSequenceFactory(title="Abschluss", parent=circle, icon="it-icon-ls-watch")
|
||||
create_standard_learning_unit(
|
||||
"Patrizia und Marco sichern sich ab - Abschluss",
|
||||
parent=circle,
|
||||
category_name=title,
|
||||
competence_id="V4",
|
||||
wbt_url="https://s3.eu-central-1.amazonaws.com/myvbv-wbt.iterativ.ch/patrizia-marco-sichern-sich-ab-abschluss-xapi--lXKe6xt/index.html",
|
||||
learning_unit_title="Gesprächszusammenfassung, Abschluss und Nachbereitung",
|
||||
)
|
||||
|
||||
create_learning_sequence_transfer(
|
||||
circle, title="Einkommenssicherung", lc_praxis_title="Heirat: Was ändert sich?"
|
||||
)
|
||||
|
||||
|
||||
def create_circle_standard_small(
|
||||
lp, title, lc_title, lu_title=None, lc_praxis_title=None
|
||||
):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
<svg viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.99997 0.500065C5.87826 0.500065 3.84354 1.34291 2.34313 2.84319C0.842877 4.34358 0 6.37855 0 8.50003C0 10.6215 0.842844 12.6565 2.34313 14.1569C3.84351 15.6571 5.87849 16.5 7.99997 16.5C10.1214 16.5 12.1564 15.6572 13.6568 14.1569C15.1571 12.6565 15.9999 10.6215 15.9999 8.50003C15.9999 7.09568 15.6303 5.71622 14.9281 4.50002C14.226 3.28382 13.2161 2.27398 11.9999 1.57181C10.7837 0.869634 9.40425 0.5 7.9999 0.5L7.99997 0.500065ZM14.2315 5.64294H11.5087C11.1104 4.2353 10.4191 2.92763 9.48007 1.80587C10.514 2.03661 11.4806 2.50308 12.3047 3.16848C13.1288 3.83405 13.7883 4.68085 14.2315 5.64298V5.64294ZM7.96862 15.0885C6.92078 14.0448 6.13802 12.7653 5.68571 11.3573H10.3143C9.8611 12.7657 9.07743 14.0451 8.02857 15.0885C8.01059 15.1014 7.98648 15.1014 7.96862 15.0885H7.96862ZM5.39718 10.2144C5.18761 9.0811 5.18761 7.9191 5.39718 6.78581H10.6028C10.8123 7.9191 10.8123 9.0811 10.6028 10.2144H5.39718ZM1.1428 8.5001C1.1419 7.92178 1.21486 7.34564 1.35989 6.78581H4.23706C4.05058 7.92103 4.05058 9.07917 4.23706 10.2144H1.35989C1.21486 9.65455 1.1419 9.07842 1.1428 8.5001ZM7.99997 1.90023C8.01004 1.89628 8.02127 1.89628 8.03135 1.90023C9.08072 2.94729 9.86361 4.23086 10.3143 5.64294H5.68567C6.13886 4.23451 6.92254 2.95506 7.97139 1.91166C7.97917 1.90439 7.98938 1.90031 7.99997 1.90018L7.99997 1.90023ZM11.7629 6.78581H14.6401C14.9296 7.91032 14.9296 9.08988 14.6401 10.2144H11.7629C11.9494 9.07917 11.9494 7.92103 11.7629 6.78581ZM6.52012 1.80587C5.5821 2.92832 4.89089 4.23572 4.49154 5.64294H1.76869C2.21193 4.68082 2.87139 3.83402 3.69549 3.16845C4.51959 2.50301 5.48619 2.03656 6.52012 1.80583V1.80587ZM1.76876 11.3573H4.49161C4.88982 12.7649 5.58115 14.0726 6.52019 15.1943C5.48626 14.9636 4.51966 14.4971 3.69556 13.8317C2.87146 13.1661 2.21199 12.3193 1.76876 11.3572V11.3573ZM9.48308 15.1943C10.4199 14.0716 11.1101 12.7642 11.5087 11.3573H14.2316C13.7883 12.3194 13.1289 13.1662 12.3048 13.8317C11.4807 14.4972 10.5141 14.9636 9.48014 15.1944L9.48308 15.1943Z" fill="#0A0A0A"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
Loading…
Reference in New Issue