commit
4cf8a6fe27
1
Pipfile
1
Pipfile
|
|
@ -10,6 +10,7 @@ python_version = '3.6'
|
|||
awscli = "*"
|
||||
ipdb = "*"
|
||||
coverage = "*"
|
||||
django-silk = "*"
|
||||
|
||||
[packages]
|
||||
factory-boy = "==2.11.0"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "e7807798e8b5c39d7c1bc57d61520f2c888da08d2b6061f07758e00b490fdbd6"
|
||||
"sha256": "ca4f635dc983134e4569df2af8f0d73f488211bc2a97d11c194f76279f942977"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
|
@ -48,18 +48,18 @@
|
|||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:27e221d3868f35687807e5c920f7e8d4872f722f64196a7fd274a06ad65beec0",
|
||||
"sha256:8ff4e3d9e5d6a26dd7494afc68dc96afe6b7bda88130cca84cd58702d888ed27"
|
||||
"sha256:629ce3be236b6e0aed52358146eea9ffa7679d6cd1cc9b3e12332226270d6499",
|
||||
"sha256:b1351e62136fae29be8fcbb1c4890f1d72017d57e33051d435a8bf9f71212fde"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.11.10"
|
||||
"version": "==1.11.14"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:cf3144994191847e30ef76781af867009bdc233b3f1f4736615e5330687a891e",
|
||||
"sha256:f11ff8616f46ca04697df031e622c9ed50931b9d649d4e719f961e9d80771e8d"
|
||||
"sha256:34ad4d73e6bef5c8ad956c66354611628cdebd431fe2927261ed9c068b9cfb7a",
|
||||
"sha256:6570f2ba046956d5b548ab2346d32f713ecf8b8cb098a839d73fcf832ccfa223"
|
||||
],
|
||||
"version": "==1.14.10"
|
||||
"version": "==1.14.14"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
|
|
@ -535,10 +535,10 @@
|
|||
},
|
||||
"s3transfer": {
|
||||
"hashes": [
|
||||
"sha256:2525bae2a530195576da53671bae8ca8c55ee8e33bc2225a65e804476611ea5a",
|
||||
"sha256:4924e10451cc37901945806423d16c2c2040a6530645a614ed87e995ccec764c"
|
||||
"sha256:2482b4259524933a022d59da830f51bd746db62f047d6eb213f2f8855dcb8a13",
|
||||
"sha256:921a37e2aefc64145e7b73d50c71bb4f26f46e4c9f414dc648c6245ff92cf7db"
|
||||
],
|
||||
"version": "==0.3.2"
|
||||
"version": "==0.3.3"
|
||||
},
|
||||
"sendgrid": {
|
||||
"hashes": [
|
||||
|
|
@ -603,6 +603,7 @@
|
|||
"sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
|
||||
"sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
|
||||
],
|
||||
"markers": "python_version != '3.4'",
|
||||
"version": "==1.25.8"
|
||||
},
|
||||
"wagtail": {
|
||||
|
|
@ -652,13 +653,26 @@
|
|||
}
|
||||
},
|
||||
"develop": {
|
||||
"asgiref": {
|
||||
"hashes": [
|
||||
"sha256:7e06d934a7718bf3975acbf87780ba678957b87c7adc056f13b6215d610695a0",
|
||||
"sha256:ea448f92fc35a0ef4b1508f53a04c4670255a3f33d22a81c8fc9c872036adbe5"
|
||||
],
|
||||
"version": "==3.2.3"
|
||||
},
|
||||
"autopep8": {
|
||||
"hashes": [
|
||||
"sha256:0f592a0447acea0c2b0a9602be1e4e3d86db52badd2e3c84f0193bfd89fd3a43"
|
||||
],
|
||||
"version": "==1.5"
|
||||
},
|
||||
"awscli": {
|
||||
"hashes": [
|
||||
"sha256:4c49f085fb827ca1aeba5e6e5e39f6005110a0059b5c772aeb1d51c4f33c4028",
|
||||
"sha256:9459ac705c2a5d8724057492800c52084df714b624853eb3331087ecf8726a22"
|
||||
"sha256:2748af4e77728ced50d7d5bda0fa980449bd71eedff90ee643bee86ed4283d2f",
|
||||
"sha256:9118015f4bbab1c671d9c9927d07b6f7eadb7e1e8bbb2b06dc849c3de578d692"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.17.9"
|
||||
"version": "==1.17.14"
|
||||
},
|
||||
"backcall": {
|
||||
"hashes": [
|
||||
|
|
@ -669,17 +683,32 @@
|
|||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:cf3144994191847e30ef76781af867009bdc233b3f1f4736615e5330687a891e",
|
||||
"sha256:f11ff8616f46ca04697df031e622c9ed50931b9d649d4e719f961e9d80771e8d"
|
||||
"sha256:34ad4d73e6bef5c8ad956c66354611628cdebd431fe2927261ed9c068b9cfb7a",
|
||||
"sha256:6570f2ba046956d5b548ab2346d32f713ecf8b8cb098a839d73fcf832ccfa223"
|
||||
],
|
||||
"version": "==1.14.10"
|
||||
"version": "==1.14.14"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
|
||||
"sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
|
||||
],
|
||||
"version": "==2019.11.28"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
"sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d",
|
||||
"sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"
|
||||
"sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff",
|
||||
"sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"
|
||||
],
|
||||
"version": "==0.4.1"
|
||||
"markers": "python_version != '3.4'",
|
||||
"version": "==0.4.3"
|
||||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
|
|
@ -725,6 +754,22 @@
|
|||
],
|
||||
"version": "==4.4.1"
|
||||
},
|
||||
"django": {
|
||||
"hashes": [
|
||||
"sha256:48522428f4a285cf265af969f4744c5ebb027c7f41958ba48b639ace2068ffe7",
|
||||
"sha256:a794f7a2f4b7c928eecfbc4ebad03712ff27fb545abe269bf01aa8500781eb1c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.15"
|
||||
},
|
||||
"django-silk": {
|
||||
"hashes": [
|
||||
"sha256:9d5d66628689230288d1020de186b86e6f38583f611b5dd796ec988bb6a6333e",
|
||||
"sha256:b0033ec3713882a5abb8b3db2b4392a746b83ce164ab7be568f0eeec4ba78a98"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.0.0"
|
||||
},
|
||||
"docutils": {
|
||||
"hashes": [
|
||||
"sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0",
|
||||
|
|
@ -733,6 +778,19 @@
|
|||
],
|
||||
"version": "==0.15.2"
|
||||
},
|
||||
"gprof2dot": {
|
||||
"hashes": [
|
||||
"sha256:b43fe04ebb3dfe181a612bbfc69e90555b8957022ad6a466f0308ed9c7f22e99"
|
||||
],
|
||||
"version": "==2019.11.30"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||
],
|
||||
"version": "==2.8"
|
||||
},
|
||||
"ipdb": {
|
||||
"hashes": [
|
||||
"sha256:5d9a4a0e3b7027a158fc6f2929934341045b9c3b0b86ed5d7e84e409653f72fd"
|
||||
|
|
@ -762,6 +820,13 @@
|
|||
],
|
||||
"version": "==0.16.0"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
|
||||
"sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
|
||||
],
|
||||
"version": "==2.11.1"
|
||||
},
|
||||
"jmespath": {
|
||||
"hashes": [
|
||||
"sha256:3720a4b1bd659dd2eecad0666459b9788813e032b83e7ba58578e48254e0a0e6",
|
||||
|
|
@ -769,6 +834,44 @@
|
|||
],
|
||||
"version": "==0.9.4"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
|
||||
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
|
||||
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
|
||||
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
|
||||
"sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
|
||||
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
|
||||
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
|
||||
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
|
||||
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
|
||||
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
|
||||
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
|
||||
"sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
|
||||
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
|
||||
"sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
|
||||
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
|
||||
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
|
||||
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
|
||||
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
|
||||
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
|
||||
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
|
||||
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
|
||||
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
|
||||
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
|
||||
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
|
||||
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
|
||||
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
|
||||
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
|
||||
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
|
||||
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
|
||||
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
|
||||
"sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
|
||||
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
|
||||
"sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"parso": {
|
||||
"hashes": [
|
||||
"sha256:56b2105a80e9c4df49de85e125feb6be69f49920e121406f15e7acde6c9dfc57",
|
||||
|
|
@ -812,6 +915,13 @@
|
|||
],
|
||||
"version": "==0.4.8"
|
||||
},
|
||||
"pycodestyle": {
|
||||
"hashes": [
|
||||
"sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56",
|
||||
"sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"
|
||||
],
|
||||
"version": "==2.5.0"
|
||||
},
|
||||
"pygments": {
|
||||
"hashes": [
|
||||
"sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b",
|
||||
|
|
@ -826,6 +936,13 @@
|
|||
],
|
||||
"version": "==2.8.1"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
|
||||
"sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
|
||||
],
|
||||
"version": "==2019.3"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:0e7f69397d53155e55d10ff68fdfb2cf630a35e6daf65cf0bdeaf04f127c09dc",
|
||||
|
|
@ -842,6 +959,14 @@
|
|||
],
|
||||
"version": "==5.2"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
|
||||
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.22.0"
|
||||
},
|
||||
"rsa": {
|
||||
"hashes": [
|
||||
"sha256:25df4e10c263fb88b5ace923dd84bf9aa7f5019687b5e55382ffcdb8bede9db5",
|
||||
|
|
@ -851,10 +976,10 @@
|
|||
},
|
||||
"s3transfer": {
|
||||
"hashes": [
|
||||
"sha256:2525bae2a530195576da53671bae8ca8c55ee8e33bc2225a65e804476611ea5a",
|
||||
"sha256:4924e10451cc37901945806423d16c2c2040a6530645a614ed87e995ccec764c"
|
||||
"sha256:2482b4259524933a022d59da830f51bd746db62f047d6eb213f2f8855dcb8a13",
|
||||
"sha256:921a37e2aefc64145e7b73d50c71bb4f26f46e4c9f414dc648c6245ff92cf7db"
|
||||
],
|
||||
"version": "==0.3.2"
|
||||
"version": "==0.3.3"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
|
@ -863,6 +988,13 @@
|
|||
],
|
||||
"version": "==1.14.0"
|
||||
},
|
||||
"sqlparse": {
|
||||
"hashes": [
|
||||
"sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177",
|
||||
"sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"
|
||||
],
|
||||
"version": "==0.3.0"
|
||||
},
|
||||
"traitlets": {
|
||||
"hashes": [
|
||||
"sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44",
|
||||
|
|
@ -875,6 +1007,7 @@
|
|||
"sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
|
||||
"sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
|
||||
],
|
||||
"markers": "python_version != '3.4'",
|
||||
"version": "==1.25.8"
|
||||
},
|
||||
"wcwidth": {
|
||||
|
|
|
|||
|
|
@ -190,8 +190,5 @@ There is a schema.json in the fixtures folder. For now it has been generated onc
|
|||
To generate a new schema, use the management command
|
||||
|
||||
```
|
||||
python manage.py graphql_schema --schema api.schema.schema --out schema.json --indent 4
|
||||
python manage.py export_schema_for_cypress
|
||||
```
|
||||
|
||||
Then, remove the `data` property from the generated `schema.json`, so the `__schema` property is on the top level.
|
||||
Also remove the two objects with `"name": "__debug"` from the JSON file.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"me": {
|
||||
"id": "VXNlck5vZGU6NQ==",
|
||||
"pk": 5,
|
||||
"username": "rahel.cueni",
|
||||
"email": "rahel.cueni@skillbox.example",
|
||||
"firstName": "Rahel",
|
||||
"lastName": "Cueni",
|
||||
"avatarUrl": "",
|
||||
"isTeacher": false,
|
||||
"lastModule": {
|
||||
"id": "TW9kdWxlTm9kZToxNw==",
|
||||
"slug": "lohn-und-budget",
|
||||
"__typename": "ModuleNode"
|
||||
},
|
||||
"selectedClass": {
|
||||
"id": "U2Nob29sQ2xhc3NOb2RlOjI=",
|
||||
"__typename": "SchoolClassNode"
|
||||
},
|
||||
"schoolClasses": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"id": "U2Nob29sQ2xhc3NOb2RlOjE=",
|
||||
"name": "FLID2018a",
|
||||
"__typename": "SchoolClassNode"
|
||||
},
|
||||
"__typename": "SchoolClassNodeEdge"
|
||||
}
|
||||
],
|
||||
"__typename": "SchoolClassNodeConnection"
|
||||
},
|
||||
"__typename": "UserNode",
|
||||
"permissions": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"me": {
|
||||
"id": "VXNlck5vZGU6NQ==",
|
||||
"pk": 5,
|
||||
"username": "hansli",
|
||||
"email": "hansli@skillbox.example",
|
||||
"firstName": "Hansli",
|
||||
"lastName": "Alleini",
|
||||
"avatarUrl": "",
|
||||
"lastModule": null,
|
||||
"selectedClass": null,
|
||||
"schoolClasses": {
|
||||
"edges": [],
|
||||
"__typename": "SchoolClassNodeConnection"
|
||||
},
|
||||
"__typename": "UserNode",
|
||||
"permissions": []
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"me": {
|
||||
"id": "VXNlck5vZGU6Mg==",
|
||||
"isTeacher": false,
|
||||
"selectedClass": {
|
||||
"id": "U2Nob29sQ2xhc3NOb2RlOjE=",
|
||||
"name": "Moordale",
|
||||
"members": [
|
||||
{
|
||||
"id": "VXNlck5vZGU6Mw==",
|
||||
"firstName": "Otis",
|
||||
"lastName": "Milburn",
|
||||
"isTeacher": false,
|
||||
"active": true,
|
||||
"__typename": "ClassMemberNode"
|
||||
},
|
||||
{
|
||||
"id": "VXNlck5vZGU6NA==",
|
||||
"firstName": "Maeve",
|
||||
"lastName": "Wiley",
|
||||
"isTeacher": false,
|
||||
"active": true,
|
||||
"__typename": "ClassMemberNode"
|
||||
}
|
||||
],
|
||||
"__typename": "SchoolClassNode"
|
||||
},
|
||||
"__typename": "UserNode"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
describe('Survey', () => {
|
||||
describe('Bookmarks', () => {
|
||||
beforeEach(() => {
|
||||
// todo: mock all the graphql queries and mutations
|
||||
cy.exec("python ../server/manage.py prepare_bookmarks_for_cypress");
|
||||
|
|
@ -27,7 +27,6 @@ describe('Survey', () => {
|
|||
|
||||
cy.get('@interviewContent').within(() => {
|
||||
cy.get('.bookmark-actions__edit-note').click();
|
||||
|
||||
});
|
||||
|
||||
cy.get('[data-cy=bookmark-note]').within(() => {
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
describe('Change Password Page', () => {
|
||||
|
||||
const validNewPassword = 'Abcd1234!';
|
||||
const validOldPassword = 'test';
|
||||
const validationTooShort = 'Das neue Passwort muss mindestens 8 Zeichen lang sein';
|
||||
const validationErrorMsg = 'Das Passwort muss Grossbuchstaben, Zahlen und Sonderzeichen beinhalten';
|
||||
const validationOldWrongMsg = 'Die Eingabe ist falsch';
|
||||
|
||||
beforeEach(function () {
|
||||
// todo: mock all the graphql queries and mutations
|
||||
cy.clearCookies();
|
||||
cy.visit('/me/profile');
|
||||
cy.login('rahel.cueni', 'test');
|
||||
});
|
||||
|
||||
after(function () {
|
||||
cy.exec("python ../server/manage.py reset_testuser_password rahel.cueni");
|
||||
});
|
||||
|
||||
it('shows an empty form', () => {
|
||||
|
||||
cy.get('[data-cy=password-change-success]').should('not.exist');
|
||||
cy.get('[data-cy=old-password]').should('have.value', '');
|
||||
cy.get('[data-cy=new-password]').should('have.value', '');
|
||||
});
|
||||
|
||||
it('shows errors if old password is not entered', () => {
|
||||
cy.changePassword('', validNewPassword);
|
||||
cy.get('[data-cy=old-password-local-errors]').should('contain', 'Dein aktuelles Passwort fehlt')
|
||||
});
|
||||
|
||||
it('shows errors if new password is not entered', () => {
|
||||
cy.changePassword(validOldPassword, '');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', 'Dein neues Passwort fehlt')
|
||||
});
|
||||
|
||||
it('shows errors if new password is too short', () => {
|
||||
cy.changePassword(validOldPassword, 'Abc1!');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationTooShort)
|
||||
});
|
||||
|
||||
it('shows errors if new password has no uppercase letter', () => {
|
||||
cy.changePassword(validOldPassword, 'aabdddedddbc1!');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationErrorMsg)
|
||||
});
|
||||
|
||||
it('shows errors if new password has no lowercase letter', () => {
|
||||
cy.changePassword(validOldPassword, 'ABCDDD334551!');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationErrorMsg)
|
||||
});
|
||||
|
||||
it('shows errors if new password has no digit', () => {
|
||||
cy.changePassword(validOldPassword, 'AbcdEEDE!');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationErrorMsg)
|
||||
});
|
||||
|
||||
it('shows errors if new password has no special character', () => {
|
||||
cy.changePassword(validOldPassword, 'AbcdEEDE09877');
|
||||
cy.get('[data-cy=new-password-local-errors]').should('contain', validationErrorMsg)
|
||||
});
|
||||
|
||||
it('shows errors if old password does not match', () => {
|
||||
cy.changePassword('test12345', validNewPassword);
|
||||
cy.get('[data-cy=old-password-remote-errors]').should('contain', validationOldWrongMsg)
|
||||
});
|
||||
|
||||
it('shows success if change was successful', () => {
|
||||
cy.changePassword(validOldPassword, validNewPassword);
|
||||
cy.get('[data-cy=password-change-success]').should('contain', 'Dein Password wurde erfolgreich geändert.');
|
||||
cy.get('[data-cy=old-password]').should('have.value', '');
|
||||
cy.get('[data-cy=new-password]').should('have.value', '');
|
||||
});
|
||||
});
|
||||
|
|
@ -44,4 +44,22 @@ describe('The Login Page', () => {
|
|||
cy.get('body').contains('Berufliche Grundbildung');
|
||||
});
|
||||
|
||||
it.only('logs out then logs in again', () => {
|
||||
cy.viewport('macbook-15');
|
||||
cy.apolloLogin('rahel.cueni', 'test');
|
||||
cy.visit('/me/my-class');
|
||||
cy.get('[data-cy=header-user-widget]').should('exist').within(() => {
|
||||
cy.get('[data-cy=user-widget-avatar]').should('exist').click();
|
||||
});
|
||||
|
||||
cy.get('[data-cy=logout]').click();
|
||||
|
||||
cy.login('rahel.cueni', 'test');
|
||||
|
||||
cy.get('[data-cy=header-user-widget]').should('exist').within(() => {
|
||||
cy.get('[data-cy=user-widget-avatar]').should('exist').click();
|
||||
});
|
||||
|
||||
cy.get('.profile-sidebar').should('be.visible');
|
||||
});
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
const schema = require('../fixtures/schema.json');
|
||||
const me = require('../fixtures/me.new-student.json');
|
||||
|
||||
describe('New student', () => {
|
||||
it('shows "Enter Code" page and adds the user to a class', () => {
|
||||
|
||||
cy.server();
|
||||
|
||||
cy.mockGraphql({
|
||||
schema: schema,
|
||||
});
|
||||
|
||||
cy.apolloLogin('hansli', 'test');
|
||||
|
||||
const __typename = "SchoolClassNode";
|
||||
const name = "KF1A";
|
||||
const id = "U2Nob29sQ2xhc3NOb2RlOjI=";
|
||||
|
||||
cy.mockGraphqlOps({
|
||||
operations: {
|
||||
MeQuery: me,
|
||||
JoinClass: {
|
||||
joinClass: {
|
||||
success: true,
|
||||
schoolClass: {
|
||||
id,
|
||||
name,
|
||||
__typename
|
||||
}
|
||||
}
|
||||
},
|
||||
MySchoolClassQuery: {
|
||||
me: {
|
||||
...me.me,
|
||||
selectedClass: {
|
||||
__typename,
|
||||
name,
|
||||
id,
|
||||
members: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cy.visit('/');
|
||||
cy.get('[data-cy=join-class-title]').should('contain', 'Zugangscode');
|
||||
cy.get('[data-cy=input-class-code]').type('XXXX');
|
||||
cy.get('[data-cy=join-class]').click();
|
||||
cy.get('[data-cy=class-list-title]').should('contain', 'Klassenliste');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,320 @@
|
|||
const schema = require('../fixtures/schema.json');
|
||||
const me = require('../fixtures/me.join-class.json');
|
||||
const selectedClass = require('../fixtures/selected-school-class.json');
|
||||
|
||||
describe('Class Management', () => {
|
||||
beforeEach(() => {
|
||||
cy.server();
|
||||
|
||||
cy.mockGraphql({
|
||||
schema: schema,
|
||||
});
|
||||
|
||||
cy.viewport('macbook-15');
|
||||
cy.apolloLogin('rahel.cueni', 'test');
|
||||
|
||||
});
|
||||
|
||||
// fixme: cache misbehaves with mequery, but only for test
|
||||
// it('should join class', () => {
|
||||
// const name = 'KF1A';
|
||||
// const id = 'U2Nob29sQ2xhc3NOb2RlOjI=';
|
||||
// const __typename = 'SchoolClassNode';
|
||||
//
|
||||
// let localMe = {
|
||||
// ...me
|
||||
// };
|
||||
//
|
||||
// cy.mockGraphqlOps({
|
||||
// operations: {
|
||||
// MeQuery: localMe,
|
||||
// // JoinClass() {
|
||||
// // // fixme: is this necessary? the cache somehow does not seem to do anything for the MeQuery
|
||||
// // let schoolClass = {
|
||||
// // id,
|
||||
// // name,
|
||||
// // // __typename
|
||||
// // };
|
||||
// // // localMe.me.schoolClasses.edges.push({
|
||||
// // // node: schoolClass,
|
||||
// // // __typename: 'SchoolClassNodeEdge'
|
||||
// // // });
|
||||
// // return {
|
||||
// // joinClass: {
|
||||
// // success: true,
|
||||
// // schoolClass
|
||||
// // }
|
||||
// // }
|
||||
// // },
|
||||
// JoinClass: {
|
||||
// joinClass: {
|
||||
// success: true,
|
||||
// schoolClass: {
|
||||
// name,
|
||||
// id
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// MySchoolClassQuery: {
|
||||
// me: {
|
||||
// ...selectedClass.me,
|
||||
// selectedClass: {
|
||||
// __typename,
|
||||
// name,
|
||||
// id,
|
||||
// members: []
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// cy.visit('/me/profile');
|
||||
//
|
||||
// cy.get('[data-cy=header-user-widget]').within(() => {
|
||||
// cy.get('[data-cy=user-widget-avatar]').click();
|
||||
// });
|
||||
// //
|
||||
// cy.get('[data-cy=class-selection]').click();
|
||||
// cy.get('[data-cy=class-selection-entry]').should('have.length', 1);
|
||||
// cy.get('[data-cy=class-selection]').click();
|
||||
//
|
||||
// cy.get('[data-cy=join-class-link]').click();
|
||||
//
|
||||
// cy.get('[data-cy=input-class-code]').type('XXXX');
|
||||
// cy.get('[data-cy=join-class]').click();
|
||||
//
|
||||
// cy.get('[data-cy=school-class-name]').should('contain', name);
|
||||
// cy.get('[data-cy=current-class-name]').should('contain', name);
|
||||
//
|
||||
// cy.get('[data-cy=header-user-widget]').within(() => {
|
||||
// cy.get('[data-cy=user-widget-avatar]').click();
|
||||
// });
|
||||
//
|
||||
// cy.get('[data-cy=class-selection]').click();
|
||||
// cy.get('[data-cy=class-selection-entry]').should('have.length', 2);
|
||||
// //
|
||||
// });
|
||||
|
||||
it('should not be able to leave class', () => {
|
||||
cy.mockGraphqlOps({
|
||||
operations: {
|
||||
MeQuery: me,
|
||||
MySchoolClassQuery: selectedClass
|
||||
}
|
||||
});
|
||||
|
||||
cy.visit('/me/my-class');
|
||||
cy.get('[data-cy=school-class-member]').should('have.length', 2);
|
||||
cy.get('[data-cy=remove-from-class]').should('have.length', 0);
|
||||
cy.get('[data-cy=add-to-class]').should('have.length', 0);
|
||||
});
|
||||
|
||||
it('should leave and re-join class', () => {
|
||||
// todo: re-enable after the deactivation of users is re-enabled again
|
||||
|
||||
// const teacher = {
|
||||
// me: {
|
||||
// ...me.me,
|
||||
// isTeacher: true
|
||||
// }
|
||||
// };
|
||||
// const teacherSelectedClass = {
|
||||
// me: {
|
||||
// ...selectedClass.me,
|
||||
// isTeacher: true
|
||||
// }
|
||||
// };
|
||||
// cy.mockGraphqlOps({
|
||||
// operations: {
|
||||
// MeQuery: teacher,
|
||||
// AddRemoveMember: {
|
||||
// addRemoveMember: {
|
||||
// success: true
|
||||
// }
|
||||
// },
|
||||
// MySchoolClassQuery: teacherSelectedClass
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// cy.visit('/me/my-class');
|
||||
// cy.get('[data-cy=active-class-members-list]').within(() => {
|
||||
// cy.get('[data-cy=school-class-member]').should('have.length', 2)
|
||||
// });
|
||||
// cy.get('[data-cy=inactive-class-members-list]').should('not.exist');
|
||||
//
|
||||
// cy.get('[data-cy=remove-from-class]').first().click();
|
||||
//
|
||||
// cy.get('[data-cy=modal-save-button]').click();
|
||||
//
|
||||
// cy.get('[data-cy=active-class-members-list]').within(() => {
|
||||
// cy.get('[data-cy=school-class-member]').should('have.length', 1)
|
||||
// });
|
||||
// cy.get('[data-cy=inactive-class-members-list]').within(() => {
|
||||
// cy.get('[data-cy=school-class-member]').should('have.length', 1)
|
||||
// });
|
||||
//
|
||||
// cy.get('[data-cy=add-to-class]').first().click();
|
||||
//
|
||||
// cy.get('[data-cy=active-class-members-list]').within(() => {
|
||||
// cy.get('[data-cy=school-class-member]').should('have.length', 2)
|
||||
// });
|
||||
// cy.get('[data-cy=inactive-class-members-list]').should('not.exist');
|
||||
});
|
||||
|
||||
it('should display old classes', () => {
|
||||
let oldClasses = me.me.schoolClasses;
|
||||
let OldClassesQuery = {
|
||||
me: {
|
||||
...me.me,
|
||||
oldClasses
|
||||
},
|
||||
};
|
||||
|
||||
cy.mockGraphqlOps({
|
||||
operations: {
|
||||
MeQuery: me,
|
||||
OldClassesQuery
|
||||
}
|
||||
});
|
||||
|
||||
cy.visit('/me/old-classes');
|
||||
|
||||
cy.get('[data-cy=old-class-item]').should('have.length', 1);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('Teacher Class Management', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
cy.server();
|
||||
|
||||
cy.mockGraphql({
|
||||
schema: schema,
|
||||
});
|
||||
|
||||
cy.viewport('macbook-15');
|
||||
cy.apolloLogin('nico.zickgraf', 'test');
|
||||
|
||||
});
|
||||
|
||||
it('changes class name', () => {
|
||||
let className = 'Gotta have class';
|
||||
|
||||
let localMe = {
|
||||
me: {
|
||||
...me.me,
|
||||
isTeacher: true
|
||||
}
|
||||
};
|
||||
|
||||
cy.mockGraphqlOps({
|
||||
operations: {
|
||||
MeQuery: localMe,
|
||||
MySchoolClassQuery: {
|
||||
me: {
|
||||
...selectedClass.me,
|
||||
isTeacher: true
|
||||
}
|
||||
},
|
||||
UpdateSchoolClass: {
|
||||
updateSchoolClass: {
|
||||
success: true,
|
||||
schoolClass: {
|
||||
name: className,
|
||||
__typename: 'SchoolClassNode'
|
||||
},
|
||||
__typename: 'UpdateSchoolClassPayload'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cy.visit('/me/my-class');
|
||||
|
||||
cy.get('[data-cy=edit-class-name-link]').click();
|
||||
cy.get('[data-cy=edit-class-name-input] input').type('{selectall}{backspace}').type(className);
|
||||
cy.get('[data-cy=modal-save-button]').click();
|
||||
cy.get('[data-cy=school-class-name]').should('contain', className);
|
||||
});
|
||||
|
||||
// // fixme: cache misbehaves with mequery, but only for test
|
||||
//
|
||||
// it.only('creates a new class', () => {
|
||||
// const name = 'Moordale';
|
||||
// const id = 'U2Nob29sQ2xhc3NOb2RlOjI=';
|
||||
// const __typename = "SchoolClassNode";
|
||||
// let localMe = {
|
||||
// me: {
|
||||
// ...me.me,
|
||||
// isTeacher: true
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// cy.mockGraphqlOps({
|
||||
// operations: {
|
||||
// MeQuery: () => {
|
||||
// return localMe;
|
||||
// },
|
||||
// CreateSchoolClass() {
|
||||
// // fixme: is this necessary? the cache somehow does not seem to do anything for the MeQuery
|
||||
// let schoolClass = {
|
||||
// id,
|
||||
// name,
|
||||
// __typename
|
||||
// };
|
||||
// // localMe.me.schoolClasses.edges.push({
|
||||
// // node: schoolClass,
|
||||
// // __typename: 'SchoolClassNodeEdge'
|
||||
// // });
|
||||
// return {
|
||||
// createSchoolClass: {
|
||||
// success: true,
|
||||
// schoolClass
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// MySchoolClassQuery: {
|
||||
// me: {
|
||||
// ...selectedClass.me,
|
||||
// selectedClass: {
|
||||
// __typename,
|
||||
// name,
|
||||
// id,
|
||||
// members: []
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// cy.visit('/me/my-class');
|
||||
//
|
||||
// cy.get('h1').should('exist');
|
||||
//
|
||||
// cy.get('[data-cy=header-user-widget]').within(() => {
|
||||
// cy.get('[data-cy=user-widget-avatar]').click();
|
||||
// });
|
||||
//
|
||||
// cy.get('[data-cy=class-selection]').click();
|
||||
// cy.get('[data-cy=class-selection-entry]').should('have.length', 1);
|
||||
//
|
||||
//
|
||||
// cy.get('[data-cy=create-class-link]').click();
|
||||
//
|
||||
// cy.get('[data-cy=input-class-name]').type(name);
|
||||
//
|
||||
// cy.get('[data-cy=create-class]').click();
|
||||
//
|
||||
// cy.get('[data-cy=school-class-name]').should('contain', name);
|
||||
// cy.get('[data-cy=current-class-name]').should('contain', name);
|
||||
//
|
||||
// cy.get('[data-cy=header-user-widget]').within(() => {
|
||||
// cy.get('[data-cy=user-widget-avatar]').click();
|
||||
// });
|
||||
//
|
||||
// cy.get('[data-cy=class-selection]').click();
|
||||
// cy.get('[data-cy=class-selection-entry]').should('have.length', 2);
|
||||
// });
|
||||
});
|
||||
|
|
@ -10,7 +10,6 @@ describe('Survey', () => {
|
|||
});
|
||||
|
||||
cy.viewport('macbook-15');
|
||||
|
||||
cy.apolloLogin('rahel.cueni', 'test');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2460,7 +2460,7 @@
|
|||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
@ -2492,7 +2492,7 @@
|
|||
},
|
||||
"onetime": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
|
||||
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
|
||||
"dev": true
|
||||
},
|
||||
|
|
@ -2766,6 +2766,15 @@
|
|||
"@types/yargs": "^12.0.9"
|
||||
}
|
||||
},
|
||||
"@samverschueren/stream-to-observable": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz",
|
||||
"integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"any-observable": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"@types/babel__core": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.2.tgz",
|
||||
|
|
@ -3185,6 +3194,12 @@
|
|||
"integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=",
|
||||
"dev": true
|
||||
},
|
||||
"any-observable": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz",
|
||||
"integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==",
|
||||
"dev": true
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
|
||||
|
|
@ -5699,13 +5714,10 @@
|
|||
}
|
||||
},
|
||||
"cachedir": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/cachedir/-/cachedir-1.3.0.tgz",
|
||||
"integrity": "sha512-O1ji32oyON9laVPJL1IZ5bmwd2cB46VfpxkDequezH+15FDzzVddEyrGEeX4WusDSqKxdyFdDQDEG1yo1GoWkg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"os-homedir": "^1.0.1"
|
||||
}
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz",
|
||||
"integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==",
|
||||
"dev": true
|
||||
},
|
||||
"caffeine-eight": {
|
||||
"version": "2.5.9",
|
||||
|
|
@ -6066,9 +6078,9 @@
|
|||
"integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE="
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
|
||||
"integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
|
||||
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"cipher-base": {
|
||||
|
|
@ -6166,6 +6178,17 @@
|
|||
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz",
|
||||
"integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg=="
|
||||
},
|
||||
"cli-table3": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz",
|
||||
"integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colors": "^1.1.2",
|
||||
"object-assign": "^4.1.0",
|
||||
"string-width": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"cli-truncate": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
|
||||
|
|
@ -7009,61 +7032,65 @@
|
|||
"integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA="
|
||||
},
|
||||
"cypress": {
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-3.8.1.tgz",
|
||||
"integrity": "sha512-eLk5OpL/ZMDfQx9t7ZaDUAGVcvSOPTi7CG1tiUnu9BGk7caBiDhuFi3Tz/D5vWqH/Dl6Uh4X+Au4W+zh0xzbXw==",
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-4.2.0.tgz",
|
||||
"integrity": "sha512-8LdreL91S/QiTCLYLNbIjLL8Ht4fJmu/4HGLxUI20Tc7JSfqEfCmXELrRfuPT0kjosJwJJZacdSji9XSRkPKUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@cypress/listr-verbose-renderer": "0.4.1",
|
||||
"@cypress/xvfb": "1.2.4",
|
||||
"@types/sizzle": "2.3.2",
|
||||
"arch": "2.1.1",
|
||||
"bluebird": "3.5.0",
|
||||
"cachedir": "1.3.0",
|
||||
"bluebird": "3.7.2",
|
||||
"cachedir": "2.3.0",
|
||||
"chalk": "2.4.2",
|
||||
"check-more-types": "2.24.0",
|
||||
"commander": "2.15.1",
|
||||
"cli-table3": "0.5.1",
|
||||
"commander": "4.1.0",
|
||||
"common-tags": "1.8.0",
|
||||
"debug": "3.2.6",
|
||||
"execa": "0.10.0",
|
||||
"debug": "4.1.1",
|
||||
"eventemitter2": "4.1.2",
|
||||
"execa": "1.0.0",
|
||||
"executable": "4.1.1",
|
||||
"extract-zip": "1.6.7",
|
||||
"fs-extra": "5.0.0",
|
||||
"getos": "3.1.1",
|
||||
"is-ci": "1.2.1",
|
||||
"fs-extra": "8.1.0",
|
||||
"getos": "3.1.4",
|
||||
"is-ci": "2.0.0",
|
||||
"is-installed-globally": "0.1.0",
|
||||
"lazy-ass": "1.6.0",
|
||||
"listr": "0.12.0",
|
||||
"listr": "0.14.3",
|
||||
"lodash": "4.17.15",
|
||||
"log-symbols": "2.2.0",
|
||||
"minimist": "1.2.0",
|
||||
"log-symbols": "3.0.0",
|
||||
"minimist": "1.2.2",
|
||||
"moment": "2.24.0",
|
||||
"ramda": "0.24.1",
|
||||
"request": "2.88.0",
|
||||
"ospath": "1.2.2",
|
||||
"pretty-bytes": "5.3.0",
|
||||
"ramda": "0.26.1",
|
||||
"request": "github:cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16",
|
||||
"request-progress": "3.0.0",
|
||||
"supports-color": "5.5.0",
|
||||
"supports-color": "7.1.0",
|
||||
"tmp": "0.1.0",
|
||||
"untildify": "3.0.3",
|
||||
"untildify": "4.0.0",
|
||||
"url": "0.11.0",
|
||||
"yauzl": "2.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.10.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
||||
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
|
||||
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz",
|
||||
"integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=",
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
|
|
@ -7075,12 +7102,23 @@
|
|||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
||||
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz",
|
||||
"integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==",
|
||||
"dev": true
|
||||
},
|
||||
"cross-spawn": {
|
||||
|
|
@ -7097,22 +7135,22 @@
|
|||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
|
||||
"integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
|
||||
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^3.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
|
|
@ -7121,11 +7159,20 @@
|
|||
}
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
|
||||
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
|
||||
"dev": true
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
|
|
@ -7162,10 +7209,19 @@
|
|||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"dev": true
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz",
|
||||
"integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.2.tgz",
|
||||
"integrity": "sha512-rIqbOrKb8GJmx/5bc2M0QchhUouMXSpd1RTclXsB41JdL+VtnojfaJR+h7F9k18/4kHUsBFgk80Uk+q569vjPA==",
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
|
|
@ -7180,16 +7236,19 @@
|
|||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
|
||||
"dev": true
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||
"version": "github:cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16",
|
||||
"from": "github:cypress-io/request#b5af0d1fa47eec97ba980cde90a13e69a2afcd16",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
|
|
@ -7199,7 +7258,7 @@
|
|||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.0",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
|
|
@ -7209,7 +7268,7 @@
|
|||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.4.3",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
|
|
@ -7224,12 +7283,20 @@
|
|||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
|
||||
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tmp": {
|
||||
|
|
@ -7242,13 +7309,13 @@
|
|||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8280,6 +8347,12 @@
|
|||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"eventemitter2": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-4.1.2.tgz",
|
||||
"integrity": "sha1-DhqEd6+CGm7zmVsxG/dMI6UkfxU=",
|
||||
"dev": true
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
|
||||
|
|
@ -8988,16 +9061,22 @@
|
|||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
|
||||
"integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"graceful-fs": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
|
||||
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
|
|
@ -9606,12 +9685,20 @@
|
|||
"integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
|
||||
},
|
||||
"getos": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/getos/-/getos-3.1.1.tgz",
|
||||
"integrity": "sha512-oUP1rnEhAr97rkitiszGP9EgDVYnmchgFzfqRzSkgtfv7ai6tEi7Ko8GgjNXts7VLWEqrTWyhsOKLe5C5b/Zkg==",
|
||||
"version": "3.1.4",
|
||||
"resolved": "https://registry.npmjs.org/getos/-/getos-3.1.4.tgz",
|
||||
"integrity": "sha512-UORPzguEB/7UG5hqiZai8f0vQ7hzynMQyJLxStoQ8dPGAcmgsfXOPA4iE/fGtweHYkK+z4zc9V0g+CIFRf5HYw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "2.6.1"
|
||||
"async": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
|
||||
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
|
|
@ -10507,12 +10594,12 @@
|
|||
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
|
||||
},
|
||||
"is-ci": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
|
||||
"integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
|
||||
"integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ci-info": "^1.5.0"
|
||||
"ci-info": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-data-descriptor": {
|
||||
|
|
@ -10638,6 +10725,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"is-observable": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz",
|
||||
"integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"symbol-observable": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
|
||||
|
|
@ -11540,7 +11636,8 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
|
@ -11568,6 +11665,7 @@
|
|||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -11582,7 +11680,8 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
|
|
@ -11593,7 +11692,8 @@
|
|||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
|
@ -11710,7 +11810,8 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
|
@ -11722,6 +11823,7 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
|
@ -11736,6 +11838,7 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
|
@ -11743,12 +11846,14 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
|
@ -11767,6 +11872,7 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
|
@ -11847,7 +11953,8 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
|
@ -11859,6 +11966,7 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -11944,7 +12052,8 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
|
@ -11980,6 +12089,7 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
|
@ -11999,6 +12109,7 @@
|
|||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
|
@ -12042,12 +12153,14 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -13167,114 +13280,26 @@
|
|||
}
|
||||
},
|
||||
"listr": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz",
|
||||
"integrity": "sha1-a84sD1YD+klYDqF81qAMwOX6RRo=",
|
||||
"version": "0.14.3",
|
||||
"resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz",
|
||||
"integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^1.1.3",
|
||||
"cli-truncate": "^0.2.1",
|
||||
"figures": "^1.7.0",
|
||||
"indent-string": "^2.1.0",
|
||||
"@samverschueren/stream-to-observable": "^0.3.0",
|
||||
"is-observable": "^1.1.0",
|
||||
"is-promise": "^2.1.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"listr-silent-renderer": "^1.1.1",
|
||||
"listr-update-renderer": "^0.2.0",
|
||||
"listr-verbose-renderer": "^0.4.0",
|
||||
"log-symbols": "^1.0.2",
|
||||
"log-update": "^1.0.2",
|
||||
"ora": "^0.2.3",
|
||||
"p-map": "^1.1.1",
|
||||
"rxjs": "^5.0.0-beta.11",
|
||||
"stream-to-observable": "^0.1.0",
|
||||
"strip-ansi": "^3.0.1"
|
||||
"listr-update-renderer": "^0.5.0",
|
||||
"listr-verbose-renderer": "^0.5.0",
|
||||
"p-map": "^2.0.0",
|
||||
"rxjs": "^6.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
|
||||
"integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"restore-cursor": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"cli-spinners": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
|
||||
"integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=",
|
||||
"dev": true
|
||||
},
|
||||
"figures": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
|
||||
"integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"object-assign": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
|
||||
"integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"onetime": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
|
||||
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
|
||||
"dev": true
|
||||
},
|
||||
"ora": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "http://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
|
||||
"integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^1.1.1",
|
||||
"cli-cursor": "^1.0.2",
|
||||
"cli-spinners": "^0.1.2",
|
||||
"object-assign": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
|
||||
"integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"exit-hook": "^1.0.0",
|
||||
"onetime": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||
"p-map": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
|
||||
"integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
|
@ -13286,9 +13311,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"listr-update-renderer": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz",
|
||||
"integrity": "sha1-yoDhd5tOcCZoB+ju0a1qvjmFUPk=",
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz",
|
||||
"integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^1.1.3",
|
||||
|
|
@ -13297,7 +13322,7 @@
|
|||
"figures": "^1.7.0",
|
||||
"indent-string": "^3.0.0",
|
||||
"log-symbols": "^1.0.2",
|
||||
"log-update": "^1.0.2",
|
||||
"log-update": "^2.3.0",
|
||||
"strip-ansi": "^3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
@ -13309,7 +13334,7 @@
|
|||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
@ -13354,77 +13379,15 @@
|
|||
}
|
||||
},
|
||||
"listr-verbose-renderer": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz",
|
||||
"integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=",
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz",
|
||||
"integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^1.1.3",
|
||||
"cli-cursor": "^1.0.2",
|
||||
"chalk": "^2.4.1",
|
||||
"cli-cursor": "^2.1.0",
|
||||
"date-fns": "^1.27.2",
|
||||
"figures": "^1.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
|
||||
"integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"restore-cursor": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"figures": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
|
||||
"integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"object-assign": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"onetime": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
|
||||
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
|
||||
"dev": true
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
|
||||
"integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"exit-hook": "^1.0.0",
|
||||
"onetime": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||
"dev": true
|
||||
}
|
||||
"figures": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"load-json-file": {
|
||||
|
|
@ -13649,44 +13612,39 @@
|
|||
}
|
||||
},
|
||||
"log-update": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz",
|
||||
"integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=",
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz",
|
||||
"integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "^1.0.0",
|
||||
"cli-cursor": "^1.0.2"
|
||||
"ansi-escapes": "^3.0.0",
|
||||
"cli-cursor": "^2.0.0",
|
||||
"wrap-ansi": "^3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-escapes": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
|
||||
"integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
|
||||
"ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||
"dev": true
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz",
|
||||
"integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=",
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"restore-cursor": "^1.0.1"
|
||||
"ansi-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"onetime": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
|
||||
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
|
||||
"dev": true
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
|
||||
"integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=",
|
||||
"wrap-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"exit-hook": "^1.0.0",
|
||||
"onetime": "^1.0.0"
|
||||
"string-width": "^2.1.1",
|
||||
"strip-ansi": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14917,6 +14875,12 @@
|
|||
"os-tmpdir": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ospath": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
|
||||
"integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=",
|
||||
"dev": true
|
||||
},
|
||||
"p-defer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
|
||||
|
|
@ -17089,6 +17053,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"pretty-bytes": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz",
|
||||
"integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-error": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz",
|
||||
|
|
@ -17255,9 +17225,9 @@
|
|||
"integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw=="
|
||||
},
|
||||
"ramda": {
|
||||
"version": "0.24.1",
|
||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz",
|
||||
"integrity": "sha1-w7d1UZfzW43DUCIoJixMkd22uFc=",
|
||||
"version": "0.26.1",
|
||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz",
|
||||
"integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==",
|
||||
"dev": true
|
||||
},
|
||||
"randomatic": {
|
||||
|
|
@ -17874,20 +17844,12 @@
|
|||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "5.5.12",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
|
||||
"integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
|
||||
"version": "6.5.4",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
|
||||
"integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"symbol-observable": "1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"symbol-observable": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
|
||||
"integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
|
||||
"dev": true
|
||||
}
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
|
|
@ -18678,12 +18640,6 @@
|
|||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
|
||||
"integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
|
||||
},
|
||||
"stream-to-observable": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz",
|
||||
"integrity": "sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4=",
|
||||
"dev": true
|
||||
},
|
||||
"strict-uri-encode": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||
|
|
@ -19456,9 +19412,9 @@
|
|||
}
|
||||
},
|
||||
"untildify": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz",
|
||||
"integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
|
||||
"integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
|
||||
"dev": true
|
||||
},
|
||||
"upath": {
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@
|
|||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-jest": "^24.8.0",
|
||||
"canvas": "^2.5.0",
|
||||
"cypress": "3.8.1",
|
||||
"cypress": "^4.2.0",
|
||||
"jest": "^24.8.0",
|
||||
"jest-serializer-vue": "^2.0.2",
|
||||
"jest-transform-graphql": "^2.1.0",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div :class="{'no-scroll': showModal || showMobileNavigation}" class="app" id="app">
|
||||
<component :is="showModalDeprecated" v-if="showModalDeprecated"></component>
|
||||
<component :is="showModal" v-if="showModal"></component>
|
||||
<component :is="layout"></component>
|
||||
<mobile-navigation v-if="showMobileNavigation"></mobile-navigation>
|
||||
|
|
@ -18,16 +19,16 @@
|
|||
import EditContentBlockWizard from '@/components/content-block-form/EditContentBlockWizard';
|
||||
import NewRoomEntryWizard from '@/components/rooms/room-entries/NewRoomEntryWizard';
|
||||
import EditRoomEntryWizard from '@/components/rooms/room-entries/EditRoomEntryWizard';
|
||||
import NewObjectiveGroupWizard from '@/components/objective-groups/NewObjectiveGroupWizard';
|
||||
import EditObjectiveGroupWizard from '@/components/objective-groups/EditObjectiveGroupWizard';
|
||||
import NewProjectEntryWizard from '@/components/portfolio/NewProjectEntryWizard';
|
||||
import EditProjectEntryWizard from '@/components/portfolio/EditProjectEntryWizard';
|
||||
import NewObjectiveWizard from '@/components/objective-groups/NewObjectiveWizard';
|
||||
import NewNoteWizard from '@/components/notes/NewNoteWizard';
|
||||
import EditNoteWizard from '@/components/notes/EditNoteWizard';
|
||||
import EditClassNameWizard from '@/components/school-class/EditClassNameWizard';
|
||||
import FullscreenImage from '@/components/FullscreenImage';
|
||||
import FullscreenInfographic from '@/components/FullscreenInfographic';
|
||||
import FullscreenVideo from '@/components/FullscreenVideo';
|
||||
import DeactivatePerson from '@/components/profile/DeactivatePerson';
|
||||
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
|
|
@ -46,24 +47,29 @@
|
|||
EditContentBlockWizard,
|
||||
NewRoomEntryWizard,
|
||||
EditRoomEntryWizard,
|
||||
// todo: remove
|
||||
NewObjectiveGroupWizard,
|
||||
EditObjectiveGroupWizard,
|
||||
NewProjectEntryWizard,
|
||||
EditProjectEntryWizard,
|
||||
NewObjectiveWizard,
|
||||
NewNoteWizard,
|
||||
EditNoteWizard,
|
||||
EditClassNameWizard,
|
||||
FullscreenImage,
|
||||
FullscreenInfographic,
|
||||
FullscreenVideo
|
||||
FullscreenVideo,
|
||||
DeactivatePerson
|
||||
},
|
||||
|
||||
computed: {
|
||||
layout() {
|
||||
return (this.$route.meta.layout || 'default') + '-layout';
|
||||
},
|
||||
...mapGetters(['showModal', 'showMobileNavigation'])
|
||||
...mapGetters({
|
||||
showModalDeprecated: 'showModal', // don't use this any more todo: remove this
|
||||
showMobileNavigation: 'showMobileNavigation'
|
||||
}),
|
||||
showModal() {
|
||||
return this.$modal.state.component;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
<template>
|
||||
<div class="add-objective-group-button" @click="addObjectiveGroup()">
|
||||
<add-icon class="add-objective-group-button__icon"></add-icon>
|
||||
<div class="add-objective-group-button__text">Zusätzlich Lernziele für «{{typeDescription}}» erfassen</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AddIcon from '@/components/icons/AddIcon';
|
||||
|
||||
export default {
|
||||
props: ['type', 'module'],
|
||||
|
||||
components: {
|
||||
AddIcon
|
||||
},
|
||||
|
||||
computed: {
|
||||
typeDescription() {
|
||||
if (this.type === 'society') {
|
||||
return 'Gesellschaft'
|
||||
}
|
||||
return 'Sprache & Kommunikation';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addObjectiveGroup() {
|
||||
this.$store.dispatch('addObjectiveGroup', {
|
||||
module: this.module,
|
||||
type: this.type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.add-objective-group-button {
|
||||
display: none;
|
||||
grid-template-columns: 45px auto;
|
||||
align-items: center;
|
||||
margin-top: -20px;
|
||||
margin-bottom: 35px;
|
||||
cursor: pointer;
|
||||
|
||||
@include desktop {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
fill: $color-silver-dark;
|
||||
}
|
||||
|
||||
&__text {
|
||||
color: $color-silver-dark;
|
||||
font-family: $sans-serif-font-family;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
<template>
|
||||
<div class="class-selection" v-if="isTeacher">
|
||||
<div class="class-selection__selected-class selected-class" @click="showPopover = !showPopover">
|
||||
<p class="selected-class__text">Klasse: {{currentClassSelection.name}}</p>
|
||||
</div>
|
||||
<widget-popover v-if="showPopover"
|
||||
@hide-me="showPopover = false"
|
||||
:mobile="mobile"
|
||||
class="class-selection__popover">
|
||||
<li class="popover-links__link popover-links__link--large" v-for="schoolClass in schoolClasses"
|
||||
:key="schoolClass.id"
|
||||
:label="schoolClass.name"
|
||||
:item="schoolClass"
|
||||
@click="updateFilter(schoolClass)">
|
||||
{{schoolClass.name}}
|
||||
</li>
|
||||
</widget-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetPopover from '@/components/WidgetPopover';
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import UPDATE_USER_SETTING from '@/graphql/gql/mutations/updateUserSetting.gql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WidgetPopover
|
||||
},
|
||||
|
||||
props: {
|
||||
mobile: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: {
|
||||
query: ME_QUERY
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
me: {
|
||||
selectedClass: {
|
||||
id: ''
|
||||
},
|
||||
permissions: []
|
||||
},
|
||||
showPopover: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateFilter(selectedClass) {
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_USER_SETTING,
|
||||
variables: {
|
||||
input: {
|
||||
id: selectedClass.id
|
||||
}
|
||||
},
|
||||
update(store, data) {
|
||||
let meData = store.readQuery({query: ME_QUERY});
|
||||
meData.me.selectedClass = selectedClass
|
||||
store.writeQuery({query: ME_QUERY, data: meData});
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log('fail', error)
|
||||
});
|
||||
this.showPopover = false;
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentClassSelection() {
|
||||
let currentClass = this.schoolClasses.find(schoolClass => {
|
||||
return schoolClass.id === this.me.selectedClass.id
|
||||
})
|
||||
return currentClass || this.schoolClasses[0];
|
||||
},
|
||||
schoolClasses() {
|
||||
return this.$getRidOfEdges(this.me.schoolClasses);
|
||||
},
|
||||
isTeacher() {
|
||||
return this.me.permissions.includes('users.can_manage_school_class_content');
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.class-selection {
|
||||
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-right: $large-spacing;
|
||||
|
||||
&__popover {
|
||||
white-space: nowrap;
|
||||
top: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.selected-class {
|
||||
&__text {
|
||||
line-height: $large-spacing;
|
||||
@include regular-text;
|
||||
color: $color-silver-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.popover-links__link {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -59,15 +59,8 @@
|
|||
display: flex;
|
||||
|
||||
&__link {
|
||||
font-size: 1.0625rem;
|
||||
padding: 0 24px;
|
||||
font-family: $sans-serif-font-family;
|
||||
font-weight: $font-weight-regular;
|
||||
color: $color-silver-dark;
|
||||
|
||||
&--active {
|
||||
color: $color-brand;
|
||||
}
|
||||
@include default-link;
|
||||
}
|
||||
|
||||
$parent: &;
|
||||
|
|
@ -96,9 +89,11 @@
|
|||
order: 3;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
order: 2;
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
<template>
|
||||
<header class="header-bar">
|
||||
<top-navigation></top-navigation>
|
||||
<content-navigation></content-navigation>
|
||||
<router-link to="/" class="header-bar__logo" data-cy="home-link">
|
||||
<logo></logo>
|
||||
</router-link>
|
||||
<div class="user-header">
|
||||
<class-selection-widget />
|
||||
<user-widget v-bind="me"></user-widget>
|
||||
<a class="user-header__sidebar-link" @click="openSidebar()"><current-class class="user-header__current-class"/></a>
|
||||
|
||||
<user-widget data-cy="header-user-widget" v-bind="me"></user-widget>
|
||||
</div>
|
||||
<book-navigation v-if="showSubnavigation">
|
||||
</book-navigation>
|
||||
|
|
@ -14,23 +15,24 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import TopNavigation from '@/components/TopNavigation.vue';
|
||||
import ContentNavigation from '@/components/ContentNavigation.vue';
|
||||
import BookNavigation from '@/components/book-navigation/BookNavigation';
|
||||
import UserWidget from '@/components/UserWidget.vue';
|
||||
import LogoutWidget from '@/components/LogoutWidget.vue';
|
||||
import Logo from '@/components/icons/Logo';
|
||||
import ClassSelectionWidget from '@/components/ClassSelectionWidget';
|
||||
import CurrentClass from '@/components/school-class/CurrentClass';
|
||||
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import openSidebar from '@/mixins/open-sidebar';
|
||||
import me from '@/mixins/me';
|
||||
|
||||
export default {
|
||||
mixins: [openSidebar, me],
|
||||
|
||||
components: {
|
||||
TopNavigation,
|
||||
ContentNavigation,
|
||||
UserWidget,
|
||||
LogoutWidget,
|
||||
BookNavigation,
|
||||
Logo,
|
||||
ClassSelectionWidget
|
||||
CurrentClass
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
@ -38,18 +40,6 @@
|
|||
return this.$route.meta.subnavigation;
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
me: {}
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: {
|
||||
query: ME_QUERY,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -58,7 +48,8 @@
|
|||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.header-bar {
|
||||
display: -ms-grid;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@supports (display: grid) {
|
||||
display: none;
|
||||
|
||||
|
|
@ -67,7 +58,7 @@
|
|||
}
|
||||
}
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
justify-content: space-between;
|
||||
background-color: $color-white;
|
||||
grid-auto-rows: 50px;
|
||||
width: 100%;
|
||||
|
|
@ -127,5 +118,13 @@
|
|||
|
||||
.user-header {
|
||||
display: flex;
|
||||
|
||||
&__current-class {
|
||||
margin-right: $large-spacing;
|
||||
}
|
||||
|
||||
&__sidebar-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="logout-widget">
|
||||
<button class="logout-widget__logout" data-cy="logout" @click="logout()">Logout</button>
|
||||
<a class="logout-widget__logout" data-cy="logout" @click="logout()">Logout</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -8,7 +8,6 @@
|
|||
import LOGOUT_MUTATION from '@/graphql/gql/mutations/logoutUser.gql';
|
||||
|
||||
export default {
|
||||
|
||||
methods: {
|
||||
logout() {
|
||||
this.$apollo.mutate({
|
||||
|
|
@ -23,6 +22,7 @@
|
|||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.logout-widget {
|
||||
color: $color-silver-dark;
|
||||
|
|
@ -30,15 +30,8 @@
|
|||
align-items: center;
|
||||
|
||||
&__logout {
|
||||
font-family: $sans-serif-font-family;
|
||||
line-height: 16px;
|
||||
margin: 0 15px 0 $large-spacing;
|
||||
background: none;
|
||||
color: inherit;
|
||||
border: none;
|
||||
padding: 0;
|
||||
@include regular-text;
|
||||
cursor: pointer;
|
||||
outline: inherit;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,31 @@
|
|||
<template>
|
||||
<div class="mobile-header">
|
||||
<router-link to="/" data-cy="mobile-home-link">
|
||||
<logo></logo>
|
||||
</router-link>
|
||||
|
||||
<a @click="showMobileNavigation">
|
||||
<hamburger class="mobile-header__hamburger"></hamburger>
|
||||
</a>
|
||||
|
||||
<router-link to="/" data-cy="mobile-home-link">
|
||||
<logo></logo>
|
||||
</router-link>
|
||||
|
||||
<user-widget v-bind="me"></user-widget>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Logo from '@/components/icons/Logo';
|
||||
import Hamburger from '@/components/icons/Hamburger';
|
||||
import UserWidget from '@/components/UserWidget';
|
||||
|
||||
import me from '@/mixins/me';
|
||||
|
||||
export default {
|
||||
mixins: [me],
|
||||
|
||||
components: {
|
||||
Logo,
|
||||
Hamburger
|
||||
Hamburger,
|
||||
UserWidget
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -1,36 +1,17 @@
|
|||
<template>
|
||||
<div class="user-widget" :class="{'user-widget--is-profile': isProfile}">
|
||||
<div class="user-widget__avatar" @click="toggleShowPopover()">
|
||||
<div class="user-widget__avatar" data-cy="user-widget-avatar" @click="openSidebar()">
|
||||
<avatar :avatar-url="avatarUrl" :icon-highlighted="isProfile"/>
|
||||
</div>
|
||||
<widget-popover v-if="showPopover && showMenu"
|
||||
@hide-me="showPopover = false"
|
||||
:mobile="mobile"
|
||||
class="user-widget__popover ">
|
||||
<li class="popover-links__link popover-links__link--large popover-links__link--emph">{{firstName}} {{lastName}}
|
||||
</li>
|
||||
<li class="popover-links__link popover-links__link--large">
|
||||
<router-link to="/me/activity" @click="toggleShowPopover()">Aktivität</router-link>
|
||||
</li>
|
||||
<li class="popover-links__link popover-links__link--large" @click="toggleShowPopover()">
|
||||
<router-link to="/me/profile">Profil</router-link>
|
||||
</li>
|
||||
<li class="popover-links__link popover-links__link--large" @click="toggleShowPopover()">
|
||||
<router-link to="/me/myclasses">Klassenliste</router-link>
|
||||
</li>
|
||||
<li class="popover-links__link popover-links__link--large" data-cy="logout" @click="logout()">
|
||||
<a>Logout</a>
|
||||
</li>
|
||||
</widget-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LOGOUT_MUTATION from '@/graphql/gql/mutations/logoutUser.gql';
|
||||
import Avatar from '@/components/profile/Avatar';
|
||||
import WidgetPopover from '@/components/WidgetPopover';
|
||||
import openSidebar from '@/mixins/open-sidebar';
|
||||
|
||||
export default {
|
||||
// todo: clean up unneeded props
|
||||
props: {
|
||||
firstName: {
|
||||
type: String
|
||||
|
|
@ -51,31 +32,10 @@
|
|||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showPopover: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleShowPopover() {
|
||||
if (this.showMenu) {
|
||||
this.showPopover = !this.showPopover;
|
||||
}
|
||||
},
|
||||
logout() {
|
||||
this.$apollo.mutate({
|
||||
mutation: LOGOUT_MUTATION,
|
||||
}).then(({data}) => {
|
||||
if (data.logout.success) {
|
||||
location.replace('/logout')
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mixins: [openSidebar],
|
||||
|
||||
components: {
|
||||
Avatar, WidgetPopover
|
||||
Avatar
|
||||
},
|
||||
computed: {
|
||||
isProfile() {
|
||||
|
|
|
|||
|
|
@ -18,51 +18,5 @@
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.widget-popover {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: $color-white;
|
||||
padding: 20px;
|
||||
z-index: 100;
|
||||
@include widget-shadow;
|
||||
|
||||
&--mobile {
|
||||
left: 0;
|
||||
right: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.popover-links {
|
||||
|
||||
list-style: none;
|
||||
display: grid;
|
||||
|
||||
&__link {
|
||||
& > a {
|
||||
display: inline-block;
|
||||
color: $color-silver-dark;
|
||||
font-family: $sans-serif-font-family;
|
||||
font-size: toRem(14px);
|
||||
line-height: 1.5;
|
||||
padding: 5px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&--large {
|
||||
line-height: 40px;
|
||||
& > a, & {
|
||||
@include small-text;
|
||||
}
|
||||
}
|
||||
&--emph {
|
||||
@include regular-text;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,32 +1,25 @@
|
|||
<template>
|
||||
<div class="mobile-navigation">
|
||||
<top-navigation class="mobile-navigation__main" :mobile="true"></top-navigation>
|
||||
<content-navigation class="mobile-navigation__main" :mobile="true"></content-navigation>
|
||||
<div class="mobile-navigation__close-button" @click="hideMobileNavigation">
|
||||
<cross class="mobile-navigation__close-icon"></cross>
|
||||
</div>
|
||||
<div class="mobile-navigation__subnavigation"></div>
|
||||
<div class="mobile-navigation__secondary">
|
||||
<class-selection-widget :mobile="true" />
|
||||
<user-widget class="mobile-navigation__user-widget" v-bind="me" :mobile="true"></user-widget>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cross from '@/components/icons/Cross';
|
||||
import UserWidget from '@/components/UserWidget';
|
||||
import LogoutWidget from '@/components/LogoutWidget';
|
||||
import TopNavigation from '@/components/TopNavigation';
|
||||
import ClassSelectionWidget from '@/components/ClassSelectionWidget';
|
||||
import ContentNavigation from '@/components/ContentNavigation';
|
||||
import ClassSelectionWidget from '@/components/school-class/ClassSelectionWidget';
|
||||
|
||||
import {meQuery} from '@/graphql/queries';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TopNavigation,
|
||||
ContentNavigation,
|
||||
Cross,
|
||||
UserWidget,
|
||||
LogoutWidget,
|
||||
ClassSelectionWidget
|
||||
},
|
||||
|
||||
|
|
@ -101,20 +94,5 @@
|
|||
opacity: 0.5;
|
||||
fill: $color-white;
|
||||
}
|
||||
|
||||
&__secondary {
|
||||
grid-area: s;
|
||||
padding: $medium-spacing;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__user-widget {
|
||||
margin-bottom: $small-spacing;
|
||||
}
|
||||
|
||||
&__logout-widget {
|
||||
margin-left: -$large-spacing;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -42,30 +42,3 @@
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.book-subnavigation {
|
||||
&__item {
|
||||
@include small-text;
|
||||
margin-bottom: $small-spacing;
|
||||
cursor: pointer;
|
||||
|
||||
color: $color-silver-dark;
|
||||
|
||||
&--mobile {
|
||||
color: $color-white;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&--active {
|
||||
color: $color-brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
import ThinglinkBlock from '@/components/content-blocks/ThinglinkBlock';
|
||||
import GeniallyBlock from '@/components/content-blocks/GeniallyBlock';
|
||||
import SubtitleBlock from '@/components/content-blocks/SubtitleBlock';
|
||||
import SectionTitleBlock from '@/components/content-blocks/SectionTitleBlock';
|
||||
import ContentListBlock from '@/components/content-blocks/ContentListBlock';
|
||||
import ModuleRoomSlug from '@/components/content-blocks/ModuleRoomSlug';
|
||||
import Assignment from '@/components/content-blocks/assignment/Assignment';
|
||||
|
|
@ -56,6 +57,7 @@
|
|||
'infogram_block': InfogramBlock,
|
||||
'genially_block': GeniallyBlock,
|
||||
'subtitle': SubtitleBlock,
|
||||
'section_title': SectionTitleBlock,
|
||||
'content_list': ContentListBlock,
|
||||
'module_room_slug': ModuleRoomSlug,
|
||||
'thinglink_block': ThinglinkBlock,
|
||||
|
|
@ -102,6 +104,7 @@
|
|||
|
||||
.content-component {
|
||||
position: relative;
|
||||
|
||||
&--bookmarked {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,8 +50,7 @@
|
|||
|
||||
data() {
|
||||
return {
|
||||
height: 0,
|
||||
// title: 'Zahlungsmittel'
|
||||
height: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -61,16 +60,9 @@
|
|||
@import "@/styles/_variables.scss";
|
||||
|
||||
.infogram-block {
|
||||
/*padding: 8px 0;*/
|
||||
/*font-family: $sans-serif-font-family;*/
|
||||
/*font-size: 13px !important;*/
|
||||
/*line-height: 15px !important;*/
|
||||
/*text-align: center;*/
|
||||
/*border-top: 1px solid #dadada;*/
|
||||
/*margin: 0 30px;*/
|
||||
margin-bottom: $large-spacing;
|
||||
|
||||
&__link {
|
||||
/*color:#989898;*/
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@
|
|||
spellcheckText() {
|
||||
if (!this.spellcheckLoading) {
|
||||
return 'Rechtschreibung prüfen'
|
||||
|
||||
} else {
|
||||
return 'Wird geprüft...'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400">
|
||||
<defs>
|
||||
<clipPath id="avatar-clip-path">
|
||||
<circle class="cls-1" cx="200" cy="200" r="197"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="bg">
|
||||
<circle class="cls-2" cx="200" cy="200" r="197"/>
|
||||
</g>
|
||||
<g id="objects">
|
||||
<g class="cls-3">
|
||||
<path class="cls-4"
|
||||
d="M380.03229,346.82485l-99.89952-29.68554-75.91247-7.58045h-2.40707l-78.31955,7.58045-103.526,30.44984s75.62737,95.55272,183.04906,95.55272S380.03229,346.82485,380.03229,346.82485Z"/>
|
||||
<path class="cls-5"
|
||||
d="M272.15765,65.53589a86.01591,86.01591,0,0,0-20.524-14.33295,103.61294,103.61294,0,0,0-49.8204-11.92284,103.61271,103.61271,0,0,0-49.8198,11.92255A86.01706,86.01706,0,0,0,131.4688,65.53589c-47.89186,45.957-59.684,136.053-53.17653,195.51559,22.30221,28.20465,70.43168,35.98046,103.97675,29.59277-1.699-28.98109-18.28465-55.36789-18.09824-84.40807,16.82179-9.95623,9.42329-59.11938,10.702-81.59916l26.94039-6.97556,26.9404,6.97556c1.27875,22.47978-6.11974,71.64293,10.70211,81.59916.18642,29.04018-16.39928,55.427-18.09824,84.40807,33.545,6.38769,81.67447-1.38812,103.97668-29.59277C331.84167,201.58886,320.04951,111.49293,272.15765,65.53589Z"/>
|
||||
<path class="cls-6"
|
||||
d="M237.057,266.23162H166.56944c0,34.9025-27.34,45.73431-43.07576,50.90769,15.73577,67.03868,142.10688,67.03868,156.63909,0C260.78642,311.96593,241.52987,305.94826,237.057,266.23162Z"/>
|
||||
<ellipse class="cls-7" cx="202.35227" cy="179.47219" rx="79.23803" ry="97.02616"/>
|
||||
<path class="cls-8"
|
||||
d="M117.61519,154.166c10.8764-3.25836,22.30778,5.29762,25.51206,19.09451,3.20424,13.7965-3.02464,27.64251-13.90108,30.90087-10.87644,3.25678-22.30919-5.29877-25.51339-19.09389-3.20425-13.79708,3.026-27.64273,13.90241-30.90149Z"/>
|
||||
<path class="cls-5"
|
||||
d="M158.77973,88.35379c34.35007,53.44875,83.71361,66.59188,126.44529,82.83956C322.20435,145.19484,244.7734,11.96688,158.77973,88.35379Z"/>
|
||||
<path class="cls-5"
|
||||
d="M181.50651,94.88021c-10.83147,33.057-30.31262,48.8307-55.51284,58.59347C109.4863,115.38906,134.25941,72.625,181.50651,94.88021Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.cls-1 {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #d1eee7;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
clip-path: url(#avatar-clip-path);
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
fill: #17a887;
|
||||
}
|
||||
|
||||
.cls-4, .cls-5, .cls-6, .cls-8 {
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #102d24;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #e5f5f2;
|
||||
}
|
||||
|
||||
.cls-7, .cls-8 {
|
||||
fill: #fff;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -31,7 +31,6 @@
|
|||
<script>
|
||||
import ObjectiveGroups from '@/components/objective-groups/ObjectiveGroups.vue';
|
||||
import ObjectiveGroupControl from '@/components/objective-groups/ObjectiveGroupControl.vue';
|
||||
import AddObjectiveGroupButton from '@/components/AddObjectiveGroupButton';
|
||||
import Chapter from '@/components/Chapter.vue';
|
||||
|
||||
import UPDATE_OBJECTIVE_PROGRESS_MUTATION from '@/graphql/gql/mutations/updateObjectiveProgress.gql';
|
||||
|
|
@ -49,7 +48,6 @@
|
|||
BookmarkActions,
|
||||
ObjectiveGroups,
|
||||
ObjectiveGroupControl,
|
||||
AddObjectiveGroupButton,
|
||||
Chapter
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@
|
|||
display: none;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
z-index: 90;
|
||||
z-index: 11;
|
||||
background-color: $color-white;
|
||||
border-top: 1px solid $color-silver;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
<template>
|
||||
<objective-group-form
|
||||
:title="title"
|
||||
:objectives="objectives"
|
||||
@save="saveObjectiveGroup"
|
||||
@hide="hideModal"
|
||||
></objective-group-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import ObjectiveGroupForm from '@/components/objective-groups/ObjectiveGroupForm';
|
||||
import AddContentElement from '@/components/AddContentElement';
|
||||
|
||||
import UPDATE_OBJECTIVE_GROUP_MUTATION from '@/graphql/gql/mutations/updateObjectiveGroup.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
|
||||
import OBJECTIVE_GROUP_QUERY from '@/graphql/gql/objectiveGroupQuery.gql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AddContentElement,
|
||||
Modal,
|
||||
ObjectiveGroupForm
|
||||
},
|
||||
|
||||
computed: {
|
||||
title() {
|
||||
if (this.$store.state.objectiveGroupType === 'society') {
|
||||
return 'Gesellschaft';
|
||||
}
|
||||
return 'Sprache & Kommunikation';
|
||||
},
|
||||
objectives() {
|
||||
return this.objectiveGroup.objectives.edges.map(edge => edge.node)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
saveObjectiveGroup(objectives) {
|
||||
const objectiveGroup = {
|
||||
id: this.$store.state.currentObjectiveGroup,
|
||||
objectives,
|
||||
};
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_OBJECTIVE_GROUP_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
objectiveGroup
|
||||
}
|
||||
},
|
||||
// todo: make update work
|
||||
// update: (store, {data: {addObjectiveGroup: {objectiveGroup}}}) => {
|
||||
// const query = MODULE_DETAILS_QUERY;
|
||||
// const variables = {slug: this.$route.params.slug};
|
||||
// const data = store.readQuery({query, variables});
|
||||
// debugger;
|
||||
// if (data.module && data.module.objectiveGroups) {
|
||||
// data.module.objectiveGroups.edges.push({
|
||||
// node: objectiveGroup,
|
||||
// __typename: 'ObjectiveGroupNode'
|
||||
// });
|
||||
// store.writeQuery({query, variables, data});
|
||||
// }
|
||||
//
|
||||
// }
|
||||
refetchQueries: [{
|
||||
query: MODULE_DETAILS_QUERY,
|
||||
variables: {
|
||||
slug: this.$route.params.slug
|
||||
}
|
||||
}]
|
||||
|
||||
}).then(() => {
|
||||
this.hideModal();
|
||||
});
|
||||
},
|
||||
hideModal() {
|
||||
this.$store.dispatch('hideModal');
|
||||
},
|
||||
},
|
||||
|
||||
apollo: {
|
||||
objectiveGroup() {
|
||||
return {
|
||||
query: OBJECTIVE_GROUP_QUERY,
|
||||
variables: {
|
||||
id: this.$store.state.currentObjectiveGroup
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
objectiveGroup: {
|
||||
objectives: {
|
||||
edges: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
<template>
|
||||
<objective-group-form
|
||||
:title="title"
|
||||
:objectives="objectives"
|
||||
@save="saveObjectiveGroup"
|
||||
@hide="hideModal"
|
||||
></objective-group-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import ObjectiveGroupForm from '@/components/objective-groups/ObjectiveGroupForm';
|
||||
import AddContentElement from '@/components/AddContentElement';
|
||||
|
||||
import NEW_OBJECTIVE_GROUP_MUTATION from '@/graphql/gql/mutations/addObjectiveGroup.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AddContentElement,
|
||||
Modal,
|
||||
ObjectiveGroupForm
|
||||
},
|
||||
|
||||
computed: {
|
||||
title() {
|
||||
if (this.$store.state.objectiveGroupType === 'society') {
|
||||
return 'Gesellschaft';
|
||||
}
|
||||
return 'Sprache & Kommunikation';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
saveObjectiveGroup(objectives) {
|
||||
const objectiveGroup = {
|
||||
title: this.$store.state.objectiveGroupType,
|
||||
module: this.$store.state.parentModule,
|
||||
objectives,
|
||||
};
|
||||
this.$apollo.mutate({
|
||||
mutation: NEW_OBJECTIVE_GROUP_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
objectiveGroup
|
||||
}
|
||||
},
|
||||
// todo: make update work
|
||||
// update: (store, {data: {addObjectiveGroup: {objectiveGroup}}}) => {
|
||||
// const query = MODULE_DETAILS_QUERY;
|
||||
// const variables = {slug: this.$route.params.slug};
|
||||
// const data = store.readQuery({query, variables});
|
||||
// debugger;
|
||||
// if (data.module && data.module.objectiveGroups) {
|
||||
// data.module.objectiveGroups.edges.push({
|
||||
// node: objectiveGroup,
|
||||
// __typename: 'ObjectiveGroupNode'
|
||||
// });
|
||||
// store.writeQuery({query, variables, data});
|
||||
// }
|
||||
//
|
||||
// }
|
||||
refetchQueries: [{
|
||||
query: MODULE_DETAILS_QUERY,
|
||||
variables: {
|
||||
slug: this.$route.params.slug
|
||||
}
|
||||
}]
|
||||
|
||||
}).then(() => {
|
||||
this.hideModal();
|
||||
});
|
||||
},
|
||||
hideModal() {
|
||||
this.$store.dispatch('hideModal');
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
objectives: [
|
||||
{},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
|
|
@ -56,12 +56,6 @@
|
|||
return this.me.selectedClass;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
editObjectiveGroup() {
|
||||
this.$store.dispatch('editObjectiveGroup', this.group.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
<template>
|
||||
<modal class="objective-group-form">
|
||||
<template slot="header">
|
||||
<h4 class="objective-group-form__heading">Lernziele: {{title}}</h4>
|
||||
</template>
|
||||
|
||||
<objective-form
|
||||
:objective="objective"
|
||||
v-for="(objective, index) in initialObjectives"
|
||||
@input="updateObjective($event, index)"
|
||||
@delete="removeObjective(index)"
|
||||
:key="index"></objective-form>
|
||||
<add-content-element @add-element="addObjective"></add-content-element>
|
||||
|
||||
<div slot="footer">
|
||||
<a class="button button--primary" data-cy="modal-save-button"
|
||||
@click="$emit('save', initialObjectives)">Speichern</a>
|
||||
<a class="button" @click="$emit('hide')">Abbrechen</a>
|
||||
</div>
|
||||
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import ObjectiveForm from '@/components/objective-groups/ObjectiveForm';
|
||||
import AddContentElement from '@/components/AddContentElement';
|
||||
|
||||
export default {
|
||||
props: ['title', 'objectives'],
|
||||
|
||||
components: {
|
||||
AddContentElement,
|
||||
Modal,
|
||||
ObjectiveForm
|
||||
},
|
||||
|
||||
methods: {
|
||||
addObjective() {
|
||||
this.initialObjectives.push({});
|
||||
},
|
||||
updateObjective(text, index) {
|
||||
this.initialObjectives.splice(index, 1, {text});
|
||||
},
|
||||
removeObjective(index) {
|
||||
this.initialObjectives.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
initialObjectives: this.objectives
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.objective-group-form {
|
||||
&__heading {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,28 +1,49 @@
|
|||
<template>
|
||||
<div class="avatar">
|
||||
<transition name="fade">
|
||||
<user-icon v-show="!isAvatarLoaded" class="avatar__placeholder" :class="{'avatar__placeholder--highlighted': iconHighlighted}"></user-icon>
|
||||
<default-avatar v-show="!isAvatarLoaded" class="avatar__placeholder"
|
||||
:class="{'avatar__placeholder--highlighted': iconHighlighted}"></default-avatar>
|
||||
</transition>
|
||||
<transition name="show">
|
||||
<div v-show="isAvatarLoaded" class="avatar__image" ref="avatarImage" :style="{'background-image': `url(${this.avatarUrl})`}"></div>
|
||||
<div v-show="isAvatarLoaded" class="avatar__image" ref="avatarImage"
|
||||
:style="{'background-image': `url(${this.avatarUrl})`}"></div>
|
||||
</transition>
|
||||
<img class="avatar__fake-image" :src="avatarUrl" ref="fakeImage"/>
|
||||
|
||||
<div class="avatar__edit" v-if="editable" @click="closeSidebar">
|
||||
<router-link :to="{name: 'profile'}">
|
||||
<pen-icon></pen-icon>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DefaultAvatar from '@/components/icons/DefaultAvatar';
|
||||
import PenIcon from '@/components/icons/PenIcon';
|
||||
|
||||
import UserIcon from '@/components/icons/UserIcon';
|
||||
import TOGGLE_SIDEBAR from '@/graphql/gql/local/mutations/toggleSidebar.gql';
|
||||
|
||||
export default {
|
||||
props: ['avatarUrl', 'iconHighlighted'],
|
||||
components: {UserIcon},
|
||||
data () {
|
||||
props: {
|
||||
avatarUrl: {
|
||||
type: String
|
||||
},
|
||||
iconHighlighted: {},
|
||||
editable: {
|
||||
default: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
DefaultAvatar,
|
||||
PenIcon
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isAvatarLoaded: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
mounted() {
|
||||
if (this.avatarUrl !== '') {
|
||||
this.$refs.fakeImage.addEventListener('load', () => {
|
||||
if (this.$refs.fakeImage) {
|
||||
|
|
@ -30,7 +51,17 @@
|
|||
this.isAvatarLoaded = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closeSidebar() {
|
||||
this.$apollo.mutate({
|
||||
mutation: TOGGLE_SIDEBAR,
|
||||
variables: {
|
||||
open: false
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -45,11 +76,11 @@
|
|||
width: $max-width;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
|
||||
&__placeholder {
|
||||
height: $max-width;
|
||||
fill: $color-silver-dark;
|
||||
border-radius: 50%;
|
||||
|
||||
&--highlighted {
|
||||
fill: $color-brand;
|
||||
|
|
@ -57,14 +88,14 @@
|
|||
}
|
||||
|
||||
&__image {
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
|
||||
&--landscape {
|
||||
&--landscape {
|
||||
width: auto;
|
||||
height: $max-width;
|
||||
}
|
||||
|
|
@ -75,10 +106,25 @@
|
|||
height: 0;
|
||||
}
|
||||
|
||||
.fade-leave-active, .show-enter-active {
|
||||
&__edit {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
display: block;
|
||||
left: 50%;
|
||||
bottom: -7px;
|
||||
transform: translateX(50%);
|
||||
background-color: $color-white;
|
||||
border-radius: 50%;
|
||||
padding: 6px;
|
||||
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.fade-leave-active, .show-enter-active {
|
||||
transition: opacity .5s;
|
||||
}
|
||||
.fade-leave-to, .show-enter {
|
||||
.fade-leave-to, .show-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
<template>
|
||||
<div class="school-class">
|
||||
<h2 class="school-class__heading"><span class="school-class__name" data-cy="school-class-name">{{name}}</span>
|
||||
<edit-class-name v-if="teacher" @edit="editClassName"></edit-class-name>
|
||||
</h2>
|
||||
<div class="school-class__members school-class-members">
|
||||
<ul class="school-class-members__list simple-list simple-list--active" data-cy="active-class-members-list">
|
||||
<li
|
||||
class="simple-list__item member-item"
|
||||
data-cy="school-class-member"
|
||||
v-for="member in activeMembers"
|
||||
:key="member.id">
|
||||
<span class="member-item__name">{{fullName(member)}}</span>
|
||||
<span class="member-item__role">{{role(member)}}</span>
|
||||
<!-- <a-->
|
||||
<!-- class="member-item__action simple-list__action"-->
|
||||
<!-- data-cy="remove-from-class"-->
|
||||
<!-- v-if="teacher"-->
|
||||
<!-- @click="$emit('remove', member)">Deaktivieren</a>-->
|
||||
</li>
|
||||
</ul>
|
||||
<!-- <template v-if="inactiveMembers.length">-->
|
||||
<!-- <h3 class="school-class__inactive-heading">Deaktivierte Personen</h3>-->
|
||||
<!-- <ul data-cy="inactive-class-members-list" class="simple-list simple-list--inactive">-->
|
||||
<!-- <li-->
|
||||
<!-- class="simple-list__item member-item"-->
|
||||
<!-- data-cy="school-class-member"-->
|
||||
<!-- v-for="member in inactiveMembers"-->
|
||||
<!-- :key="member.id">-->
|
||||
<!-- <span class="member-item__name">{{fullName(member)}}</span>-->
|
||||
<!-- <span class="member-item__role">{{role(member)}}</span>-->
|
||||
<!-- <a-->
|
||||
<!-- class="member-item__action simple-list__action"-->
|
||||
<!-- data-cy="add-to-class"-->
|
||||
<!-- v-if="teacher"-->
|
||||
<!-- @click="$emit('add', member)">Aktivieren</a>-->
|
||||
<!-- </li>-->
|
||||
<!-- </ul>-->
|
||||
<!-- </template>-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EditClassName from '@/components/school-class/EditClassName';
|
||||
|
||||
export default {
|
||||
props: ['members', 'name', 'teacher', 'id'],
|
||||
|
||||
components: {
|
||||
EditClassName
|
||||
},
|
||||
|
||||
methods: {
|
||||
fullName(member) {
|
||||
return `${member.firstName} ${member.lastName}`;
|
||||
},
|
||||
role({isTeacher}) {
|
||||
return isTeacher ? 'Lehrperson' : 'Schüler';
|
||||
},
|
||||
editClassName() {
|
||||
this.$store.dispatch('editClassName');
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activeMembers() {
|
||||
return this.members.filter(member => member.active)
|
||||
},
|
||||
inactiveMembers() {
|
||||
return this.members.filter(member => !member.active)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.school-class {
|
||||
&__inactive-heading {
|
||||
@include heading-4;
|
||||
margin-bottom: $small-spacing;
|
||||
}
|
||||
|
||||
&__name {
|
||||
@include heading-2;
|
||||
}
|
||||
}
|
||||
|
||||
.member-item {
|
||||
&__name {
|
||||
font-family: $sans-serif-font-family;
|
||||
font-weight: $font-weight-bold;
|
||||
flex: 2 1 auto;
|
||||
}
|
||||
|
||||
&__role {
|
||||
flex: 0 1 110px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&__action {
|
||||
flex: 0 1 110px;
|
||||
padding-left: $large-spacing;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
<template>
|
||||
<div class="schoolclass">
|
||||
<h2 class="schoolclass__name">{{name}}</h2>
|
||||
<div class="schoolclass__members schoolclass-members">
|
||||
<ul class="schoolclass-members__list members-list">
|
||||
<li v-for="user in users" :key="user.id" class="members-list__item">
|
||||
<p class="member-item"><span class="member-item__name">{{fullName(user)}}</span> <span class="member-item__role">{{role(user)}}</span></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: ['users', 'name'],
|
||||
methods: {
|
||||
fullName (user) {
|
||||
return `${user.firstName} ${user.lastName}`;
|
||||
},
|
||||
role ({permissions}) {
|
||||
return permissions.indexOf('users.can_manage_school_class_content') > -1 ? 'Lehrperson' : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
$height: 52px;
|
||||
|
||||
.members-list {
|
||||
&__item {
|
||||
line-height: $height;
|
||||
height: $height;
|
||||
border-bottom: 1px solid $color-silver-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.member-item {
|
||||
|
||||
line-height: $height;
|
||||
height: $height;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
&__name {
|
||||
font-family: $sans-serif-font-family;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
&__role {
|
||||
padding-right: $medium-spacing;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
<template>
|
||||
<modal class="deactivate-user" :hide-header="true" :small="true">
|
||||
<h3 class="deactivate-user__heading">
|
||||
<template v-if="myself">
|
||||
Mich
|
||||
</template>
|
||||
<template v-else>
|
||||
Person
|
||||
</template>
|
||||
deaktivieren
|
||||
</h3>
|
||||
<p class="deactivate-user__text deactivate-user__paragraph">
|
||||
<template v-if="myself">
|
||||
Möchten Sie die Klasse <strong class="deactivate-user__text--strong">{{schoolClass}}</strong> verlassen?
|
||||
</template>
|
||||
<template v-else>
|
||||
Möchten Sie <strong
|
||||
class="deactivate-user__text--strong">{{name}}</strong> in der
|
||||
Klasse
|
||||
<strong class="deactivate-user__text--strong">{{schoolClass}}</strong> deaktivieren?
|
||||
</template>
|
||||
</p>
|
||||
<ul class="deactivate-user__list">
|
||||
<li class="deactivate-user__text deactivate-user__list-item">
|
||||
<template v-if="myself">
|
||||
Sie können
|
||||
</template>
|
||||
<template v-else>
|
||||
Diese Person kann
|
||||
</template>
|
||||
in Zukunft keine Inhalte mehr erfassen, bearbeiten und teilen.
|
||||
</li>
|
||||
<li class="deactivate-user__text deactivate-user__list-item">
|
||||
<template v-if="myself">
|
||||
Sie können
|
||||
</template>
|
||||
<template v-else>
|
||||
Diese Person kann
|
||||
</template>
|
||||
weiterhin Module und Instrumente lesen.
|
||||
</li>
|
||||
<li class="deactivate-user__text deactivate-user__list-item">
|
||||
<template v-if="myself">
|
||||
Sie können der Klasse jederzeit wieder beitreten.
|
||||
</template>
|
||||
<template v-else>
|
||||
Sie können diese Person jederzeit wieder aktivieren.
|
||||
</template>
|
||||
</li>
|
||||
</ul>
|
||||
<div slot="footer">
|
||||
<a class="button button--primary" data-cy="modal-save-button" v-on:click="confirm">Speichern</a>
|
||||
<a class="button" v-on:click="cancel">Abbrechen</a>
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Modal
|
||||
},
|
||||
|
||||
computed: {
|
||||
myself() {
|
||||
return this.$modal.state.payload.myself;
|
||||
},
|
||||
name() {
|
||||
return this.$modal.state.payload.name;
|
||||
},
|
||||
schoolClass() {
|
||||
return this.$modal.state.payload.className;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
confirm() {
|
||||
this.$modal.confirm();
|
||||
},
|
||||
cancel() {
|
||||
this.$modal.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.deactivate-user {
|
||||
&__heading {
|
||||
margin-bottom: $medium-spacing;
|
||||
}
|
||||
|
||||
&__list {
|
||||
padding-left: $medium-spacing;
|
||||
}
|
||||
|
||||
&__list-item {
|
||||
list-style: disc;
|
||||
}
|
||||
|
||||
&__text {
|
||||
@include regular-text;
|
||||
margin-bottom: $medium-spacing;
|
||||
|
||||
&--strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
<template>
|
||||
<!-- Not currently in use, but keeping the file in case it's needed again -->
|
||||
<div class="password-reset">
|
||||
<h2 class="password-reset__header">Passwort ändern</h2>
|
||||
<div v-if="showSuccess" class="success-message">
|
||||
|
|
@ -7,7 +8,7 @@
|
|||
<password-change-form
|
||||
@passwordSubmited="resetPassword"
|
||||
:oldPasswordErrors="oldPasswordErrors"
|
||||
:newPasswordErrors="newPasswordErrors" />
|
||||
:newPasswordErrors="newPasswordErrors"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
resetPassword (passwords) {
|
||||
resetPassword(passwords) {
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_PASSWORD_MUTATION,
|
||||
variables: {
|
||||
|
|
@ -37,7 +38,7 @@
|
|||
passwordInput: passwords
|
||||
}
|
||||
}
|
||||
}).then(({ data }) => {
|
||||
}).then(({data}) => {
|
||||
if (data.updatePassword.success) {
|
||||
this.oldPasswordErrors = [];
|
||||
this.newPasswordErrors = [];
|
||||
|
|
@ -56,14 +57,14 @@
|
|||
console.log('fail', error)
|
||||
});
|
||||
},
|
||||
handleOldPasswordError (error) {
|
||||
handleOldPasswordError(error) {
|
||||
this.oldPasswordErrors = error.errors.map((fieldError) => {
|
||||
if (fieldError.code === 'invalid') {
|
||||
return 'Die Eingabe ist falsch'
|
||||
}
|
||||
});
|
||||
},
|
||||
handleNewPasswordError (error) {
|
||||
handleNewPasswordError(error) {
|
||||
this.newPasswordErrors = error.errors.map((fieldError) => {
|
||||
if (fieldError.code === 'invalid') {
|
||||
return 'Das Passwort muss Grossbuchstaben, Zahlen und Sonderzeichen beinhalten'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<template>
|
||||
<div class="profile">
|
||||
<h1 class="profile__header">Profil</h1>
|
||||
<h2 class="profile__avatar profile-avatar">Profilbild</h2>
|
||||
<h1 class="profile__header">Profilbild</h1>
|
||||
<div class="profile-avatar" v-if="me.avatarUrl" >
|
||||
<div class="profile-avatar__image">
|
||||
<avatar :avatarUrl="me.avatarUrl" />
|
||||
|
|
@ -11,22 +10,18 @@
|
|||
</a>
|
||||
</div>
|
||||
<avatar-upload-form v-else @avatarUpdate="updateAvatar"/>
|
||||
<password-change />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import UPDATE_AVATAR_QUERY from '@/graphql/gql/mutations/updateAvatarUrl.gql';
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import PasswordChange from '@/components/profile/PasswordChange';
|
||||
import AvatarUploadForm from '@/components/profile/AvatarUploadForm';
|
||||
import Avatar from '@/components/profile/Avatar';
|
||||
import TrashIcon from '@/components/icons/TrashIcon';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PasswordChange,
|
||||
AvatarUploadForm,
|
||||
Avatar,
|
||||
TrashIcon
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
<template>
|
||||
<div class="profile-sidebar" v-if="sidebar.open" v-click-outside="closeSidebar">
|
||||
<a class="profile-sidebar__close-link" @click="closeSidebar">
|
||||
<cross class="profile-sidebar__close-icon"></cross>
|
||||
</a>
|
||||
<profile-widget class="profile-sidebar__item"></profile-widget>
|
||||
<div class="profile-sidebar__item" @click="closeSidebar">
|
||||
<router-link to="/me/activity" class="profile-sidebar__link">Meine Aktivitäten</router-link>
|
||||
</div>
|
||||
<div class="profile-sidebar__item">
|
||||
<h3 class="profile-sidebar__subtitle">Klasse</h3>
|
||||
<class-selection-widget></class-selection-widget>
|
||||
<div @click="closeSidebar">
|
||||
<router-link :to="{name: 'my-class'}" class="profile-sidebar__link">Klassenliste anzeigen</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="profile-sidebar__item" @click="closeSidebar">
|
||||
<router-link :to="{name:'join-class'}" data-cy="join-class-link" class="profile-sidebar__link">Zugangscode
|
||||
eingeben
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="profile-sidebar__item">
|
||||
<logout-widget></logout-widget>
|
||||
</div>
|
||||
|
||||
<p class="profile-sidebar__support">
|
||||
Supportanfragen: rahel.wenger@hep-verlag.ch
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProfileWidget from '@/components/profile/ProfileWidget';
|
||||
import Cross from '@/components/icons/Cross';
|
||||
|
||||
import ClassSelectionWidget from '@/components/school-class/ClassSelectionWidget';
|
||||
|
||||
import sidebarMixin from '@/mixins/sidebar';
|
||||
import LogoutWidget from '@/components/LogoutWidget';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
LogoutWidget,
|
||||
ClassSelectionWidget,
|
||||
ProfileWidget,
|
||||
Cross
|
||||
},
|
||||
|
||||
mixins: [sidebarMixin],
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.profile-sidebar {
|
||||
padding: $large-spacing 0;
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
height: 100vh;
|
||||
background-color: $color-white;
|
||||
z-index: 15;
|
||||
box-shadow: 0 3px 9px 0 rgba(0, 0, 0, 0.12);
|
||||
overflow-y: scroll;
|
||||
|
||||
width: 100%;
|
||||
@include desktop {
|
||||
width: 333px;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&__item {
|
||||
border-bottom: 1px solid $color-silver-light;
|
||||
padding: $large-spacing $medium-spacing;
|
||||
}
|
||||
|
||||
&__subtitle {
|
||||
@include small-text;
|
||||
margin: 0;
|
||||
margin-bottom: $small-spacing;
|
||||
}
|
||||
|
||||
&__link {
|
||||
@include default-link;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&__close-link {
|
||||
position: absolute;
|
||||
right: $small-spacing;
|
||||
top: $small-spacing;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__close-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
&__support {
|
||||
padding: $small-spacing;
|
||||
@include regular-text;
|
||||
color: $color-silver-dark;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div class="profile-widget">
|
||||
<div class="profile-widget__avatar">
|
||||
<avatar :avatar-url="me.avatarUrl" :editable="true"></avatar>
|
||||
</div>
|
||||
<h3 class="profile-widget__name">{{me.firstName}} {{me.lastName}}</h3>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Avatar from '@/components/profile/Avatar';
|
||||
import {meQuery} from '@/graphql/queries';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Avatar
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: meQuery
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
me: {}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.profile-widget {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
&__name {
|
||||
@include heading-3;
|
||||
text-align: center;
|
||||
margin-bottom: $small-spacing;
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: $medium-spacing;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
<template>
|
||||
<div class="class-selection" v-if="currentClassSelection">
|
||||
<div data-cy="class-selection" class="class-selection__selected-class selected-class"
|
||||
@click="showPopover = !showPopover">
|
||||
<current-class class="selected-class__text"></current-class>
|
||||
<chevron-down class="selected-class__dropdown-icon"></chevron-down>
|
||||
</div>
|
||||
<widget-popover v-if="showPopover"
|
||||
@hide-me="showPopover = false"
|
||||
:mobile="mobile"
|
||||
class="class-selection__popover">
|
||||
<li data-cy="class-selection-entry" class="popover-links__link popover-links__link--large"
|
||||
v-for="schoolClass in me.schoolClasses"
|
||||
:key="schoolClass.id"
|
||||
:label="schoolClass.name"
|
||||
:item="schoolClass"
|
||||
@click="updateSelectedClassAndHidePopover(schoolClass)">
|
||||
{{schoolClass.name}}
|
||||
</li>
|
||||
<li class="popover-links__link popover-links__link--large popover-links__divider"
|
||||
v-if="me.isTeacher"
|
||||
data-cy="create-class-link" @click="closeSidebar">
|
||||
<router-link tag="span" class="popover-links__link-with-icon" :to="{name: 'create-class'}">
|
||||
<add-icon class="popover-links__icon"/>
|
||||
<span>Klasse erfassen</span>
|
||||
</router-link>
|
||||
</li>
|
||||
<!-- <li class="popover-links__link popover-links__link--large popover-links__divider" @click="closeSidebar">-->
|
||||
<!-- <router-link tag="span" :to="{name: 'old-classes'}">Alte Klassen anzeigen</router-link>-->
|
||||
<!-- </li>-->
|
||||
</widget-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetPopover from '@/components/WidgetPopover';
|
||||
import ChevronDown from '@/components/icons/ChevronDown';
|
||||
import CurrentClass from '@/components/school-class/CurrentClass';
|
||||
import AddIcon from '@/components/icons/AddIcon';
|
||||
|
||||
import updateSelectedClassMixin from '@/mixins/updateSelectedClass';
|
||||
import sidebarMixin from '@/mixins/sidebar';
|
||||
import meMixin from '@/mixins/me';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
WidgetPopover,
|
||||
ChevronDown,
|
||||
CurrentClass,
|
||||
AddIcon
|
||||
},
|
||||
|
||||
props: {
|
||||
mobile: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
mixins: [updateSelectedClassMixin, sidebarMixin, meMixin],
|
||||
|
||||
data() {
|
||||
return {
|
||||
showPopover: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateSelectedClassAndHidePopover(selectedClass) {
|
||||
this.updateSelectedClass(selectedClass);
|
||||
this.showPopover = false;
|
||||
this.closeSidebar();
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentClassSelection() {
|
||||
let currentClass = this.me.schoolClasses.find(schoolClass => {
|
||||
return schoolClass.id === this.me.selectedClass.id
|
||||
});
|
||||
return currentClass || this.me.schoolClasses[0];
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.class-selection {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
margin-bottom: $medium-spacing;
|
||||
border: 1px solid $color-silver;
|
||||
border-radius: 4px;
|
||||
|
||||
&__popover {
|
||||
white-space: nowrap;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
transform: translateY($small-spacing);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.selected-class {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: $small-spacing $medium-spacing;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&__text {
|
||||
line-height: $large-spacing;
|
||||
@include regular-text;
|
||||
color: $color-silver-dark;
|
||||
}
|
||||
|
||||
&__dropdown-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: $color-brand;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<template>
|
||||
<span class="current-class" data-cy="current-class-name">{{currentClassName}}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import me from '@/mixins/me';
|
||||
|
||||
export default {
|
||||
mixins: [me],
|
||||
|
||||
computed: {
|
||||
currentClassName() {
|
||||
let currentClass = this.me.schoolClasses.find(schoolClass => {
|
||||
return schoolClass.id === this.me.selectedClass.id
|
||||
});
|
||||
return currentClass ? currentClass.name : this.me.schoolClasses.length ? this.me.schoolClasses[0].name : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.current-class {
|
||||
line-height: $large-spacing;
|
||||
@include regular-text;
|
||||
color: $color-silver-dark;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<a class="edit-class-name" @click="$emit('edit')" data-cy="edit-class-name-link">
|
||||
<pen-icon class="edit-class-name__icon"></pen-icon>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PenIcon from '@/components/icons/PenIcon';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PenIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
.edit-class-name {
|
||||
&__icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: $color-brand;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<template>
|
||||
<modal :hide-header="false" :small="true" title="Hello">
|
||||
<h4 slot="header">Klasse bearbeiten</h4>
|
||||
<modal-input v-on:input="name = $event"
|
||||
placeholder="Klassenname"
|
||||
data-cy="edit-class-name-input"
|
||||
:value="name"
|
||||
></modal-input>
|
||||
<div slot="footer">
|
||||
<a class="button button--primary" data-cy="modal-save-button"
|
||||
@click="save">Speichern</a>
|
||||
<a class="button" @click="hide">Abbrechen</a>
|
||||
</div>
|
||||
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import ModalInput from '@/components/ModalInput';
|
||||
|
||||
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/mySchoolClass.gql';
|
||||
import UPDATE_SCHOOL_CLASS_MUTATION from '@/graphql/gql/mutations/updateSchoolClass.gql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Modal,
|
||||
ModalInput
|
||||
},
|
||||
|
||||
methods: {
|
||||
save() {
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_SCHOOL_CLASS_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
name: this.name,
|
||||
id: this.schoolClass.id
|
||||
}
|
||||
},
|
||||
update(store, {data: {updateSchoolClass: {schoolClass: {name}}}}) {
|
||||
let query = MY_SCHOOL_CLASS_QUERY;
|
||||
let data = store.readQuery({query});
|
||||
data.me.selectedClass.name = name;
|
||||
store.writeQuery({query, data});
|
||||
}
|
||||
});
|
||||
this.hide();
|
||||
},
|
||||
hide() {
|
||||
this.$store.dispatch('hideModal');
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
schoolClass: {
|
||||
query: MY_SCHOOL_CLASS_QUERY,
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).me.selectedClass
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.name = this.schoolClass ? this.schoolClass.name : '';
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
name: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -7,6 +7,22 @@ import fetch from 'unfetch'
|
|||
import {typeDefs} from '@/graphql/typedefs';
|
||||
import {resolvers} from '@/graphql/resolvers';
|
||||
|
||||
const writeLocalCache = cache => {
|
||||
// we use the cache as our local state
|
||||
cache.writeData({
|
||||
data: {
|
||||
scrollPosition: {
|
||||
__typename: 'ScrollPosition',
|
||||
scrollTo: ''
|
||||
},
|
||||
sidebar: {
|
||||
__typename: 'Sidebar',
|
||||
open: false
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default function (uri) {
|
||||
const httpLink = createHttpLink({
|
||||
// uri: process.env.NODE_ENV !== 'production' ? 'http://localhost:8000/api/graphql/' : '/api/graphql/',
|
||||
|
|
@ -96,23 +112,19 @@ export default function (uri) {
|
|||
}
|
||||
};
|
||||
|
||||
// we use the cache as our local state
|
||||
cache.writeData({
|
||||
data: {
|
||||
scrollPosition: {
|
||||
__typename: 'ScrollPosition',
|
||||
scrollTo: ''
|
||||
}
|
||||
}
|
||||
});
|
||||
writeLocalCache(cache);
|
||||
|
||||
// Create the apollo client
|
||||
return new ApolloClient({
|
||||
const client = new ApolloClient({
|
||||
link: composedLink,
|
||||
// link: httpLink,
|
||||
cache,
|
||||
connectToDevTools: true,
|
||||
typeDefs,
|
||||
resolvers
|
||||
})
|
||||
});
|
||||
client.onResetStore(() => {
|
||||
writeLocalCache(cache);
|
||||
});
|
||||
return client;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
mutation($open: Boolean!) {
|
||||
toggleSidebar(open: $open) @client
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
query Sidebar {
|
||||
sidebar @client {
|
||||
open
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
query MeQuery {
|
||||
me {
|
||||
...UserParts
|
||||
isTeacher
|
||||
permissions
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
#import "../fragments/objectiveGroupParts.gql"
|
||||
mutation AddObjectiveGroup($input: AddObjectiveGroupInput!) {
|
||||
addObjectiveGroup(input: $input) {
|
||||
objectiveGroup {
|
||||
...ObjectiveGroupParts
|
||||
objectives {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
mutation AddRemoveMember($input: AddRemoveMemberInput!) {
|
||||
addRemoveMember(input: $input) {
|
||||
success
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
mutation CreateSchoolClass($input: CreateSchoolClassInput!) {
|
||||
createSchoolClass(input: $input) {
|
||||
success
|
||||
schoolClass {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
mutation JoinClass($input: JoinClassInput!) {
|
||||
joinClass(input: $input) {
|
||||
success
|
||||
schoolClass {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#import "../fragments/objectiveGroupParts.gql"
|
||||
mutation UpdateObjectiveGroup($input: UpdateObjectiveGroupInput!) {
|
||||
updateObjectiveGroup(input: $input) {
|
||||
objectiveGroup {
|
||||
...ObjectiveGroupParts
|
||||
objectives {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
mutation UpdateSchoolClass($input: UpdateSchoolClassInput!) {
|
||||
updateSchoolClass(input: $input) {
|
||||
success
|
||||
schoolClass {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
query MySchoolClassQuery {
|
||||
me {
|
||||
id
|
||||
isTeacher
|
||||
selectedClass {
|
||||
id
|
||||
name
|
||||
code
|
||||
members {
|
||||
id
|
||||
firstName
|
||||
lastName
|
||||
isTeacher
|
||||
active
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
query {
|
||||
me {
|
||||
id
|
||||
schoolClasses {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
users {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
firstName
|
||||
lastName
|
||||
permissions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
query OldClassesQuery {
|
||||
me {
|
||||
id
|
||||
oldClasses {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import SCROLL_POSITION from '@/graphql/gql/local/scrollPosition.gql';
|
||||
import SIDEBAR from '@/graphql/gql/local/sidebar.gql';
|
||||
|
||||
export const resolvers = {
|
||||
Mutation: {
|
||||
|
|
@ -7,6 +8,12 @@ export const resolvers = {
|
|||
data.scrollPosition.scrollTo = scrollTo;
|
||||
cache.writeQuery({query: SCROLL_POSITION, data});
|
||||
return data.scrollPosition;
|
||||
},
|
||||
toggleSidebar: (_, {open}, {cache}) => {
|
||||
const data = cache.readQuery({query: SIDEBAR});
|
||||
data.sidebar.open = open;
|
||||
cache.writeQuery({query: SIDEBAR, data});
|
||||
return data.sidebar;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ export const typeDefs = gql`
|
|||
scrollTo: String!
|
||||
}
|
||||
|
||||
type Sidebar {
|
||||
open: Boolean!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
scrollTo(scrollTo: String!): ScrollPosition
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div class="blank-layout">
|
||||
<profile-sidebar></profile-sidebar>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -14,9 +15,9 @@
|
|||
</style>
|
||||
|
||||
<script>
|
||||
import ProfileSidebar from '@/components/profile/ProfileSidebar';
|
||||
|
||||
export default {
|
||||
components: {},
|
||||
components: {ProfileSidebar},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div class="container skillbox" :class="specialContainerClass">
|
||||
<profile-sidebar></profile-sidebar>
|
||||
<header-bar class="header skillbox__header">
|
||||
</header-bar>
|
||||
|
||||
|
|
@ -13,11 +14,13 @@
|
|||
<script>
|
||||
import HeaderBar from '@/components/HeaderBar';
|
||||
import MobileHeader from '@/components/MobileHeader';
|
||||
import ProfileSidebar from '@/components/profile/ProfileSidebar';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HeaderBar,
|
||||
MobileHeader
|
||||
MobileHeader,
|
||||
ProfileSidebar
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
|
|
|||
|
|
@ -17,32 +17,13 @@ import {dateFilter} from './filters/date-filter';
|
|||
import autoGrow from '@/directives/auto-grow'
|
||||
import clickOutside from '@/directives/click-outside'
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import VueModal from '@/plugins/modal';
|
||||
import VueRemoveEdges from '@/plugins/edges';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
// TODO: Move into a separate project as a plugin
|
||||
//
|
||||
function getRidOfEdges(collection) {
|
||||
if (typeof collection === 'object' && collection && !Array.isArray(collection)) {
|
||||
let newObj = {};
|
||||
for (const k in collection) {
|
||||
if (k === 'edges') {
|
||||
return collection.edges.map(edge => getRidOfEdges(edge.node));
|
||||
} else {
|
||||
newObj[k] = getRidOfEdges(collection[k]);
|
||||
if (newObj[k]) {
|
||||
// delete newObj[k]['__typename']
|
||||
}
|
||||
}
|
||||
}
|
||||
return newObj
|
||||
} else {
|
||||
return collection
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(Vue.prototype, '$getRidOfEdges', {value: getRidOfEdges});
|
||||
|
||||
Vue.use(VueModal);
|
||||
Vue.use(VueRemoveEdges);
|
||||
Vue.use(VueApollo);
|
||||
Vue.use(VueAxios, axios);
|
||||
Vue.use(VueVimeoPlayer);
|
||||
|
|
@ -141,6 +122,7 @@ router.beforeEach(async (to, from, next) => {
|
|||
// handle logout
|
||||
if (to.path === '/logout') {
|
||||
privateApolloClient.resetStore();
|
||||
publicApolloClient.resetStore();
|
||||
next({name: 'login'});
|
||||
return
|
||||
}
|
||||
|
|
@ -151,8 +133,8 @@ router.beforeEach(async (to, from, next) => {
|
|||
return
|
||||
}
|
||||
|
||||
if (to.name !== 'noClass' && loginRequired(to) && await redirectStudentsWithoutClass()) {
|
||||
next({name: 'noClass'})
|
||||
if (to.name !== 'join-class' && loginRequired(to) && await redirectStudentsWithoutClass()) {
|
||||
next({name: 'join-class'})
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
import ME_QUERY from '@/graphql/gql/meQuery';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
addSchoolClass(store, schoolClass) {
|
||||
const query = ME_QUERY;
|
||||
if (schoolClass) {
|
||||
console.log('updating school class');
|
||||
const data = store.readQuery({query});
|
||||
if (data) {
|
||||
data.me.schoolClasses.edges = [
|
||||
...data.me.schoolClasses.edges,
|
||||
{
|
||||
node: schoolClass,
|
||||
__typename: 'SchoolClassNodeEdge'
|
||||
}
|
||||
];
|
||||
data.me.selectedClass = {
|
||||
id: schoolClass.id,
|
||||
__typename: 'SchoolClassNode'
|
||||
};
|
||||
store.writeQuery({query, data});
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
me: {
|
||||
selectedClass: {
|
||||
id: ''
|
||||
},
|
||||
permissions: [],
|
||||
schoolClasses: [],
|
||||
isTeacher: false
|
||||
},
|
||||
showPopover: false
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: {
|
||||
query: ME_QUERY,
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).me;
|
||||
},
|
||||
fetchPolicy: 'cache-first'
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import TOGGLE_SIDEBAR from '@/graphql/gql/local/mutations/toggleSidebar.gql';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
openSidebar() {
|
||||
this.$nextTick(() => { // we don't want this to happen instantly, only almost instantly. Otherwise the click-outside-directive won't work
|
||||
this.$apollo.mutate({
|
||||
mutation: TOGGLE_SIDEBAR,
|
||||
variables: {
|
||||
open: true
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/mySchoolClass';
|
||||
|
||||
export default {
|
||||
apollo: {
|
||||
me: {
|
||||
query: MY_SCHOOL_CLASS_QUERY,
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).me
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
me: {
|
||||
isTeacher: false,
|
||||
selectedClass: {
|
||||
name: '',
|
||||
members: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import SIDEBAR from '@/graphql/gql/local/sidebar.gql';
|
||||
import TOGGLE_SIDEBAR from '@/graphql/gql/local/mutations/toggleSidebar.gql';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
closeSidebar() {
|
||||
if (this.sidebar.open) {
|
||||
this.$apollo.mutate({
|
||||
mutation: TOGGLE_SIDEBAR,
|
||||
variables: {
|
||||
open: false
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
apollo: {
|
||||
sidebar: {
|
||||
query: SIDEBAR
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
sidebar: {
|
||||
open: false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import UPDATE_USER_SETTING from '@/graphql/gql/mutations/updateUserSetting.gql';
|
||||
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/mySchoolClass.gql';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
updateSelectedClass(selectedClass) {
|
||||
return this.$apollo.mutate({
|
||||
mutation: UPDATE_USER_SETTING,
|
||||
variables: {
|
||||
input: {
|
||||
id: selectedClass.id
|
||||
}
|
||||
},
|
||||
update(store, data) {
|
||||
let meData = store.readQuery({query: ME_QUERY});
|
||||
|
||||
meData.me.selectedClass = selectedClass;
|
||||
|
||||
store.writeQuery({query: ME_QUERY, data: meData});
|
||||
},
|
||||
refetchQueries: [{
|
||||
query: MY_SCHOOL_CLASS_QUERY
|
||||
}]
|
||||
}).catch((error) => {
|
||||
console.warn('failed to update selected class', error)
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<template>
|
||||
<div class="create-class">
|
||||
<h1 class="create-class__title">Klasse erfassen</h1>
|
||||
|
||||
<div>
|
||||
<div class="skillboxform-input">
|
||||
<label for="class-name" class="skillboxform-input__label">Name</label>
|
||||
<input
|
||||
id="class-name"
|
||||
class="skillbox-input skillboxform-input__input"
|
||||
:class="{'skillboxform-input__input--error': error}"
|
||||
data-cy="input-class-name"
|
||||
:value="name"
|
||||
@input="updateName">
|
||||
<small
|
||||
v-if="error"
|
||||
class="skillboxform-input__error"
|
||||
data-cy="email-local-errors"
|
||||
>{{ error }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="button button--primary button--big" data-cy="create-class" @click="createClass(name)">Klasse
|
||||
erfassen</a>
|
||||
<a class="button button--big" data-cy="create-class-cancel" @click="cancel">Abbrechen</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import addSchoolClassMixin from '@/mixins/add-school-class';
|
||||
|
||||
import CREATE_CLASS_MUTATION from '@/graphql/gql/mutations/createClass.gql';
|
||||
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/mySchoolClass';
|
||||
|
||||
export default {
|
||||
mixins: [addSchoolClassMixin],
|
||||
data: () => ({
|
||||
name: '',
|
||||
error: ''
|
||||
}),
|
||||
|
||||
methods: {
|
||||
updateName(event) {
|
||||
this.name = event.target.value;
|
||||
this.error = '';
|
||||
},
|
||||
createClass(name) {
|
||||
let self = this;
|
||||
this.$apollo.mutate({
|
||||
mutation: CREATE_CLASS_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
name
|
||||
}
|
||||
},
|
||||
update(store, {data: {createSchoolClass: {schoolClass}}}) {
|
||||
self.addSchoolClass(store, schoolClass);
|
||||
self.$router.push({
|
||||
name: 'my-class'
|
||||
});
|
||||
},
|
||||
refetchQueries: [{
|
||||
query: MY_SCHOOL_CLASS_QUERY
|
||||
}]
|
||||
});
|
||||
},
|
||||
cancel() {
|
||||
this.$router.go(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
.create-class {
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1 data-cy="join-class-title">Zugangscode eingeben</h1>
|
||||
<div>
|
||||
<div class="skillboxform-input">
|
||||
<label for="join-code" class="skillboxform-input__label">Zugangscode</label>
|
||||
<input
|
||||
id="join-code"
|
||||
class="skillbox-input skillboxform-input__input"
|
||||
:class="{'skillboxform-input__input--error': error}"
|
||||
data-cy="input-class-code"
|
||||
:value="code"
|
||||
@input="updateCode">
|
||||
<small
|
||||
v-if="error"
|
||||
class="skillboxform-input__error"
|
||||
data-cy="email-local-errors"
|
||||
>{{ error }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="button button--primary button--big" data-cy="join-class" @click="joinClass(code)">Klasse beitreten</a>
|
||||
<a class="button button--big" data-cy="join-class-cancel" @click="cancel">Abbrechen</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import JOIN_CLASS_MUTATION from '@/graphql/gql/mutations/joinClass.gql';
|
||||
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/mySchoolClass';
|
||||
|
||||
import addSchoolClassMixin from '@/mixins/add-school-class';
|
||||
|
||||
export default {
|
||||
mixins: [addSchoolClassMixin],
|
||||
|
||||
data: () => ({
|
||||
code: '',
|
||||
error: ''
|
||||
}),
|
||||
|
||||
methods: {
|
||||
updateCode(event) {
|
||||
this.code = event.target.value;
|
||||
this.error = '';
|
||||
},
|
||||
joinClass(code) {
|
||||
let self = this;
|
||||
this.$apollo.mutate({
|
||||
mutation: JOIN_CLASS_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
code
|
||||
}
|
||||
},
|
||||
update(store, {data: {joinClass: {schoolClass}}}) {
|
||||
self.addSchoolClass(store, schoolClass);
|
||||
self.$router.push({name: 'my-class'});
|
||||
},
|
||||
refetchQueries: [{query: MY_SCHOOL_CLASS_QUERY}]
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
})
|
||||
.catch(e => {
|
||||
console.debug(e);
|
||||
if (e.message.indexOf('[CAJ]') > -1) {
|
||||
this.error = 'Sie sind dieser Klasse bereits beigetreten.';
|
||||
} else {
|
||||
this.error = 'Dieser Zugangscode ist nicht gültig.';
|
||||
}
|
||||
})
|
||||
},
|
||||
cancel() {
|
||||
this.$router.go(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.module-page {
|
||||
display: -ms-grid;
|
||||
display: flex;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<script>
|
||||
import MODULE_ROOM_ENTRIES_QUERY from '@/graphql/gql/moduleRoomEntryQuery.gql';
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import roomMixin from '@/components/mixins/room'
|
||||
import roomMixin from '@/mixins/room'
|
||||
|
||||
export default {
|
||||
props: ['slug'],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
<template>
|
||||
<div class="my-class">
|
||||
<h1 class="my-class__header" data-cy="class-list-title">Klassenliste</h1>
|
||||
<router-link class="my-class__code-link button button--primary"
|
||||
v-if="me.isTeacher"
|
||||
:to="{name: 'show-code'}">Zugangscode anzeigen
|
||||
</router-link>
|
||||
<class-list
|
||||
class="my-class__class"
|
||||
:name="me.selectedClass.name"
|
||||
:members="me.selectedClass.members"
|
||||
:teacher="me.isTeacher"
|
||||
:id="me.selectedClass.id"
|
||||
@remove="remove"
|
||||
@add="add"
|
||||
></class-list>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ClassList from '@/components/profile/ClassList';
|
||||
|
||||
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/mySchoolClass.gql';
|
||||
import ADD_REMOVE_MEMBER_MUTATION from '@/graphql/gql/mutations/addRemoveMember.gql';
|
||||
import selectedClassMixin from '@/mixins/selected-class';
|
||||
|
||||
export default {
|
||||
mixins: [selectedClassMixin],
|
||||
|
||||
components: {
|
||||
ClassList
|
||||
},
|
||||
|
||||
methods: {
|
||||
changeMember(member, active) {
|
||||
this.$apollo.mutate({
|
||||
mutation: ADD_REMOVE_MEMBER_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
member: member.id,
|
||||
schoolClass: this.me.selectedClass.id,
|
||||
active
|
||||
}
|
||||
},
|
||||
update(store, {data: {addRemoveMember: {success}}}) {
|
||||
if (success) {
|
||||
const query = MY_SCHOOL_CLASS_QUERY;
|
||||
const data = store.readQuery({query});
|
||||
let memberIndex = data.me.selectedClass.members.findIndex(m => m.id === member.id);
|
||||
data.me.selectedClass.members = [
|
||||
...data.me.selectedClass.members.slice(0, memberIndex),
|
||||
{...member, active},
|
||||
...data.me.selectedClass.members.slice(memberIndex + 1),
|
||||
];
|
||||
store.writeQuery({query, data});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
add(member) {
|
||||
this.changeMember(member, true);
|
||||
},
|
||||
remove(member) {
|
||||
this.$modal.open('deactivate-person', {
|
||||
myself: member.id === this.me.id,
|
||||
name: `${member.firstName} ${member.lastName}`,
|
||||
className: this.me.selectedClass.name,
|
||||
})
|
||||
.then(() => {
|
||||
this.changeMember(member, false);
|
||||
})
|
||||
.catch(() => {
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
.my-class {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto;
|
||||
grid-template-rows: auto auto;
|
||||
grid-template-areas: "h b" "c c";
|
||||
|
||||
&__header {
|
||||
grid-area: h;
|
||||
}
|
||||
|
||||
&__code-link {
|
||||
grid-area: b;
|
||||
justify-self: end;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&__class {
|
||||
grid-area: c;
|
||||
width: 100%;
|
||||
margin-bottom: $large-spacing;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<template>
|
||||
<div class="myclasses">
|
||||
<h1 class="myclasses__header">Klassenliste</h1>
|
||||
<classlist v-for="schoolClass in schoolClasses" v-bind="schoolClass" :key="schoolClass.name" class="myclasses__class"></classlist>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import MY_SCHOOL_CLASSES_QUERY from '@/graphql/gql/mySchoolClasses.gql';
|
||||
import Classlist from '@/components/profile/Classlist';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Classlist
|
||||
},
|
||||
|
||||
apollo: {
|
||||
schoolClasses: {
|
||||
query: MY_SCHOOL_CLASSES_QUERY,
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).me.schoolClasses
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
schoolClasses: []
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
.myclasses {
|
||||
&__class {
|
||||
margin-bottom: $large-spacing;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<template>
|
||||
<div class="old-classes">
|
||||
<h1 class="old-classes__title">Alte Klassen</h1>
|
||||
<ul class="old-classes__list simple-list">
|
||||
<li class="simple-list__item" v-for="schoolClass in me.oldClasses" :key="schoolClass.id" data-cy="old-class-item"><span
|
||||
class="old-classes__class-name">{{schoolClass.name}}</span> <a
|
||||
class="simple-list__action" @click="updateSelectedClassAndGoToClassList(schoolClass)">Anzeigen</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import OLD_CLASSES_QUERY from '@/graphql/gql/oldClasses.gql';
|
||||
|
||||
import updateSelectedClassMixin from '@/mixins/updateSelectedClass';
|
||||
|
||||
export default {
|
||||
mixins: [updateSelectedClassMixin],
|
||||
|
||||
methods: {
|
||||
updateSelectedClassAndGoToClassList(selectedClass) {
|
||||
this.updateSelectedClass(selectedClass).then(() => {
|
||||
this.$router.push({name: 'my-class'});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// todo: test this in front- and backend
|
||||
apollo: {
|
||||
me: {
|
||||
query: OLD_CLASSES_QUERY,
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).me;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
me: {
|
||||
oldClasses: []
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
.old-classes {
|
||||
&__class-name {
|
||||
font-family: $sans-serif-font-family;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,16 +1,5 @@
|
|||
<template>
|
||||
<div class="profile">
|
||||
<nav class="top-navigation profile-submenu profile__submenu">
|
||||
<router-link to="/me/activity" active-class="top-navigation__link--active"
|
||||
class="top-navigation__link profile-submenu__item submenu-item">Aktivität
|
||||
</router-link>
|
||||
<router-link to="/me/myclasses" active-class="top-navigation__link--active"
|
||||
class="top-navigation__link profile-submenu__item submenu-item">Klassenliste
|
||||
</router-link>
|
||||
<router-link to="/me/profile" active-class="top-navigation__link--active"
|
||||
class="top-navigation__link profile-submenu__item submenu-item">Profil
|
||||
</router-link>
|
||||
</nav>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -21,26 +10,15 @@
|
|||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.profile {
|
||||
padding: $medium-spacing;
|
||||
padding: $large-spacing;
|
||||
max-width: 640px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
@include desktop {
|
||||
max-width: 1024px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__submenu {
|
||||
margin-bottom: $medium-spacing;
|
||||
margin-left: -$medium-spacing;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-submenu {
|
||||
&__item {
|
||||
font-family: $sans-serif-font-family;
|
||||
font-size: toRem(14px);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
<script>
|
||||
import ROOM_ENTRIES_QUERY from '@/graphql/gql/roomEntriesQuery.gql';
|
||||
import roomMixin from '@/components/mixins/room'
|
||||
import roomMixin from '@/mixins/room'
|
||||
|
||||
export default {
|
||||
props: ['slug'],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
<template>
|
||||
<div class="show-code">
|
||||
<h2 class="show-code__title">Zugangscode Klasse {{me.selectedClass.name}}</h2>
|
||||
<h1 class="show-code__code">{{me.selectedClass.code}}</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import selectedClassMixin from '@/mixins/selected-class';
|
||||
|
||||
export default {
|
||||
mixins: [selectedClassMixin],
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.show-code {
|
||||
&__title {
|
||||
@include regular-text;
|
||||
margin-bottom: 2*$large-spacing;
|
||||
}
|
||||
|
||||
&__code {
|
||||
font-size: toRem(120px);
|
||||
letter-spacing: toRem(20px);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -40,9 +40,9 @@
|
|||
<news-teaser date="11. März 2020" title="Brexit"
|
||||
url="https://myskillbox-abu-news.webflow.io/brexit"></news-teaser>
|
||||
<news-teaser date="20. Dezember 2019" title="Blockchain"
|
||||
url="http://abunews-blockchain.webflow.io/"></news-teaser>
|
||||
url="https://myskillbox-abu-news.webflow.io/blockchain"></news-teaser>
|
||||
<news-teaser date="9. September 2019" title="Klima – was sonst?"
|
||||
url="https://abunews-1f178193a10edaabf-4caff67b27d10.webflow.io/"></news-teaser>
|
||||
url="https://myskillbox-abu-news.webflow.io/klima"></news-teaser>
|
||||
<!--<news-teaser date="31. Oktober 2018" title="Sommerzeit - Festivalzeit"-->
|
||||
<!--url="https://abunews.webflow.io/"></news-teaser>-->
|
||||
<div class="news__more">Mehr...</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<h1 class="survey-page__title">{{title}}</h1>
|
||||
<survey :survey='survey'></survey>
|
||||
|
||||
<solution :value="solution" v-if="module.solutionsEnabled || isTeacher"></solution>
|
||||
<solution :value="solution" v-if="showSolution"></solution>
|
||||
<div v-if="surveyComplete">
|
||||
<a class="button button--primary" @click="reopen">Übung bearbeiten</a>
|
||||
</div>
|
||||
|
|
@ -50,6 +50,9 @@
|
|||
surveyComplete() {
|
||||
return this.survey && this.survey.isCompleted
|
||||
},
|
||||
showSolution() {
|
||||
return (module.solutionsEnabled || isTeacher) && !this.survey.isCompleted
|
||||
},
|
||||
solution() {
|
||||
return {
|
||||
text: this.answers.reduce((previous, answer) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
const getRidOfEdges = (collection) => {
|
||||
if (typeof collection === 'object' && collection && !Array.isArray(collection)) {
|
||||
let newObj = {};
|
||||
for (const k in collection) {
|
||||
if (collection.hasOwnProperty(k)) {
|
||||
if (k === 'edges') {
|
||||
return collection.edges.map(edge => getRidOfEdges(edge.node));
|
||||
} else {
|
||||
newObj[k] = getRidOfEdges(collection[k]);
|
||||
if (newObj[k]) {
|
||||
// delete newObj[k]['__typename']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return newObj
|
||||
} else {
|
||||
return collection
|
||||
}
|
||||
};
|
||||
|
||||
const EdgesPlugin = {
|
||||
install(Vue, options) {
|
||||
Vue.prototype.$getRidOfEdges = getRidOfEdges;
|
||||
}
|
||||
};
|
||||
|
||||
export default EdgesPlugin;
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// adapted from
|
||||
// https://stackoverflow.com/questions/41791193/vuejs-reactive-binding-for-a-plugin-how-to/41801107#41801107
|
||||
import Vue from 'vue';
|
||||
|
||||
class ModalStore {
|
||||
constructor(data = {}) {
|
||||
this.vm = new Vue({
|
||||
data: () => ({
|
||||
component: '',
|
||||
payload: {}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
get state() {
|
||||
return this.vm.$data;
|
||||
}
|
||||
}
|
||||
|
||||
const ModalPlugin = {
|
||||
install(Vue, options) {
|
||||
const store = new ModalStore({});
|
||||
|
||||
const reset = () => {
|
||||
store.state.component = '';
|
||||
store.state.payload = {};
|
||||
};
|
||||
|
||||
Vue.prototype.$modal = {
|
||||
state: store.state,
|
||||
component: store.state.component,
|
||||
payload: store.state.payload,
|
||||
open: (component, payload) => {
|
||||
store.state.payload = payload;
|
||||
store.state.component = component;
|
||||
return new Promise((resolve, reject) => {
|
||||
this._resolve = resolve;
|
||||
this._reject = reject;
|
||||
});
|
||||
},
|
||||
confirm: () => {
|
||||
reset();
|
||||
this._resolve();
|
||||
},
|
||||
cancel: () => {
|
||||
reset();
|
||||
this._reject();
|
||||
},
|
||||
_resolve: () => {
|
||||
},
|
||||
_reject: () => {
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export default ModalPlugin;
|
||||
|
|
@ -19,7 +19,7 @@ import portfolio from '@/pages/portfolio'
|
|||
import project from '@/pages/project'
|
||||
import profilePage from '@/pages/profile'
|
||||
import profile from '@/components/profile/Profile'
|
||||
import myClasses from '@/pages/myClasses'
|
||||
import myClass from '@/pages/myClass'
|
||||
import activity from '@/pages/activity'
|
||||
import Router from 'vue-router'
|
||||
import editProject from '@/pages/editProject'
|
||||
|
|
@ -30,6 +30,10 @@ import moduleRoom from '@/pages/moduleRoom'
|
|||
import login from '@/pages/login'
|
||||
import registration from '@/pages/registration'
|
||||
import waitForClass from '@/pages/waitForClass'
|
||||
import joinClass from '@/pages/joinClass'
|
||||
import oldClasses from '@/pages/oldClasses';
|
||||
import createClass from '@/pages/createClass';
|
||||
import showCode from '@/pages/showCode';
|
||||
|
||||
import store from '@/store/index';
|
||||
|
||||
|
|
@ -107,11 +111,20 @@ const routes = [
|
|||
component: profilePage,
|
||||
children: [
|
||||
{path: 'profile', name: 'profile', component: profile, meta: {isProfile: true}},
|
||||
{path: 'myclasses', name: 'my-classes', component: myClasses, meta: {isProfile: true}},
|
||||
{path: 'my-class', name: 'my-class', component: myClass, meta: {isProfile: true}},
|
||||
{path: 'activity', name: 'activity', component: activity, meta: {isProfile: true}},
|
||||
{path: '', name: 'profile-activity', component: activity, meta: {isProfile: true}},
|
||||
{
|
||||
path: 'old-classes',
|
||||
name: 'old-classes',
|
||||
component: oldClasses,
|
||||
meta: {isProfile: true}
|
||||
},
|
||||
{path: 'create-class', name: 'create-class', component: createClass, meta: {layout: 'simple'}},
|
||||
{path: 'show-code', name: 'show-code', component: showCode, meta: {layout: 'simple'}},
|
||||
]
|
||||
},
|
||||
{path: 'join-class', name: 'join-class', component: joinClass, meta: {layout: 'simple'}},
|
||||
{
|
||||
path: '/survey/:id',
|
||||
component: surveyPage,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
Vue.use(Vuex);
|
||||
|
||||
// WARNING fixme todo: please do not use this anymore, use the local GraphQL cache
|
||||
export default new Vuex.Store({
|
||||
|
|
@ -19,7 +19,6 @@ export default new Vuex.Store({
|
|||
currentRoomEntry: '',
|
||||
parentRoom: null,
|
||||
parentModule: '',
|
||||
objectiveGroupType: '',
|
||||
currentObjectiveGroup: '',
|
||||
parentProject: null,
|
||||
currentNote: null,
|
||||
|
|
@ -34,7 +33,10 @@ export default new Vuex.Store({
|
|||
scrollToAssignmentId: '',
|
||||
scrollToAssignmentReady: false,
|
||||
scrollingToAssignment: false,
|
||||
editModule: false
|
||||
editModule: false,
|
||||
modulePayload: [],
|
||||
modalResolve: () => {},
|
||||
modalReject: () => {},
|
||||
},
|
||||
|
||||
getters: {
|
||||
|
|
@ -51,12 +53,21 @@ export default new Vuex.Store({
|
|||
currentNote: state => state.currentNote,
|
||||
currentNoteParent: state => state.currentNoteParent,
|
||||
noteType: state => state.noteType,
|
||||
modulePayload: state => state.modulePayload
|
||||
},
|
||||
|
||||
actions: {
|
||||
setSpecialContainerClass({commit}, payload) {
|
||||
commit('setSpecialContainerClass', payload);
|
||||
},
|
||||
confirmModal({dispatch, state}) {
|
||||
dispatch('hideModal');
|
||||
state.modalResolve();
|
||||
},
|
||||
cancelModal({dispatch, state}) {
|
||||
dispatch('hideModal');
|
||||
state.modalReject();
|
||||
},
|
||||
hideModal({commit, dispatch}) {
|
||||
document.body.classList.remove('no-scroll'); // won't get at the body any other way
|
||||
commit('setModal', false);
|
||||
|
|
@ -70,8 +81,6 @@ export default new Vuex.Store({
|
|||
commit('setContentBlockPosition', {});
|
||||
commit('setParentRoom', null);
|
||||
commit('setParentModule', '');
|
||||
// todo: remove
|
||||
commit('setObjectiveGroupType', '');
|
||||
commit('setCurrentObjectiveGroup', '');
|
||||
commit('setParentProject', null);
|
||||
commit('setCurrentProjectEntry', null);
|
||||
|
|
@ -83,6 +92,7 @@ export default new Vuex.Store({
|
|||
commit('setVimeoId', null);
|
||||
commit('setCurrentNote', null);
|
||||
commit('setNoteType', '');
|
||||
commit('setModulePayload', []);
|
||||
},
|
||||
resetContentBlockPosition({commit}) {
|
||||
commit('setContentBlockPosition', {});
|
||||
|
|
@ -110,19 +120,14 @@ export default new Vuex.Store({
|
|||
commit('setCurrentRoomEntry', payload);
|
||||
dispatch('showModal', 'edit-room-entry-wizard');
|
||||
},
|
||||
// todo: remove
|
||||
addObjectiveGroup({commit, dispatch}, {module, type}) {
|
||||
commit('setParentModule', module);
|
||||
commit('setObjectiveGroupType', type);
|
||||
dispatch('showModal', 'new-objective-group-wizard');
|
||||
},
|
||||
editObjectiveGroup({commit, dispatch}, payload) {
|
||||
commit('setCurrentObjectiveGroup', payload);
|
||||
dispatch('showModal', 'edit-objective-group-wizard');
|
||||
},
|
||||
showModal({commit}, payload) {
|
||||
document.body.classList.add('no-scroll'); // won't get at the body any other way
|
||||
|
||||
commit('setModal', payload);
|
||||
return new Promise((resolve, reject) => {
|
||||
commit('setModalResolve', resolve);
|
||||
commit('setModalReject', reject);
|
||||
})
|
||||
},
|
||||
addProjectEntry({commit, dispatch}, payload) {
|
||||
commit('setParentProject', payload);
|
||||
|
|
@ -179,6 +184,13 @@ export default new Vuex.Store({
|
|||
},
|
||||
editModule({commit}, payload) {
|
||||
commit('setEditModule', payload)
|
||||
},
|
||||
editClassName({dispatch}, payload) {
|
||||
dispatch('showModal', 'edit-class-name-wizard');
|
||||
},
|
||||
deactivateUser({commit, dispatch}, payload) {
|
||||
commit('setModulePayload', payload);
|
||||
return dispatch('showModal', 'deactivate-person');
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -216,10 +228,6 @@ export default new Vuex.Store({
|
|||
setParentModule(state, payload) {
|
||||
state.parentModule = payload;
|
||||
},
|
||||
// todo: remove
|
||||
setObjectiveGroupType(state, payload) {
|
||||
state.objectiveGroupType = payload;
|
||||
},
|
||||
setCurrentObjectiveGroup(state, payload) {
|
||||
state.currentObjectiveGroup = payload;
|
||||
},
|
||||
|
|
@ -258,6 +266,15 @@ export default new Vuex.Store({
|
|||
},
|
||||
setNoteType(state, payload) {
|
||||
state.noteType = payload;
|
||||
},
|
||||
setModulePayload(state, payload) {
|
||||
state.modulePayload = payload;
|
||||
},
|
||||
setModalResolve(state, payload) {
|
||||
state.modalResolve = payload;
|
||||
},
|
||||
setModalReject(state, payload) {
|
||||
state.modalReject = payload;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
.book-subnavigation {
|
||||
&__item {
|
||||
@include small-text;
|
||||
margin-bottom: $small-spacing;
|
||||
cursor: pointer;
|
||||
|
||||
color: $color-silver-dark;
|
||||
|
||||
&--mobile {
|
||||
color: $color-white;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&--active {
|
||||
color: $color-brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,11 @@
|
|||
.skillbox {
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
|
|
@ -34,39 +39,15 @@
|
|||
-ms-grid-column: 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
display: -ms-grid;
|
||||
-ms-grid-rows: 50px 30px auto; // 1 extra row for gap
|
||||
-ms-grid-columns: 1fr;
|
||||
|
||||
@include skillbox-colors;
|
||||
|
||||
&__header {
|
||||
grid-area: h;
|
||||
-ms-grid-row: 1;
|
||||
}
|
||||
|
||||
&__content {
|
||||
-ms-grid-row: 3;
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
grid-area: f;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
& > :nth-child(2) {
|
||||
|
||||
}
|
||||
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-row: 4;
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,18 @@
|
|||
font-size: toRem(18px);
|
||||
}
|
||||
|
||||
@mixin default-link {
|
||||
font-size: toRem(18px);
|
||||
font-family: $sans-serif-font-family;
|
||||
font-weight: $font-weight-regular;
|
||||
color: $color-silver-dark;
|
||||
cursor: pointer;
|
||||
|
||||
&--active {
|
||||
color: $color-brand;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin page-form-input-heading {
|
||||
display: block;
|
||||
margin-bottom: $medium-spacing;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
@import "variables";
|
||||
|
||||
.simple-list {
|
||||
border-top: 1px solid $color-silver-dark;
|
||||
|
||||
&--active {
|
||||
margin-bottom: 2*$large-spacing;
|
||||
}
|
||||
|
||||
&__item {
|
||||
line-height: $list-height;
|
||||
height: $list-height;
|
||||
border-bottom: 1px solid $color-silver-dark;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&__action {
|
||||
@include default-link;
|
||||
color: $color-brand;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
@import "variables";
|
||||
|
||||
.uploadcare--panel {
|
||||
background: $color-silver-light;
|
||||
height: 200px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: $color-white;
|
||||
height: 230px;
|
||||
border: 1px dashed $color-silver;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.uploadcare--menu {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ $red: #FA5F5F;
|
|||
$green: #6DD79A;
|
||||
$brown: #EB9E77;
|
||||
|
||||
$list-height: 52px;
|
||||
|
||||
|
||||
|
||||
$default-border-radius: 13px;
|
||||
$input-border-radius: 3px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
@import "variables";
|
||||
@import "mixins";
|
||||
|
||||
.widget-popover {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: $color-white;
|
||||
padding: 0;
|
||||
z-index: 100;
|
||||
@include widget-shadow;
|
||||
|
||||
&--mobile {
|
||||
left: 0;
|
||||
right: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.popover-links {
|
||||
list-style: none;
|
||||
display: grid;
|
||||
|
||||
&__icon {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
margin-right: $small-spacing;
|
||||
}
|
||||
|
||||
&__link-with-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__link {
|
||||
cursor: pointer;
|
||||
padding: 0 $medium-spacing;
|
||||
|
||||
& > a {
|
||||
display: inline-block;
|
||||
color: $color-silver-dark;
|
||||
font-family: $sans-serif-font-family;
|
||||
font-size: toRem(14px);
|
||||
line-height: 1.5;
|
||||
padding: 5px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&--large {
|
||||
line-height: 40px;
|
||||
padding: $small-spacing $medium-spacing;
|
||||
|
||||
& > a, & {
|
||||
@include small-text;
|
||||
}
|
||||
}
|
||||
|
||||
&--emph {
|
||||
@include regular-text;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
&__divider {
|
||||
border-top: 1px solid $color-silver-dark;
|
||||
}
|
||||
}
|
||||
|
|
@ -22,3 +22,6 @@
|
|||
@import "public-page";
|
||||
@import "student-submission";
|
||||
@import "module-activity";
|
||||
@import "book-subnavigation";
|
||||
@import "simple-list";
|
||||
@import "widget-popover";
|
||||
|
|
|
|||
|
|
@ -46,6 +46,12 @@ def get_graphql_query(filename):
|
|||
|
||||
|
||||
def get_graphql_mutation(filename):
|
||||
"""
|
||||
Get the GraphQL mutation from the mutation directory
|
||||
:param filename: the filename of the mutation
|
||||
:return: the mutation
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
with io.open(os.path.join(settings.GRAPHQL_MUTATIONS_DIR, filename)) as f:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from graphql_relay import to_global_id
|
|||
from api.test_utils import create_client, DefaultUserTestCase
|
||||
from assignments.models import Assignment, StudentSubmission
|
||||
from users.factories import SchoolClassFactory
|
||||
from users.models import SchoolClassMember
|
||||
from ..factories import AssignmentFactory, StudentSubmissionFactory, SubmissionFeedbackFactory
|
||||
|
||||
|
||||
|
|
@ -25,13 +26,16 @@ class SubmissionFeedbackTestCase(DefaultUserTestCase):
|
|||
)
|
||||
self.assignment_id = to_global_id('AssignmentNode', self.assignment.pk)
|
||||
|
||||
self.student_submission = StudentSubmissionFactory(assignment=self.assignment, student=self.student1, final=False)
|
||||
self.student_submission = StudentSubmissionFactory(assignment=self.assignment, student=self.student1,
|
||||
final=False)
|
||||
self.student_submission_id = to_global_id('StudentSubmissionNode', self.student_submission.pk)
|
||||
|
||||
school_class = SchoolClassFactory()
|
||||
school_class.users.add(self.student1)
|
||||
school_class.users.add(self.teacher)
|
||||
school_class.users.add(self.teacher2)
|
||||
for user in [self.student1, self.teacher, self.teacher2]:
|
||||
SchoolClassMember.objects.create(
|
||||
user=user,
|
||||
school_class=school_class
|
||||
)
|
||||
|
||||
def _create_submission_feedback(self, user, final, text, student_submission_id):
|
||||
mutation = '''
|
||||
|
|
@ -122,19 +126,17 @@ class SubmissionFeedbackTestCase(DefaultUserTestCase):
|
|||
})
|
||||
|
||||
def test_teacher_can_create_feedback(self):
|
||||
|
||||
result = self._create_submission_feedback(self.teacher, False, 'Balalal', self.student_submission_id)
|
||||
|
||||
self.assertIsNone(result.get('errors'))
|
||||
self.assertIsNotNone(result.get('data').get('updateSubmissionFeedback').get('updatedSubmissionFeedback').get('id'))
|
||||
self.assertIsNotNone(
|
||||
result.get('data').get('updateSubmissionFeedback').get('updatedSubmissionFeedback').get('id'))
|
||||
|
||||
def test_student_cannot_create_feedback(self):
|
||||
|
||||
result = self._create_submission_feedback(self.student1, False, 'Balalal', self.student_submission_id)
|
||||
self.assertIsNotNone(result.get('errors'))
|
||||
|
||||
def test_teacher_can_update_feedback(self):
|
||||
|
||||
assignment = AssignmentFactory(
|
||||
owner=self.teacher
|
||||
)
|
||||
|
|
@ -148,13 +150,13 @@ class SubmissionFeedbackTestCase(DefaultUserTestCase):
|
|||
|
||||
self.assertIsNone(result.get('errors'))
|
||||
|
||||
submission_feedback_response = result.get('data').get('updateSubmissionFeedback').get('updatedSubmissionFeedback')
|
||||
submission_feedback_response = result.get('data').get('updateSubmissionFeedback').get(
|
||||
'updatedSubmissionFeedback')
|
||||
|
||||
self.assertTrue(submission_feedback_response.get('final'))
|
||||
self.assertEqual(submission_feedback_response.get('text'), 'Some')
|
||||
|
||||
def test_rogue_teacher_cannot_update_feedback(self):
|
||||
|
||||
assignment = AssignmentFactory(
|
||||
owner=self.teacher
|
||||
)
|
||||
|
|
@ -169,14 +171,12 @@ class SubmissionFeedbackTestCase(DefaultUserTestCase):
|
|||
self.assertIsNotNone(result.get('errors'))
|
||||
|
||||
def test_student_does_not_see_non_final_feedback(self):
|
||||
|
||||
SubmissionFeedbackFactory(teacher=self.teacher, final=False, student_submission=self.student_submission)
|
||||
result = self._fetch_assignment_student(self.student1)
|
||||
|
||||
self.assertIsNone(result.get('data').get('submissionFeedback'))
|
||||
|
||||
def test_student_does_see_final_feedback(self):
|
||||
|
||||
submission_feedback = SubmissionFeedbackFactory(teacher=self.teacher, final=True,
|
||||
student_submission=self.student_submission)
|
||||
result = self._fetch_assignment_student(self.student1)
|
||||
|
|
@ -195,7 +195,7 @@ class SubmissionFeedbackTestCase(DefaultUserTestCase):
|
|||
|
||||
def test_rogue_teacher_cannot_see_feedback(self):
|
||||
SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
||||
student_submission=self.student_submission)
|
||||
student_submission=self.student_submission)
|
||||
self.student_submission.final = True
|
||||
self.student_submission.save()
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue