Merged in feature/highlight-proof-of-concept (pull request #38)
Feature/highlight proof of concept Approved-by: Christian Cueni <christian.cueni@iterativ.ch>
This commit is contained in:
commit
9462665826
3
Pipfile
3
Pipfile
|
|
@ -35,7 +35,8 @@ django-libsass = "*"
|
|||
bleach = "*"
|
||||
newrelic = "*"
|
||||
sentry-sdk = "==0.7.2"
|
||||
"django-sendgrid-v5" = "*"
|
||||
"django-sendgrid-v5" = "==0.8.0"
|
||||
python-http-client = "==3.2.1"
|
||||
coverage = "*"
|
||||
graphql-relay = "*"
|
||||
ipython = "*"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "85020e50720b4f71b864719a7c4fae8a0cb4e80352d3bc7eb1e4726bf2405f6d"
|
||||
"sha256": "725dd26226fe58559f67b30a09dec72086dc4681a69f2f2672f5bd87c9ac74b8"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
|
@ -23,6 +23,14 @@
|
|||
],
|
||||
"version": "==7.0.0"
|
||||
},
|
||||
"appnope": {
|
||||
"hashes": [
|
||||
"sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0",
|
||||
"sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"
|
||||
],
|
||||
"markers": "sys_platform == 'darwin'",
|
||||
"version": "==0.1.0"
|
||||
},
|
||||
"backcall": {
|
||||
"hashes": [
|
||||
"sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4",
|
||||
|
|
@ -48,18 +56,18 @@
|
|||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:778e66711d7de9352b6330692ae44c0ba012559dabb4c39d7416b0135fb335a6",
|
||||
"sha256:c8371f1f9c52f64cef1f14a773629fc8434ecca6195b2ef2a429a7bbbf8ecf23"
|
||||
"sha256:08d949fede71c14db8b9b638edaa13831d79daed84e2da27750629fd606bdb57",
|
||||
"sha256:4d7c2cc266917cd0ff7e5e039158de80991e21696a2e8bf85201de2d06d7ceea"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.9.228"
|
||||
"version": "==1.10.9"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:7c391c46cf1f8d6c04758f84b51337a64136077e4a160eced87551fdcc051669",
|
||||
"sha256:c9148df92ba21a90ea32f2c7f185c31b1c8b8e48417d0ba8cad02b9b3336c09a"
|
||||
"sha256:61ad58e737e7a5d61308599606cd5a435cc3b97eb7fa693f99663c91bf1706d1",
|
||||
"sha256:8cb038c110822681925a1f5d9005dc2bbc4259fff89d4abfaaf803a3489d0ee3"
|
||||
],
|
||||
"version": "==1.12.228"
|
||||
"version": "==1.13.9"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
|
|
@ -122,10 +130,10 @@
|
|||
},
|
||||
"decorator": {
|
||||
"hashes": [
|
||||
"sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de",
|
||||
"sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"
|
||||
"sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce",
|
||||
"sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"
|
||||
],
|
||||
"version": "==4.4.0"
|
||||
"version": "==4.4.1"
|
||||
},
|
||||
"dj-database-url": {
|
||||
"hashes": [
|
||||
|
|
@ -242,9 +250,9 @@
|
|||
},
|
||||
"draftjs-exporter": {
|
||||
"hashes": [
|
||||
"sha256:503f222c81de9a0619158d8f88b638f9069af8de233dc020faa782c7a3b22100"
|
||||
"sha256:5839cbc29d7bce2fb99837a404ca40c3a07313f2a20e2700de7ad6aa9a9a18fb"
|
||||
],
|
||||
"version": "==2.1.6"
|
||||
"version": "==2.1.7"
|
||||
},
|
||||
"factory-boy": {
|
||||
"hashes": [
|
||||
|
|
@ -256,16 +264,16 @@
|
|||
},
|
||||
"faker": {
|
||||
"hashes": [
|
||||
"sha256:1d3f700e8dfcefd6e657118d71405d53e86974448aba78884f119bbd84c0cddf",
|
||||
"sha256:d5366e120191c5610fceeebfe1c298dc46da0277096f639c6dd7e2eaee0fa547"
|
||||
"sha256:5902379d8df308a204fc11c4f621590ee83975805a6c7b2228203b9defa45250",
|
||||
"sha256:5e8c755c619f332d5ec28b7586389665f136bcf528e165eb925e87c06a63eda7"
|
||||
],
|
||||
"version": "==2.0.1"
|
||||
"version": "==2.0.3"
|
||||
},
|
||||
"future": {
|
||||
"hashes": [
|
||||
"sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"
|
||||
"sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
|
||||
],
|
||||
"version": "==0.17.1"
|
||||
"version": "==0.18.2"
|
||||
},
|
||||
"graphene": {
|
||||
"hashes": [
|
||||
|
|
@ -322,11 +330,11 @@
|
|||
},
|
||||
"ipython": {
|
||||
"hashes": [
|
||||
"sha256:c4ab005921641e40a68e405e286e7a1fcc464497e14d81b6914b4fd95e5dee9b",
|
||||
"sha256:dd76831f065f17bddd7eaa5c781f5ea32de5ef217592cf019e34043b56895aa1"
|
||||
"sha256:dfd303b270b7b5232b3d08bd30ec6fd685d8a58cabd54055e3d69d8f029f7280",
|
||||
"sha256:ed7ebe1cba899c1c3ccad6f7f1c2d2369464cc77dba8eebc65e2043e19cda995"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==7.8.0"
|
||||
"version": "==7.9.0"
|
||||
},
|
||||
"ipython-genutils": {
|
||||
"hashes": [
|
||||
|
|
@ -351,30 +359,31 @@
|
|||
},
|
||||
"libsass": {
|
||||
"hashes": [
|
||||
"sha256:2457723fe04f4e690105f758aa125e809afc840812965095fa3f4edccd6275ef",
|
||||
"sha256:2974772e7984b27a51a6d91ebc140183ddd574a9663bd02154ddfb75f13a3eed",
|
||||
"sha256:2d067ce4f393fee2ce52bb810a364deac5454dfdb7945d31d1f4265f21f03ab8",
|
||||
"sha256:57d0b99c4e3512233a44141f1bf852570d359724a606dfc4550eccd0f570460d",
|
||||
"sha256:5b604e4f5befdecc76240c2ba243fd7e23c642ffc2dd86cbfd094a44ead6b08d",
|
||||
"sha256:5dd647ffa1319a2a18572f41fee3bb561d7f77d8d4784074a00b2eb22c61a859",
|
||||
"sha256:78f3f14e47612be4fa4b161278f2a3e880a19b6a3367f749e9ae240434b7e7f5",
|
||||
"sha256:8d423e4b4c0e219488104b4ec4267688dbd816f3ae806beb4201918eff059b2d",
|
||||
"sha256:a20473b0427d82e37fa68f0b3a8d219f0bb5ca6d3f7d93b0f5342219285e7064",
|
||||
"sha256:c1f76c2a0993914f3c3088e9b6c7031f22e879c5d27a060cdc8c5aa1318eb9b6",
|
||||
"sha256:c99fbc950f1955e8b6370aafdb9d84d324e4984a2e00a2b47f04dbcc3706a9d1",
|
||||
"sha256:cb50f385117535f7671ac7ff3144c1ef0b8e088778c58d269ce6f31b87bfad72",
|
||||
"sha256:f0f033a8154be60e1a2e1f79ee849ea69a1d62e5d476a78f69e4c7d8fd7c20e1",
|
||||
"sha256:f2572b73b2e13e74b28388ae86c4fabb853ddbfc12279b4444243bd614710ce8",
|
||||
"sha256:f8790db67e00c5bc7be1bdd81ed477563a4b191e839193ecc0c2c5ec679ec481"
|
||||
"sha256:003a65b4facb4c5dbace53fb0f70f61c5aae056a04b4d112a198c3c9674b31f2",
|
||||
"sha256:0fd8b4337b3b101c6e6afda9112cc0dc4bacb9133b59d75d65968c7317aa3272",
|
||||
"sha256:338e9ae066bf1fde874e335324d5355c52d2081d978b4f74fc59536564b35b08",
|
||||
"sha256:4dcfd561fb100250b89496e1362b96f2cc804f689a59731eb0f94f9a9e144f4a",
|
||||
"sha256:50778d4be269a021ba2bf42b5b8f6ff3704ab96a82175a052680bddf3ba7cc9f",
|
||||
"sha256:6a51393d75f6e3c812785b0fa0b7d67c54258c28011921f204643b55f7355ec0",
|
||||
"sha256:74acd9adf506142699dfa292f0e569fdccbd9e7cf619e8226f7117de73566e32",
|
||||
"sha256:81a013a4c2a614927fd1ef7a386eddabbba695cbb02defe8f31cf495106e974c",
|
||||
"sha256:845a9573b25c141164972d498855f4ad29367c09e6d76fad12955ad0e1c83013",
|
||||
"sha256:8b5b6d1a7c4ea1d954e0982b04474cc076286493f6af2d0a13c2e950fbe0be95",
|
||||
"sha256:9b59afa0d755089c4165516400a39a289b796b5612eeef5736ab7a1ebf96a67c",
|
||||
"sha256:a7e685466448c9b1bf98243339793978f654a1151eb5c975f09b83c7a226f4c1",
|
||||
"sha256:c93df526eeef90b1ea4799c1d33b6cd5aea3e9f4633738fb95c1287c13e6b404",
|
||||
"sha256:e318f06f06847ff49b1f8d086ac9ebce1e63404f7ea329adab92f4f16ba0e00e",
|
||||
"sha256:fc5f8336750f76f1bfae82f7e9e89ae71438d26fc4597e3ab4c05ca8fcd41d8a",
|
||||
"sha256:fcb7ab4dc81889e5fc99cafbc2017bc76996f9992fc6b175f7a80edac61d71df"
|
||||
],
|
||||
"version": "==0.19.2"
|
||||
"version": "==0.19.4"
|
||||
},
|
||||
"newrelic": {
|
||||
"hashes": [
|
||||
"sha256:9d6d3bf2e125410d485fd91279e1b0f50e8f0f5887284b345aed4ec81db33c0a"
|
||||
"sha256:da9adab674d9fe7aa8fbabb6691b33fb7be94a32b6a80548ec7018be9df8ef65"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.0.2.126"
|
||||
"version": "==5.2.1.129"
|
||||
},
|
||||
"parso": {
|
||||
"hashes": [
|
||||
|
|
@ -438,11 +447,11 @@
|
|||
},
|
||||
"prompt-toolkit": {
|
||||
"hashes": [
|
||||
"sha256:11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780",
|
||||
"sha256:2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1",
|
||||
"sha256:977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55"
|
||||
"sha256:46642344ce457641f28fc9d1c9ca939b63dadf8df128b86f1b9860e59c73a5e4",
|
||||
"sha256:e7f8af9e3d70f514373bf41aa51bc33af12a6db3f71461ea47fea985defb2c31",
|
||||
"sha256:f15af68f66e664eaa559d4ac8a928111eebd5feda0c11738b5998045224829db"
|
||||
],
|
||||
"version": "==2.0.9"
|
||||
"version": "==2.0.10"
|
||||
},
|
||||
"psycopg2": {
|
||||
"hashes": [
|
||||
|
|
@ -517,14 +526,15 @@
|
|||
"sha256:c2776054245db376ea26c859b80e9280b1a470b96ed998d60d35951f89bbbe79",
|
||||
"sha256:e455ae0dfd5819ac483f7fecf08ab8693048d9dc47a0a6fe0d4aebf86d9d1d17"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.2.1"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32",
|
||||
"sha256:c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7"
|
||||
"sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
|
||||
"sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
|
||||
],
|
||||
"version": "==2019.2"
|
||||
"version": "==2019.3"
|
||||
},
|
||||
"raven": {
|
||||
"hashes": [
|
||||
|
|
@ -611,17 +621,17 @@
|
|||
},
|
||||
"text-unidecode": {
|
||||
"hashes": [
|
||||
"sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d",
|
||||
"sha256:801e38bd550b943563660a91de8d4b6fa5df60a542be9093f7abf819f86050cc"
|
||||
"sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8",
|
||||
"sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"
|
||||
],
|
||||
"version": "==1.2"
|
||||
"version": "==1.3"
|
||||
},
|
||||
"traitlets": {
|
||||
"hashes": [
|
||||
"sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835",
|
||||
"sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9"
|
||||
"sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44",
|
||||
"sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7"
|
||||
],
|
||||
"version": "==4.3.2"
|
||||
"version": "==4.3.3"
|
||||
},
|
||||
"typing": {
|
||||
"hashes": [
|
||||
|
|
@ -640,11 +650,11 @@
|
|||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
|
||||
"sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
|
||||
"sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398",
|
||||
"sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86"
|
||||
],
|
||||
"markers": "python_version >= '3.4'",
|
||||
"version": "==1.25.3"
|
||||
"version": "==1.25.6"
|
||||
},
|
||||
"wagtail": {
|
||||
"hashes": [
|
||||
|
|
@ -689,13 +699,21 @@
|
|||
}
|
||||
},
|
||||
"develop": {
|
||||
"appnope": {
|
||||
"hashes": [
|
||||
"sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0",
|
||||
"sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"
|
||||
],
|
||||
"markers": "sys_platform == 'darwin'",
|
||||
"version": "==0.1.0"
|
||||
},
|
||||
"awscli": {
|
||||
"hashes": [
|
||||
"sha256:5c36a818130c8393b778e5b98b9bf38985522b62a684782512a2d57340697582",
|
||||
"sha256:a022dfb7e6cc9ee8540c382b9bdc4637070dbbe2b09f3a74ad4f30719414c0b7"
|
||||
"sha256:4a75cb44dc3dab14bc9bdb0d2731c37a5026bf0afa4acb620fec72c74e62915a",
|
||||
"sha256:90b0b3e91a900e4569bc47f29769522337c46ff50e35f9e4a41830fdb425f000"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.16.238"
|
||||
"version": "==1.16.273"
|
||||
},
|
||||
"backcall": {
|
||||
"hashes": [
|
||||
|
|
@ -706,17 +724,18 @@
|
|||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:7c391c46cf1f8d6c04758f84b51337a64136077e4a160eced87551fdcc051669",
|
||||
"sha256:c9148df92ba21a90ea32f2c7f185c31b1c8b8e48417d0ba8cad02b9b3336c09a"
|
||||
"sha256:61ad58e737e7a5d61308599606cd5a435cc3b97eb7fa693f99663c91bf1706d1",
|
||||
"sha256:8cb038c110822681925a1f5d9005dc2bbc4259fff89d4abfaaf803a3489d0ee3"
|
||||
],
|
||||
"version": "==1.12.228"
|
||||
"version": "==1.13.9"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
"sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda",
|
||||
"sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"
|
||||
"sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d",
|
||||
"sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"
|
||||
],
|
||||
"version": "==0.3.9"
|
||||
"markers": "python_version != '2.6' and python_version != '3.3'",
|
||||
"version": "==0.4.1"
|
||||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
|
|
@ -758,10 +777,10 @@
|
|||
},
|
||||
"decorator": {
|
||||
"hashes": [
|
||||
"sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de",
|
||||
"sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"
|
||||
"sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce",
|
||||
"sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"
|
||||
],
|
||||
"version": "==4.4.0"
|
||||
"version": "==4.4.1"
|
||||
},
|
||||
"docutils": {
|
||||
"hashes": [
|
||||
|
|
@ -780,11 +799,11 @@
|
|||
},
|
||||
"ipython": {
|
||||
"hashes": [
|
||||
"sha256:c4ab005921641e40a68e405e286e7a1fcc464497e14d81b6914b4fd95e5dee9b",
|
||||
"sha256:dd76831f065f17bddd7eaa5c781f5ea32de5ef217592cf019e34043b56895aa1"
|
||||
"sha256:dfd303b270b7b5232b3d08bd30ec6fd685d8a58cabd54055e3d69d8f029f7280",
|
||||
"sha256:ed7ebe1cba899c1c3ccad6f7f1c2d2369464cc77dba8eebc65e2043e19cda995"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==7.8.0"
|
||||
"version": "==7.9.0"
|
||||
},
|
||||
"ipython-genutils": {
|
||||
"hashes": [
|
||||
|
|
@ -831,11 +850,11 @@
|
|||
},
|
||||
"prompt-toolkit": {
|
||||
"hashes": [
|
||||
"sha256:11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780",
|
||||
"sha256:2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1",
|
||||
"sha256:977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55"
|
||||
"sha256:46642344ce457641f28fc9d1c9ca939b63dadf8df128b86f1b9860e59c73a5e4",
|
||||
"sha256:e7f8af9e3d70f514373bf41aa51bc33af12a6db3f71461ea47fea985defb2c31",
|
||||
"sha256:f15af68f66e664eaa559d4ac8a928111eebd5feda0c11738b5998045224829db"
|
||||
],
|
||||
"version": "==2.0.9"
|
||||
"version": "==2.0.10"
|
||||
},
|
||||
"ptyprocess": {
|
||||
"hashes": [
|
||||
|
|
@ -882,7 +901,7 @@
|
|||
"sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41",
|
||||
"sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"
|
||||
],
|
||||
"markers": "python_version != '2.6'",
|
||||
"markers": "python_version != '2.6' and python_version != '3.3'",
|
||||
"version": "==5.1.2"
|
||||
},
|
||||
"rsa": {
|
||||
|
|
@ -908,18 +927,18 @@
|
|||
},
|
||||
"traitlets": {
|
||||
"hashes": [
|
||||
"sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835",
|
||||
"sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9"
|
||||
"sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44",
|
||||
"sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7"
|
||||
],
|
||||
"version": "==4.3.2"
|
||||
"version": "==4.3.3"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
|
||||
"sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
|
||||
"sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398",
|
||||
"sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86"
|
||||
],
|
||||
"markers": "python_version >= '3.4'",
|
||||
"version": "==1.25.3"
|
||||
"version": "==1.25.6"
|
||||
},
|
||||
"wcwidth": {
|
||||
"hashes": [
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ dist/
|
|||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
cypress/videos
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
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 FullscreenImage from '@/components/FullscreenImage';
|
||||
import FullscreenInfographic from '@/components/FullscreenInfographic';
|
||||
import FullscreenVideo from '@/components/FullscreenVideo';
|
||||
|
|
@ -50,6 +52,8 @@
|
|||
NewProjectEntryWizard,
|
||||
EditProjectEntryWizard,
|
||||
NewObjectiveWizard,
|
||||
NewNoteWizard,
|
||||
EditNoteWizard,
|
||||
FullscreenImage,
|
||||
FullscreenInfographic,
|
||||
FullscreenVideo
|
||||
|
|
|
|||
|
|
@ -18,11 +18,15 @@
|
|||
<h3 v-if="instrumentLabel !== ''" class="content-block__instrument-label">{{instrumentLabel}}</h3>
|
||||
<h4 class="content-block__title" v-if="!contentBlock.indent">{{contentBlock.title}}</h4>
|
||||
|
||||
<component v-for="component in contentBlocksWithContentLists.contents"
|
||||
:key="component.id"
|
||||
:is="component.type"
|
||||
v-bind="component">
|
||||
</component>
|
||||
<content-component v-for="component in contentBlocksWithContentLists.contents"
|
||||
:key="component.id"
|
||||
:component="component"
|
||||
:root="root"
|
||||
:parent="contentBlock"
|
||||
:bookmarks="contentBlock.bookmarks"
|
||||
:notes="contentBlock.notes"
|
||||
>
|
||||
</content-component>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -33,22 +37,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import TextBlock from '@/components/content-blocks/TextBlock';
|
||||
import InstrumentWidget from '@/components/content-blocks/InstrumentWidget';
|
||||
import Task from '@/components/content-blocks/Task';
|
||||
import ImageBlock from '@/components/content-blocks/ImageBlock';
|
||||
import ImageUrlBlock from '@/components/content-blocks/ImageUrlBlock';
|
||||
import VideoBlock from '@/components/content-blocks/VideoBlock';
|
||||
import LinkBlock from '@/components/content-blocks/LinkBlock';
|
||||
import DocumentBlock from '@/components/content-blocks/DocumentBlock';
|
||||
import InfogramBlock from '@/components/content-blocks/InfogramBlock';
|
||||
import GeniallyBlock from '@/components/content-blocks/GeniallyBlock';
|
||||
import ThinglinkBlock from '@/components/content-blocks/ThinglinkBlock';
|
||||
import SubtitleBlock from '@/components/content-blocks/SubtitleBlock';
|
||||
import ContentListBlock from '@/components/content-blocks/ContentListBlock';
|
||||
import Assignment from '@/components/content-blocks/assignment/Assignment';
|
||||
import Survey from '@/components/content-blocks/SurveyBlock';
|
||||
import Solution from '@/components/content-blocks/Solution';
|
||||
import AddContentButton from '@/components/AddContentButton';
|
||||
import MoreOptionsWidget from '@/components/MoreOptionsWidget';
|
||||
import UserWidget from '@/components/UserWidget';
|
||||
|
|
@ -56,7 +44,7 @@
|
|||
import EyeIcon from '@/components/icons/EyeIcon';
|
||||
import PenIcon from '@/components/icons/PenIcon';
|
||||
import TrashIcon from '@/components/icons/TrashIcon';
|
||||
import ModuleRoomSlug from '@/components/content-blocks/ModuleRoomSlug'
|
||||
import ContentComponent from '@/components/content-blocks/ContentComponent';
|
||||
|
||||
import CHAPTER_QUERY from '@/graphql/gql/chapterQuery.gql';
|
||||
import DELETE_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/deleteContentBlock.gql';
|
||||
|
|
@ -77,24 +65,7 @@
|
|||
name: 'content-block',
|
||||
|
||||
components: {
|
||||
'text_block': TextBlock,
|
||||
'basic_knowledge': InstrumentWidget, // for legacy
|
||||
'instrument': InstrumentWidget,
|
||||
'image_block': ImageBlock,
|
||||
'image_url_block': ImageUrlBlock,
|
||||
'video_block': VideoBlock,
|
||||
'link_block': LinkBlock,
|
||||
'document_block': DocumentBlock,
|
||||
'infogram_block': InfogramBlock,
|
||||
'genially_block': GeniallyBlock,
|
||||
'thinglink_block': ThinglinkBlock,
|
||||
'subtitle': SubtitleBlock,
|
||||
'content_list': ContentListBlock,
|
||||
'module_room_slug': ModuleRoomSlug,
|
||||
Survey,
|
||||
Solution,
|
||||
Assignment,
|
||||
Task,
|
||||
ContentComponent,
|
||||
AddContentButton,
|
||||
VisibilityAction,
|
||||
EyeIcon,
|
||||
|
|
@ -181,6 +152,10 @@
|
|||
},
|
||||
hidden() {
|
||||
return isHidden(this.contentBlock, this.schoolClass);
|
||||
},
|
||||
root() {
|
||||
// we need the root content block id, not the generated content block if inside a content list block
|
||||
return this.contentBlock.root ? this.contentBlock.root : this.contentBlock.id;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<div class="modal__backdrop">
|
||||
<div class="modal" :class="{'modal--hide-header': hideHeader || fullscreen, 'modal--fullscreen': fullscreen}">
|
||||
<div class="modal"
|
||||
:class="{'modal--hide-header': hideHeader || fullscreen, 'modal--fullscreen': fullscreen, 'modal--small': small}">
|
||||
<div class="modal__header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
|
|
@ -32,6 +33,10 @@
|
|||
fullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
small: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -68,49 +73,6 @@
|
|||
-ms-grid-rows: auto 1fr 65px;
|
||||
position: relative;
|
||||
|
||||
&--hide-header {
|
||||
grid-template-rows: 1fr 65px;
|
||||
grid-template-areas: "body" "footer";
|
||||
}
|
||||
|
||||
&--hide-header &__header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&--hide-header &__body {
|
||||
padding: $default-padding;
|
||||
}
|
||||
|
||||
&--fullscreen {
|
||||
width: 95vw;
|
||||
height: auto;
|
||||
grid-template-rows: 1fr;
|
||||
-ms-grid-rows: 1fr;
|
||||
grid-template-areas: "body";
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&--fullscreen &__footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&--fullscreen &__body {
|
||||
padding: 0;
|
||||
scrollbar-width: none;
|
||||
margin-right: -5px;
|
||||
|
||||
height: auto;
|
||||
max-height: 95vh;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&--fullscreen &__close-button {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__backdrop {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
@ -165,5 +127,59 @@
|
|||
border-top: 1px solid $color-silver-light;
|
||||
padding: 16px $modal-lateral-padding;
|
||||
}
|
||||
|
||||
$parent: &;
|
||||
|
||||
&--hide-header {
|
||||
grid-template-rows: 1fr 65px;
|
||||
grid-template-areas: "body" "footer";
|
||||
|
||||
#{$parent}__header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#{$parent}__body {
|
||||
padding: $default-padding;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&--fullscreen {
|
||||
width: 95vw;
|
||||
height: auto;
|
||||
grid-template-rows: 1fr;
|
||||
-ms-grid-rows: 1fr;
|
||||
grid-template-areas: "body";
|
||||
overflow: hidden;
|
||||
|
||||
#{$parent}__footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#{$parent}__body {
|
||||
padding: 0;
|
||||
scrollbar-width: none;
|
||||
margin-right: -5px;
|
||||
|
||||
height: auto;
|
||||
max-height: 95vh;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#{$parent}__close-button {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
&--small {
|
||||
height: auto;
|
||||
|
||||
#{$parent}__body {
|
||||
min-height: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,154 @@
|
|||
<template>
|
||||
<div class="content-component" :class="{'content-component--bookmarked': bookmarked}">
|
||||
<bookmark-actions
|
||||
v-if="showBookmarkActions()"
|
||||
@add-note="addNote(component.id)"
|
||||
@edit-note="editNote"
|
||||
@bookmark="bookmarkContent(component.id, !bookmarked)"
|
||||
:bookmarked="bookmarked"
|
||||
:note="note"></bookmark-actions>
|
||||
<component
|
||||
:is="component.type"
|
||||
v-bind="component"
|
||||
:parent="parent"
|
||||
>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
import TextBlock from '@/components/content-blocks/TextBlock';
|
||||
import InstrumentWidget from '@/components/content-blocks/InstrumentWidget';
|
||||
import ImageBlock from '@/components/content-blocks/ImageBlock';
|
||||
import ImageUrlBlock from '@/components/content-blocks/ImageUrlBlock';
|
||||
import VideoBlock from '@/components/content-blocks/VideoBlock';
|
||||
import LinkBlock from '@/components/content-blocks/LinkBlock';
|
||||
import DocumentBlock from '@/components/content-blocks/DocumentBlock';
|
||||
import InfogramBlock from '@/components/content-blocks/InfogramBlock';
|
||||
import GeniallyBlock from '@/components/content-blocks/GeniallyBlock';
|
||||
import SubtitleBlock from '@/components/content-blocks/SubtitleBlock';
|
||||
import ContentListBlock from '@/components/content-blocks/ContentListBlock';
|
||||
import ModuleRoomSlug from '@/components/content-blocks/ModuleRoomSlug';
|
||||
import Assignment from '@/components/content-blocks/assignment/Assignment';
|
||||
import Survey from '@/components/content-blocks/SurveyBlock';
|
||||
import Solution from '@/components/content-blocks/Solution';
|
||||
import BookmarkActions from '@/components/notes/BookmarkActions';
|
||||
|
||||
import UPDATE_CONTENT_BOOKMARK from '@/graphql/gql/mutations/updateContentBookmark.gql';
|
||||
import CONTENT_BLOCK_QUERY from '@/graphql/gql/contentBlockQuery.gql';
|
||||
|
||||
export default {
|
||||
props: ['component', 'parent', 'bookmarks', 'notes', 'root'],
|
||||
|
||||
components: {
|
||||
'text_block': TextBlock,
|
||||
'basic_knowledge': InstrumentWidget, // for legacy
|
||||
'instrument': InstrumentWidget,
|
||||
'image_block': ImageBlock,
|
||||
'image_url_block': ImageUrlBlock,
|
||||
'video_block': VideoBlock,
|
||||
'link_block': LinkBlock,
|
||||
'document_block': DocumentBlock,
|
||||
'infogram_block': InfogramBlock,
|
||||
'genially_block': GeniallyBlock,
|
||||
'subtitle': SubtitleBlock,
|
||||
'content_list': ContentListBlock,
|
||||
'module_room_slug': ModuleRoomSlug,
|
||||
Survey,
|
||||
Solution,
|
||||
Assignment,
|
||||
BookmarkActions
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['editModule']),
|
||||
bookmarked() {
|
||||
return this.bookmarks && !!this.bookmarks.find(bookmark => bookmark.uuid === this.component.id);
|
||||
},
|
||||
note() {
|
||||
const bookmark = this.bookmarks && this.bookmarks.find(bookmark => bookmark.uuid === this.component.id);
|
||||
return bookmark && bookmark.note;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addNote(id) {
|
||||
this.$store.dispatch('addNote', {
|
||||
content: id,
|
||||
contentBlock: this.root
|
||||
});
|
||||
},
|
||||
editNote() {
|
||||
this.$store.dispatch('editNote', this.note);
|
||||
},
|
||||
bookmarkContent(uuid, bookmarked) {
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_CONTENT_BOOKMARK,
|
||||
variables: {
|
||||
input: {
|
||||
uuid,
|
||||
contentBlock: this.root,
|
||||
bookmarked
|
||||
}
|
||||
},
|
||||
update: (store, response) => {
|
||||
const query = CONTENT_BLOCK_QUERY;
|
||||
const variables = {id: this.root};
|
||||
const data = store.readQuery({
|
||||
query,
|
||||
variables
|
||||
});
|
||||
|
||||
const bookmarks = data.contentBlock.bookmarks;
|
||||
|
||||
if (bookmarked) {
|
||||
bookmarks.push({
|
||||
note: null,
|
||||
uuid: uuid,
|
||||
__typename: 'ContentBlockBookmarkNode'
|
||||
});
|
||||
} else {
|
||||
let index = bookmarks.findIndex(element => {
|
||||
return element.uuid === uuid;
|
||||
});
|
||||
if (index > -1) {
|
||||
bookmarks.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
data.contentBlock.bookmarks = bookmarks;
|
||||
|
||||
store.writeQuery({
|
||||
data,
|
||||
query,
|
||||
variables
|
||||
});
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
updateContentBookmark: {
|
||||
__typename: 'UpdateContentBookmarkPayload',
|
||||
success: true
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
showBookmarkActions() {
|
||||
return this.component.type !== 'content_list' && this.component.type !== 'basic_knowledge' && !this.editModule;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
.content-component {
|
||||
position: relative;
|
||||
&--bookmarked {
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -6,7 +6,10 @@
|
|||
:key="contentBlock.id"
|
||||
v-for="(contentBlock, index) in contentBlocks">
|
||||
<p class="content-list__numbering">{{alphaIndex(index)}})</p>
|
||||
<content-block :contentBlock="contentBlock"></content-block>
|
||||
<content-block
|
||||
:contentBlock="contentBlock"
|
||||
:parent="parent"
|
||||
></content-block>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
|
@ -38,7 +41,10 @@
|
|||
return this.contents.map(contentBlock => {
|
||||
return Object.assign({}, contentBlock, {
|
||||
contents: [...contentBlock.value],
|
||||
indent: true
|
||||
indent: true,
|
||||
bookmarks: this.parent.bookmarks,
|
||||
notes: this.parent.notes,
|
||||
root: this.parent.id
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
@ -57,7 +63,7 @@
|
|||
&__item {
|
||||
list-style: none;
|
||||
position: relative;
|
||||
padding: 0 2*15px;
|
||||
padding: 0 0 0 2*15px;
|
||||
}
|
||||
|
||||
&__numbering {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<svg class="add-note-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<path
|
||||
d="M81.5,88.39746H18.7627a2.49981,2.49981,0,0,1-2.5-2.5V35.35352L1.72559,20.71191A2.50054,2.50054,0,0,1,3.5,16.4502h78a2.49981,2.49981,0,0,1,2.5,2.5V85.89746A2.49981,2.49981,0,0,1,81.5,88.39746Zm-60.2373-5H79V21.4502H9.50488L20.53711,32.56152a2.5013,2.5013,0,0,1,.72559,1.76172Z"/>
|
||||
<path d="M64.9209,55.08447H36.18457a2.5,2.5,0,0,1,0-5H64.9209a2.5,2.5,0,0,1,0,5Z"/>
|
||||
<path d="M48.26318,66.95313V38.21582a2.5,2.5,0,0,1,5,0v28.7373a2.5,2.5,0,0,1-5,0Z"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.add-note-icon {
|
||||
width: 29px;
|
||||
height: 25px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" class="bookmark-icon">
|
||||
<g :class="{'bookmark-icon--bookmarked': bookmarked}">
|
||||
<path class="bookmark-icon__background"
|
||||
d="M51,67.32872a5.06849,5.06849,0,0,1,2.98875.97385L84,90V11H18V90L48.01333,68.30149A5.064,5.064,0,0,1,51,67.32872Z"
|
||||
/>
|
||||
<path id="bookmark-icon__outline"
|
||||
d="M84.5,93.07715a2.49662,2.49662,0,0,1-1.43359-.45215L51,70.17871,18.93359,92.625A2.49964,2.49964,0,0,1,15,90.57715V11.42285a2.49981,2.49981,0,0,1,2.5-2.5h67a2.49981,2.49981,0,0,1,2.5,2.5v79.1543a2.49947,2.49947,0,0,1-2.5,2.5ZM51,65.15527a4.8673,4.8673,0,0,1,2.80762.88574L82,85.77539V13.92285H20V85.77539L48.19434,66.04A4.863,4.863,0,0,1,51,65.15527Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['bookmarked']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
.bookmark-icon {
|
||||
width: 24px;
|
||||
height: 28px;
|
||||
|
||||
&__background {
|
||||
fill: white;
|
||||
}
|
||||
|
||||
$parent: &;
|
||||
|
||||
&--bookmarked {
|
||||
#{$parent}__background {
|
||||
fill: $color-accent-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<svg class="note-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<path
|
||||
d="M81.5,88.39746H18.7627a2.49981,2.49981,0,0,1-2.5-2.5V35.35352L1.72559,20.71191A2.50054,2.50054,0,0,1,3.5,16.4502h78a2.49981,2.49981,0,0,1,2.5,2.5V85.89746A2.49981,2.49981,0,0,1,81.5,88.39746Zm-60.2373-5H79V21.4502H9.50488L20.53711,32.56152a2.5013,2.5013,0,0,1,.72559,1.76172Z"/>
|
||||
<path d="M61.9209,40.92676H39.18457a2.5,2.5,0,0,1,0-5H61.9209a2.5,2.5,0,0,1,0,5Z"/>
|
||||
<path d="M62.13184,55.24219H39.39453a2.5,2.5,0,0,1,0-5h22.7373a2.5,2.5,0,0,1,0,5Z"/>
|
||||
<path d="M62.13184,69.55859H39.39453a2.5,2.5,0,0,1,0-5h22.7373a2.5,2.5,0,0,1,0,5Z"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.note-icon {
|
||||
width: 29px;
|
||||
height: 25px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<template>
|
||||
<div class="bookmark-actions">
|
||||
<a class="bookmark-actions__action" @click="$emit('bookmark')"
|
||||
:class="{'bookmark-actions__action--bookmarked': bookmarked}">
|
||||
<bookmark-icon :bookmarked="bookmarked"></bookmark-icon>
|
||||
</a>
|
||||
<a class="bookmark-actions__action" v-if="bookmarked && !note" @click="$emit('add-note')">
|
||||
<add-note-icon></add-note-icon>
|
||||
</a>
|
||||
<a class="bookmark-actions__action bookmark-actions__action--noted" @click="$emit('edit-note')" v-if="note">
|
||||
<note-icon></note-icon>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BookmarkIcon from '@/components/icons/BookmarkIcon';
|
||||
import AddNoteIcon from '@/components/icons/AddNoteIcon';
|
||||
import NoteIcon from '@/components/icons/NoteIcon';
|
||||
|
||||
export default {
|
||||
props: ['bookmarked', 'note'],
|
||||
components: {
|
||||
BookmarkIcon,
|
||||
AddNoteIcon,
|
||||
NoteIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.bookmark-actions {
|
||||
height: 100%;
|
||||
min-height: 60px;
|
||||
|
||||
padding: 0 2*$large-spacing;
|
||||
position: absolute;
|
||||
right: -5*$large-spacing;
|
||||
|
||||
display: none;
|
||||
|
||||
@include desktop {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
flex-direction: column;
|
||||
align-content: center;
|
||||
|
||||
&__action {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
cursor: pointer;
|
||||
width: 26px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
&--bookmarked, &--noted {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
$parent: &;
|
||||
|
||||
&:hover {
|
||||
#{$parent}__action {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<note-form @save="editNote" @hide="hide" :note="currentNote"></note-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NoteForm from '@/components/notes/NoteForm';
|
||||
|
||||
import UPDATE_NOTE_MUTATION from '@/graphql/gql/mutations/updateNote.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
|
||||
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NoteForm
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['currentNote'])
|
||||
},
|
||||
|
||||
methods: {
|
||||
editNote(note) {
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_NOTE_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
note
|
||||
}
|
||||
},
|
||||
refetchQueries: [{
|
||||
query: MODULE_DETAILS_QUERY,
|
||||
variables: {
|
||||
slug: this.$route.params.slug
|
||||
}
|
||||
}]
|
||||
}).then(() => {
|
||||
this.$store.dispatch('hideModal');
|
||||
});
|
||||
},
|
||||
hide() {
|
||||
this.$store.dispatch('hideModal');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<note-form @save="addNote" @hide="hide" :note="note"></note-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NoteForm from '@/components/notes/NoteForm';
|
||||
|
||||
import ADD_NOTE_MUTATION from '@/graphql/gql/mutations/addNote.gql';
|
||||
import CONTENT_BLOCK_QUERY from '@/graphql/gql/contentBlockQuery.gql';
|
||||
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NoteForm
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
note: {}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['currentContent', 'currentContentBlock'])
|
||||
},
|
||||
|
||||
methods: {
|
||||
addNote(note) {
|
||||
const content = this.currentContent;
|
||||
const contentBlock = this.currentContentBlock;
|
||||
const text = note.text;
|
||||
|
||||
this.$apollo.mutate({
|
||||
mutation: ADD_NOTE_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
note: {
|
||||
content,
|
||||
contentBlock,
|
||||
text
|
||||
}
|
||||
}
|
||||
},
|
||||
update: (store, {data: {addNote: {note}}}) => {
|
||||
const query = CONTENT_BLOCK_QUERY;
|
||||
const variables = {id: contentBlock};
|
||||
const data = store.readQuery({
|
||||
query,
|
||||
variables
|
||||
});
|
||||
|
||||
const bookmarks = data.contentBlock.bookmarks;
|
||||
|
||||
let index = bookmarks.findIndex(element => {
|
||||
return element.uuid === content;
|
||||
});
|
||||
|
||||
if (index > -1) {
|
||||
let el = bookmarks[index];
|
||||
el.note = note;
|
||||
bookmarks.splice(index, 1, el);
|
||||
}
|
||||
|
||||
data.contentBlock.bookmarks = bookmarks;
|
||||
|
||||
store.writeQuery({
|
||||
data,
|
||||
query,
|
||||
variables
|
||||
});
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
addNote: {
|
||||
__typename: 'AddNotePayload',
|
||||
note: {
|
||||
__typename: 'NoteNode',
|
||||
id: -1,
|
||||
text: text
|
||||
}
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
this.$store.dispatch('hideModal');
|
||||
});
|
||||
},
|
||||
hide() {
|
||||
this.$store.dispatch('hideModal');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<modal :hide-header="true" :small="true">
|
||||
<modal-input v-on:input="localNote.text = $event"
|
||||
placeholder="Notiz erfassen"
|
||||
:value="localNote.text"
|
||||
></modal-input>
|
||||
<div slot="footer">
|
||||
<a class="button button--primary" data-cy="modal-save-button"
|
||||
@click="$emit('save', localNote)">Speichern</a>
|
||||
<a class="button" @click="$emit('hide')">Abbrechen</a>
|
||||
</div>
|
||||
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import ModalInput from '@/components/ModalInput';
|
||||
|
||||
export default {
|
||||
props: ['note'],
|
||||
|
||||
components: {
|
||||
Modal,
|
||||
ModalInput
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
localNote: Object.assign({},
|
||||
{
|
||||
...this.note
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -6,6 +6,13 @@ fragment ContentBlockParts on ContentBlockNode {
|
|||
contents
|
||||
userCreated
|
||||
mine
|
||||
bookmarks {
|
||||
uuid
|
||||
note {
|
||||
id
|
||||
text
|
||||
}
|
||||
}
|
||||
hiddenFor {
|
||||
edges {
|
||||
node {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
mutation AddNote($input: AddNoteInput!) {
|
||||
addNote(input: $input) {
|
||||
note {
|
||||
id
|
||||
text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
mutation UpdateContentBookmark($input: UpdateContentBookmarkInput!) {
|
||||
updateContentBookmark(input: $input) {
|
||||
success
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
mutation UpdateNote($input: UpdateNoteInput!) {
|
||||
updateNote(input: $input) {
|
||||
note {
|
||||
id
|
||||
text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ export default new Vuex.Store({
|
|||
showMobileNavigation: false,
|
||||
contentBlockPosition: {},
|
||||
scrollPosition: 0,
|
||||
currentContent: '',
|
||||
currentContentBlock: '',
|
||||
currentRoomEntry: '',
|
||||
parentRoom: null,
|
||||
|
|
@ -19,6 +20,7 @@ export default new Vuex.Store({
|
|||
objectiveGroupType: '',
|
||||
currentObjectiveGroup: '',
|
||||
parentProject: null,
|
||||
currentNote: null,
|
||||
currentProjectEntry: null,
|
||||
imageUrl: '',
|
||||
infographic: {
|
||||
|
|
@ -33,18 +35,17 @@ export default new Vuex.Store({
|
|||
},
|
||||
|
||||
getters: {
|
||||
showModal: state => {
|
||||
return state.showModal
|
||||
},
|
||||
showMobileNavigation: state => {
|
||||
return state.showMobileNavigation
|
||||
},
|
||||
showModal: state => state.showModal,
|
||||
showMobileNavigation: state => state.showMobileNavigation,
|
||||
scrollToAssignmentId: state => state.scrollToAssignmentId,
|
||||
scrollToAssignmentReady: state => state.scrollToAssignmentReady,
|
||||
scrollingToAssignment: state => state.scrollingToAssignment,
|
||||
currentProjectEntry: state => state.currentProjectEntry,
|
||||
editModule: state => state.editModule,
|
||||
currentObjectiveGroup: state => state.currentObjectiveGroup
|
||||
currentObjectiveGroup: state => state.currentObjectiveGroup,
|
||||
currentContent: state => state.currentContent,
|
||||
currentContentBlock: state => state.currentContentBlock,
|
||||
currentNote: state => state.currentNote,
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
|
@ -58,6 +59,7 @@ export default new Vuex.Store({
|
|||
},
|
||||
resetModalState({commit}) {
|
||||
commit('setCurrentRoomEntry', '');
|
||||
commit('setCurrentContent', '');
|
||||
commit('setCurrentContentBlock', '');
|
||||
commit('setContentBlockPosition', {});
|
||||
commit('setParentRoom', null);
|
||||
|
|
@ -73,6 +75,7 @@ export default new Vuex.Store({
|
|||
type: ''
|
||||
});
|
||||
commit('setVimeoId', null);
|
||||
commit('setCurrentNote', null);
|
||||
},
|
||||
resetContentBlockPosition({commit}) {
|
||||
commit('setContentBlockPosition', {});
|
||||
|
|
@ -122,6 +125,15 @@ export default new Vuex.Store({
|
|||
commit('setCurrentProjectEntry', payload);
|
||||
dispatch('showModal', 'edit-project-entry-wizard');
|
||||
},
|
||||
addNote({commit, dispatch}, payload) {
|
||||
commit('setCurrentContentBlock', payload.contentBlock);
|
||||
commit('setCurrentContent', payload.content);
|
||||
dispatch('showModal', 'new-note-wizard');
|
||||
},
|
||||
editNote({commit, dispatch}, payload) {
|
||||
commit('setCurrentNote', payload);
|
||||
dispatch('showModal', 'edit-note-wizard');
|
||||
},
|
||||
showFullscreenImage({commit, dispatch}, payload) {
|
||||
commit('setImageUrl', payload);
|
||||
dispatch('showModal', 'fullscreen-image');
|
||||
|
|
@ -146,7 +158,7 @@ export default new Vuex.Store({
|
|||
scrollingToAssignment({commit, state, dispatch}, payload) {
|
||||
if (payload && !state.scrollingToAssignment) {
|
||||
commit('setScrollingToAssignment', true);
|
||||
};
|
||||
}
|
||||
|
||||
if (!payload && state.scrollingToAssignment) {
|
||||
commit('setScrollingToAssignment', false);
|
||||
|
|
@ -174,12 +186,18 @@ export default new Vuex.Store({
|
|||
setContentBlockPosition(state, payload) {
|
||||
state.contentBlockPosition = payload;
|
||||
},
|
||||
setCurrentContent(state, payload) {
|
||||
state.currentContent = payload;
|
||||
},
|
||||
setCurrentContentBlock(state, payload) {
|
||||
state.currentContentBlock = payload;
|
||||
},
|
||||
setParentRoom(state, payload) {
|
||||
state.parentRoom = payload;
|
||||
},
|
||||
setCurrentNote(state, payload) {
|
||||
state.currentNote = payload;
|
||||
},
|
||||
setCurrentRoomEntry(state, payload) {
|
||||
state.currentRoomEntry = payload;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,12 +11,13 @@ from basicknowledge.queries import BasicKnowledgeQuery
|
|||
from books.schema.mutations.main import BookMutations
|
||||
from books.schema.queries import BookQuery
|
||||
from core.schema.mutations.main import CoreMutations
|
||||
from notes.mutations import NoteMutations
|
||||
from objectives.mutations import ObjectiveMutations
|
||||
from objectives.schema import ObjectivesQuery
|
||||
from portfolio.mutations import PortfolioMutations
|
||||
from portfolio.schema import PortfolioQuery
|
||||
from surveys.schema import SurveysQuery
|
||||
from surveys.mutations import SurveysMutations
|
||||
from surveys.mutations import SurveyMutations
|
||||
from rooms.mutations import RoomMutations
|
||||
from rooms.schema import RoomsQuery, ModuleRoomsQuery
|
||||
from users.schema import AllUsersQuery, UsersQuery
|
||||
|
|
@ -33,7 +34,7 @@ class Query(UsersQuery, AllUsersQuery, ModuleRoomsQuery, RoomsQuery, ObjectivesQ
|
|||
|
||||
|
||||
class Mutation(BookMutations, RoomMutations, AssignmentMutations, ObjectiveMutations, CoreMutations, PortfolioMutations,
|
||||
ProfileMutations, SurveysMutations, graphene.ObjectType):
|
||||
ProfileMutations, SurveyMutations, NoteMutations, graphene.ObjectType):
|
||||
|
||||
if settings.DEBUG:
|
||||
debug = graphene.Field(DjangoDebug, name='__debug')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
# Generated by Django 2.0.6 on 2019-10-10 09:52
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('notes', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('books', '0014_auto_20190912_1228'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='contentblock',
|
||||
name='bookmarks',
|
||||
field=models.ManyToManyField(related_name='bookmarked_content_blocks', through='notes.ContentBlockBookmark', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
|
|
@ -11,8 +11,9 @@ from books.blocks import TextBlock, BasicKnowledgeBlock, LinkBlock, VideoBlock,
|
|||
ThinglinkBlock
|
||||
from books.utils import get_type_and_value
|
||||
from core.wagtail_utils import StrictHierarchyPage
|
||||
from notes.models import ContentBlockBookmark
|
||||
from surveys.models import Survey
|
||||
from users.models import SchoolClass
|
||||
from users.models import SchoolClass, User
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -34,10 +35,14 @@ class ContentBlock(StrictHierarchyPage):
|
|||
(BASE_SOCIETY, 'Instrument Gesellschaft'),
|
||||
)
|
||||
|
||||
# blocks without owner are visible by default, need to be hidden for each class
|
||||
hidden_for = models.ManyToManyField(SchoolClass, related_name='hidden_content_blocks')
|
||||
# blocks with owner are hidden by default, need to be shown for each class
|
||||
visible_for = models.ManyToManyField(SchoolClass, related_name='visible_content_blocks')
|
||||
user_created = models.BooleanField(default=False)
|
||||
|
||||
bookmarks = models.ManyToManyField(User, through=ContentBlockBookmark, related_name='bookmarked_content_blocks')
|
||||
|
||||
content_blocks = [
|
||||
('text_block', TextBlock()),
|
||||
('basic_knowledge', BasicKnowledgeBlock()),
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from books.models import ContentBlock, Chapter, SchoolClass
|
|||
from books.schema.inputs import ContentBlockInput
|
||||
from books.schema.queries import ContentBlockNode
|
||||
from core.utils import set_hidden_for, set_visible_for
|
||||
from notes.models import ContentBlockBookmark
|
||||
from .utils import handle_content_block, set_user_defined_block_type
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ from graphene_django.filter import DjangoFilterConnectionField
|
|||
|
||||
from api.utils import get_object
|
||||
from books.utils import are_solutions_enabled_for
|
||||
from notes.models import ContentBlockBookmark
|
||||
from notes.schema import ContentBlockBookmarkNode
|
||||
from rooms.models import ModuleRoomSlug
|
||||
from ..models import Book, Topic, Module, Chapter, ContentBlock
|
||||
|
||||
|
|
@ -24,6 +26,7 @@ def process_module_room_slug_block(content):
|
|||
|
||||
class ContentBlockNode(DjangoObjectType):
|
||||
mine = graphene.Boolean()
|
||||
bookmarks = graphene.List(ContentBlockBookmarkNode)
|
||||
|
||||
class Meta:
|
||||
model = ContentBlock
|
||||
|
|
@ -54,6 +57,12 @@ class ContentBlockNode(DjangoObjectType):
|
|||
self.contents.stream_data = updated_stream_data
|
||||
return self.contents
|
||||
|
||||
def resolve_bookmarks(self, info, **kwargs):
|
||||
return ContentBlockBookmark.objects.filter(
|
||||
user=info.context.user,
|
||||
content_block=self
|
||||
)
|
||||
|
||||
|
||||
class ChapterNode(DjangoObjectType):
|
||||
content_blocks = DjangoFilterConnectionField(ContentBlockNode)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ INSTALLED_APPS = [
|
|||
'portfolio',
|
||||
'statistics',
|
||||
'surveys',
|
||||
'notes',
|
||||
|
||||
'wagtail.contrib.forms',
|
||||
'wagtail.contrib.redirects',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class NotesConfig(AppConfig):
|
||||
name = 'notes'
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import graphene
|
||||
from graphene import InputObjectType
|
||||
|
||||
|
||||
class AddNoteArgument(InputObjectType):
|
||||
content = graphene.UUID(required=True)
|
||||
content_block = graphene.ID(required=True)
|
||||
text = graphene.String(required=True)
|
||||
|
||||
|
||||
class UpdateNoteArgument(InputObjectType):
|
||||
id = graphene.ID(required=True)
|
||||
text = graphene.String(required=True)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Generated by Django 2.0.6 on 2019-10-10 09:52
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('books', '0014_auto_20190912_1228'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ContentBlockBookmark',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('uuid', models.UUIDField(unique=True)),
|
||||
('content_block', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.ContentBlock')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Note',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('text', models.TextField()),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contentblockbookmark',
|
||||
name='note',
|
||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='notes.Note'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='contentblockbookmark',
|
||||
name='user',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
from core.wagtail_utils import StrictHierarchyPage
|
||||
from users.models import User
|
||||
|
||||
|
||||
class Note(models.Model):
|
||||
text = models.TextField()
|
||||
|
||||
|
||||
class Bookmark(models.Model):
|
||||
uuid = models.UUIDField(unique=True)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
note = models.OneToOneField(Note, null=True, on_delete=models.SET_NULL)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class ContentBlockBookmark(Bookmark):
|
||||
content_block = models.ForeignKey('books.ContentBlock', on_delete=models.CASCADE)
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
from builtins import PermissionError
|
||||
|
||||
import graphene
|
||||
import json
|
||||
from graphene import relay
|
||||
|
||||
from api.utils import get_object
|
||||
from books.models import ContentBlock
|
||||
from notes.inputs import AddNoteArgument, UpdateNoteArgument
|
||||
from notes.models import ContentBlockBookmark, Note
|
||||
from notes.schema import NoteNode
|
||||
|
||||
|
||||
class UpdateContentBookmark(relay.ClientIDMutation):
|
||||
class Input:
|
||||
uuid = graphene.UUID(required=True)
|
||||
content_block = graphene.ID(required=True)
|
||||
bookmarked = graphene.Boolean(required=True)
|
||||
|
||||
success = graphene.Boolean()
|
||||
errors = graphene.String()
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||
uuid = kwargs.get('uuid')
|
||||
user = info.context.user
|
||||
content_block_id = kwargs.get('content_block')
|
||||
bookmarked = kwargs.get('bookmarked')
|
||||
|
||||
content_block = get_object(ContentBlock, content_block_id)
|
||||
|
||||
if bookmarked:
|
||||
ContentBlockBookmark.objects.create(
|
||||
content_block=content_block,
|
||||
uuid=uuid,
|
||||
user=user
|
||||
)
|
||||
else:
|
||||
ContentBlockBookmark.objects.get(
|
||||
content_block=content_block,
|
||||
uuid=uuid,
|
||||
user=user
|
||||
).delete()
|
||||
|
||||
return cls(success=True)
|
||||
|
||||
|
||||
class AddNote(relay.ClientIDMutation):
|
||||
class Input:
|
||||
note = graphene.Argument(AddNoteArgument)
|
||||
|
||||
note = graphene.Field(NoteNode)
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||
user = info.context.user
|
||||
|
||||
note = kwargs.get('note')
|
||||
content_uuid = note.get('content')
|
||||
content_block_id = note.get('content_block')
|
||||
content_block = get_object(ContentBlock, content_block_id)
|
||||
text = note.get('text')
|
||||
|
||||
bookmark = ContentBlockBookmark.objects.get(
|
||||
content_block=content_block,
|
||||
uuid=content_uuid,
|
||||
user=user
|
||||
)
|
||||
|
||||
bookmark.note = Note.objects.create(text=text)
|
||||
bookmark.save()
|
||||
|
||||
return cls(note=bookmark.note)
|
||||
|
||||
|
||||
class UpdateNote(relay.ClientIDMutation):
|
||||
class Input:
|
||||
note = graphene.Argument(UpdateNoteArgument)
|
||||
|
||||
note = graphene.Field(NoteNode)
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||
user = info.context.user
|
||||
|
||||
note = kwargs.get('note')
|
||||
id = note.get('id')
|
||||
text = note.get('text')
|
||||
note = get_object(Note, id)
|
||||
|
||||
if note.contentblockbookmark.user != user:
|
||||
raise PermissionError
|
||||
|
||||
note.text = text
|
||||
note.save()
|
||||
return cls(note=note)
|
||||
|
||||
|
||||
class NoteMutations:
|
||||
add_note = AddNote.Field()
|
||||
update_note = UpdateNote.Field()
|
||||
update_content_bookmark = UpdateContentBookmark.Field()
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import graphene
|
||||
from graphene import relay
|
||||
from graphene_django import DjangoObjectType
|
||||
|
||||
from notes.models import Note, ContentBlockBookmark
|
||||
|
||||
|
||||
class NoteNode(DjangoObjectType):
|
||||
pk = graphene.Int()
|
||||
|
||||
class Meta:
|
||||
model = Note
|
||||
interfaces = (relay.Node,)
|
||||
|
||||
def resolve_pk(self, *args, **kwargs):
|
||||
return self.id
|
||||
|
||||
|
||||
class ContentBlockBookmarkNode(DjangoObjectType):
|
||||
# note = graphene.
|
||||
uuid = graphene.UUID()
|
||||
note = graphene.Field(NoteNode)
|
||||
|
||||
class Meta:
|
||||
model = ContentBlockBookmark
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
|
|
@ -33,5 +33,5 @@ class UpdateAnswer(relay.ClientIDMutation):
|
|||
return cls(answer=answer)
|
||||
|
||||
|
||||
class SurveysMutations:
|
||||
class SurveyMutations:
|
||||
update_answer = UpdateAnswer.Field()
|
||||
|
|
|
|||
Loading…
Reference in New Issue