merge develop into feature/pw-reset
This commit is contained in:
commit
f8c1f372cb
|
|
@ -40,3 +40,5 @@ server/media/
|
|||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
.coverage
|
||||
|
|
|
|||
2
Pipfile
2
Pipfile
|
|
@ -35,3 +35,5 @@ django-libsass = "*"
|
|||
bleach = "*"
|
||||
newrelic = "*"
|
||||
sentry-sdk = "==0.7.2"
|
||||
"django-sendgrid-v5" = "*"
|
||||
coverage = "*"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "61e358e30d3f66b4b69ac4ad424c24401d367fc483aaffeac28d970a418066aa"
|
||||
"sha256": "97ff5ca56ac835d40353e34e32ec8333ccb23822bcf971644b7641429d9774e1"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
|
@ -41,25 +41,25 @@
|
|||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:0bed0db8c10b88b3daa042adaa1fb6c3262caed39d28086e8548015405c71744",
|
||||
"sha256:70e71e0192a68f65754ab9d2a335be3c6856a1e8a15f3bd6263ea12e2f442bc7"
|
||||
"sha256:3927beac97e5467f869d63d60920b83c2d39964f69fbf944bc1db724116bfe1a",
|
||||
"sha256:be88cae6f16bb9fe3b850b6c8259b297f60b46855175cadae57594c9a403c582"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.9.93"
|
||||
"version": "==1.9.124"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:4df39ef9bcd7766e3a71a9e7f976ca6c9e926f451914a9c073aa50e9519436ca",
|
||||
"sha256:d3cea95919892eac30e2ff8c5a8908022d5a93f917df3cff4ed06a6926dcc0e5"
|
||||
"sha256:bb756a8da2c6e3ccf42dccb0ac71c1df2e07844db339183da06f4e0285b251d0",
|
||||
"sha256:fc7560a2676df2f0bab4ef0638277b86e5a00944c2ce1c3bb124b3066e6d3d2a"
|
||||
],
|
||||
"version": "==1.12.93"
|
||||
"version": "==1.12.124"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7",
|
||||
"sha256:993f830721089fef441cdfeb4b2c8c9df86f0c63239f06bd025a76a7daddb033"
|
||||
"sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
|
||||
"sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
|
||||
],
|
||||
"version": "==2018.11.29"
|
||||
"version": "==2019.3.9"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
|
|
@ -75,6 +75,43 @@
|
|||
],
|
||||
"version": "==7.0"
|
||||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
"sha256:3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9",
|
||||
"sha256:39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74",
|
||||
"sha256:3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390",
|
||||
"sha256:465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8",
|
||||
"sha256:48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe",
|
||||
"sha256:5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf",
|
||||
"sha256:5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e",
|
||||
"sha256:68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741",
|
||||
"sha256:6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09",
|
||||
"sha256:7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd",
|
||||
"sha256:7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034",
|
||||
"sha256:839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420",
|
||||
"sha256:8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c",
|
||||
"sha256:932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab",
|
||||
"sha256:988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba",
|
||||
"sha256:998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e",
|
||||
"sha256:9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609",
|
||||
"sha256:9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2",
|
||||
"sha256:a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49",
|
||||
"sha256:a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b",
|
||||
"sha256:aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d",
|
||||
"sha256:bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce",
|
||||
"sha256:bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9",
|
||||
"sha256:c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4",
|
||||
"sha256:c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773",
|
||||
"sha256:c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723",
|
||||
"sha256:df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c",
|
||||
"sha256:f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f",
|
||||
"sha256:f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1",
|
||||
"sha256:f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260",
|
||||
"sha256:fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.5.3"
|
||||
},
|
||||
"dj-database-url": {
|
||||
"hashes": [
|
||||
"sha256:7f4c78d2a090df8dfaf56d5d3ff7bbee17360436e4879558317e2314424864cd"
|
||||
|
|
@ -92,10 +129,10 @@
|
|||
},
|
||||
"django-appconf": {
|
||||
"hashes": [
|
||||
"sha256:6a4d9aea683b4c224d97ab8ee11ad2d29a37072c0c6c509896dd9857466fb261",
|
||||
"sha256:ddab987d14b26731352c01ee69c090a4ebfc9141ed223bef039d79587f22acd9"
|
||||
"sha256:35f13ca4d567f132b960e2cd4c832c2d03cb6543452d34e29b7ba10371ba80e3",
|
||||
"sha256:c98a7af40062e996b921f5962a1c4f3f0c979fa7885f7be4710cceb90ebe13a6"
|
||||
],
|
||||
"version": "==1.0.2"
|
||||
"version": "==1.0.3"
|
||||
},
|
||||
"django-compressor": {
|
||||
"hashes": [
|
||||
|
|
@ -143,6 +180,14 @@
|
|||
],
|
||||
"version": "==4.3"
|
||||
},
|
||||
"django-sendgrid-v5": {
|
||||
"hashes": [
|
||||
"sha256:471f718ae02c775f0f2ba8f901d5abb486b016805af8b2ac543ac9ff2f4164ec",
|
||||
"sha256:c69ba0171b260c25def8048b69d931b46fbd8360b9aff4eb5477a284260fce0c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.7.1"
|
||||
},
|
||||
"django-storages": {
|
||||
"hashes": [
|
||||
"sha256:8e35d2c7baeda5dc6f0b4f9a0fc142d25f9a1bf72b8cebfcbc5db4863abc552d",
|
||||
|
|
@ -153,10 +198,10 @@
|
|||
},
|
||||
"django-taggit": {
|
||||
"hashes": [
|
||||
"sha256:a21cbe7e0879f1364eef1c88a2eda89d593bf000ebf51c3f00423c6927075dce",
|
||||
"sha256:db4430ec99265341e05d0274edb0279163bd74357241f7b4d9274bdcb3338b17"
|
||||
"sha256:710b4d15ec1996550cc68a0abbc41903ca7d832540e52b1336e6858737e410d8",
|
||||
"sha256:bb8f27684814cd1414b2af75b857b5e26a40912631904038a7ecacd2bfafc3ac"
|
||||
],
|
||||
"version": "==0.23.0"
|
||||
"version": "==0.24.0"
|
||||
},
|
||||
"django-treebeard": {
|
||||
"hashes": [
|
||||
|
|
@ -196,10 +241,16 @@
|
|||
},
|
||||
"faker": {
|
||||
"hashes": [
|
||||
"sha256:16342dca4d92bfc83bab6a7daf6650e0ab087605a66bc38f17523fdb01757910",
|
||||
"sha256:d871ea315b2dcba9138b8344f2c131a76ac62d6227ca39f69b0c889fec97376c"
|
||||
"sha256:00b7011757c4907546f17d0e47df098b542ea2b04c966ee0e80a493aae2c13c8",
|
||||
"sha256:745ac8b9c9526e338696e07b7f2e206e5e317e5744e22fdd7c2894bf19af41f1"
|
||||
],
|
||||
"version": "==1.0.2"
|
||||
"version": "==1.0.4"
|
||||
},
|
||||
"future": {
|
||||
"hashes": [
|
||||
"sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"
|
||||
],
|
||||
"version": "==0.17.1"
|
||||
},
|
||||
"graphene": {
|
||||
"hashes": [
|
||||
|
|
@ -253,38 +304,38 @@
|
|||
},
|
||||
"jmespath": {
|
||||
"hashes": [
|
||||
"sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64",
|
||||
"sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63"
|
||||
"sha256:3720a4b1bd659dd2eecad0666459b9788813e032b83e7ba58578e48254e0a0e6",
|
||||
"sha256:bde2aef6f44302dfb30320115b17d030798de8c4110e28d5cf6cf91a7a31074c"
|
||||
],
|
||||
"version": "==0.9.3"
|
||||
"version": "==0.9.4"
|
||||
},
|
||||
"libsass": {
|
||||
"hashes": [
|
||||
"sha256:0da943e00e028211cb4bb91496a20becab9fe82407bb75266ec4212af04acb45",
|
||||
"sha256:107591ba2c0d173bb1705bef0e9fd04a5b6f482f3584f4ea51b28ab8b137fbb2",
|
||||
"sha256:1aeadc155594af23879e27792667dc06e7f248c2c599c40ff2a7335193abdf05",
|
||||
"sha256:411833c623288138744865d882f5226f6db52afce1e19f42722c416df9d308dc",
|
||||
"sha256:4bf7a80a956da9de9715436b85343a179da4ff399a6e9a1694e70bff93d43099",
|
||||
"sha256:53be1c6cea9458fc0b59fafff5307d63cbde4d6f8a4413fb52ae467566273357",
|
||||
"sha256:55b77204cfa363142ab02c49ee871321a396b8e51f6361ebc226c3953c780541",
|
||||
"sha256:66e3062ff508c81928e35c66702f0cc4f70fb12eb76ba23eeb0ff87a6340cc13",
|
||||
"sha256:747e1cb3624b25ce9104315cf98b080246c5112d008cba6536a7dd2edb16fcc2",
|
||||
"sha256:75605a97f4b2f47fafc5a372f09efec210c7f33908c6de726362f85489fd53aa",
|
||||
"sha256:7c7a531b8cd786c35170e97338be2e73a74806f95539366a8ee837df94b8a8cf",
|
||||
"sha256:953ebe810f09d81b84ccafdca0fb6171d1b58c8f0147cb650184a41e124e296f",
|
||||
"sha256:a19041e78d5bb7c5d72e010e893c29119693628b6ee06025503ab2584cf24edd",
|
||||
"sha256:b3e4abf50ad3a6bec25acd0c67495301cab6137aa79b8640364276f7f3712586",
|
||||
"sha256:bf6b7ad08f287695338f050c80f79d258a405e5c349cdaeb9be5d5376c09e37a",
|
||||
"sha256:fcbc861a001ffd68c4df00164b41c6152d5451185d06c654ac240d811be9f7e2"
|
||||
"sha256:2ae3b061a7d250fb47e5fdad1a8191600ca15dc604e76b109b6d3bf8e08fd2ed",
|
||||
"sha256:2ee186aa682a035a53c557b7e61ce562a1114f1a1a992d0ba962cbc3e82c490c",
|
||||
"sha256:366f4fd5a5eab4a519beb583e9fa78718cf2c0f40e92ed835d7ed23b82e5d954",
|
||||
"sha256:5511b3c62e8d97daf929c63bd516b794f0a06acd09dd261445d864e48290551b",
|
||||
"sha256:7462da168c8fb997b31cb4dc3ee5adb9af2d106f7b92c2d57a1c68a56ae5a3a0",
|
||||
"sha256:84a16ec5cf7842ff5bc2caed2c032ed624d587699797bc2a4d4a8e41f579b6e7",
|
||||
"sha256:8fc0360ee99224f7a3cb09987e641171d34180759f467ba3d15934102ade396f",
|
||||
"sha256:a6c5535a21a07d769151453270bc6a8373b821d1d2fd9810d84fccfe315ab188",
|
||||
"sha256:b375bfbf3c86ec0f4a27f266b44b2753a4b8cab7e73649eed7afcad84bc56257",
|
||||
"sha256:b548af46c1a606aed93da2566901146005d6065f73fefc63d256ba62ba1f803d",
|
||||
"sha256:bb30fc7125350c64925a98cb90da7979f76bb0ea1a0157e8aeb268f8da38e296",
|
||||
"sha256:c2f386677514f9fc758631328bd318dd3e9d839ad7b6e248ec4535a191bfd271",
|
||||
"sha256:d1f301637ad5768aecc81d17dcf40a68f2e11b7ca8b427dbb9f8972c150d303e",
|
||||
"sha256:e0cf54dddf2cc6e373005bed6e46ccdce1f3a77bd169ab505c3a8ad9023eee5f",
|
||||
"sha256:e8941881063691d50f9cc8b8d6d8fd7bec86a8c461b2a4fc87188a5fc44d6ba4",
|
||||
"sha256:f4b29b0c70d753c754a58aaad7c31ad3309ca4a26f9aa64e695157251f6832ad"
|
||||
],
|
||||
"version": "==0.17.0"
|
||||
"version": "==0.18.0"
|
||||
},
|
||||
"newrelic": {
|
||||
"hashes": [
|
||||
"sha256:8fdc94350bfe69e4f70dc8a3e7ead6c6a1905e8f161ce24de7ee3de4f69196ad"
|
||||
"sha256:1d08248dee0d33116a145de723a2ae86e57a10674145ce4c8af3c316423bd140"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.12.0.113"
|
||||
"version": "==4.16.0.116"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
|
|
@ -377,6 +428,12 @@
|
|||
"index": "pypi",
|
||||
"version": "==0.7.1"
|
||||
},
|
||||
"python-http-client": {
|
||||
"hashes": [
|
||||
"sha256:7e430f4b9dd2b621b0051f6a362f103447ea8e267594c602a5c502a0c694ee38"
|
||||
],
|
||||
"version": "==3.1.0"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9",
|
||||
|
|
@ -425,6 +482,13 @@
|
|||
],
|
||||
"version": "==0.2.0"
|
||||
},
|
||||
"sendgrid": {
|
||||
"hashes": [
|
||||
"sha256:97eb356ea44a18a03e6fe99f02b7942445be306a50f73a7dd35471fe15cc0094",
|
||||
"sha256:9e9d3d75602b8853f174ec959d1af1ac168cd361cbcafc81285fa8c183f7a505"
|
||||
],
|
||||
"version": "==5.6.0"
|
||||
},
|
||||
"sentry-sdk": {
|
||||
"hashes": [
|
||||
"sha256:131e3b9ac11dffd86fe4f1f5d388d3dab372fc9e30d6611d1fc87096a1d67359",
|
||||
|
|
@ -515,11 +579,11 @@
|
|||
"develop": {
|
||||
"awscli": {
|
||||
"hashes": [
|
||||
"sha256:11a18d6f42469366920ad96d483a64804f17ea63e21e5f4a66d8492d7031aa14",
|
||||
"sha256:21ad9141041834dfc135c731d32fdde674642f33d19b21e2ac9c696a8370d717"
|
||||
"sha256:87258e4719978f51dae8c62e15cd0486a778ddcb530645f3bc035239b800f184",
|
||||
"sha256:fbd9dc00ecd7060f36e5768122c9293672b82748fa224cb13e22e6322532d8db"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.16.103"
|
||||
"version": "==1.16.134"
|
||||
},
|
||||
"backcall": {
|
||||
"hashes": [
|
||||
|
|
@ -530,10 +594,10 @@
|
|||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:4df39ef9bcd7766e3a71a9e7f976ca6c9e926f451914a9c073aa50e9519436ca",
|
||||
"sha256:d3cea95919892eac30e2ff8c5a8908022d5a93f917df3cff4ed06a6926dcc0e5"
|
||||
"sha256:bb756a8da2c6e3ccf42dccb0ac71c1df2e07844db339183da06f4e0285b251d0",
|
||||
"sha256:fc7560a2676df2f0bab4ef0638277b86e5a00944c2ce1c3bb124b3066e6d3d2a"
|
||||
],
|
||||
"version": "==1.12.93"
|
||||
"version": "==1.12.124"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
|
|
@ -544,47 +608,47 @@
|
|||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
"sha256:09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f",
|
||||
"sha256:0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe",
|
||||
"sha256:0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d",
|
||||
"sha256:10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0",
|
||||
"sha256:1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607",
|
||||
"sha256:1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d",
|
||||
"sha256:2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b",
|
||||
"sha256:447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3",
|
||||
"sha256:46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e",
|
||||
"sha256:4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815",
|
||||
"sha256:510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36",
|
||||
"sha256:5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1",
|
||||
"sha256:5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14",
|
||||
"sha256:5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c",
|
||||
"sha256:6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794",
|
||||
"sha256:6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b",
|
||||
"sha256:77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840",
|
||||
"sha256:828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd",
|
||||
"sha256:85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82",
|
||||
"sha256:8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952",
|
||||
"sha256:a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389",
|
||||
"sha256:aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f",
|
||||
"sha256:ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4",
|
||||
"sha256:b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da",
|
||||
"sha256:bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647",
|
||||
"sha256:c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d",
|
||||
"sha256:d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42",
|
||||
"sha256:d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478",
|
||||
"sha256:da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b",
|
||||
"sha256:ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb",
|
||||
"sha256:ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9"
|
||||
"sha256:3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9",
|
||||
"sha256:39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74",
|
||||
"sha256:3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390",
|
||||
"sha256:465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8",
|
||||
"sha256:48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe",
|
||||
"sha256:5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf",
|
||||
"sha256:5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e",
|
||||
"sha256:68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741",
|
||||
"sha256:6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09",
|
||||
"sha256:7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd",
|
||||
"sha256:7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034",
|
||||
"sha256:839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420",
|
||||
"sha256:8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c",
|
||||
"sha256:932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab",
|
||||
"sha256:988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba",
|
||||
"sha256:998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e",
|
||||
"sha256:9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609",
|
||||
"sha256:9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2",
|
||||
"sha256:a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49",
|
||||
"sha256:a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b",
|
||||
"sha256:aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d",
|
||||
"sha256:bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce",
|
||||
"sha256:bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9",
|
||||
"sha256:c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4",
|
||||
"sha256:c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773",
|
||||
"sha256:c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723",
|
||||
"sha256:df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c",
|
||||
"sha256:f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f",
|
||||
"sha256:f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1",
|
||||
"sha256:f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260",
|
||||
"sha256:fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.5.2"
|
||||
"version": "==4.5.3"
|
||||
},
|
||||
"decorator": {
|
||||
"hashes": [
|
||||
"sha256:33cd704aea07b4c28b3eb2c97d288a06918275dac0ecebdaf1bc8a48d98adb9e",
|
||||
"sha256:cabb249f4710888a2fc0e13e9a16c343d932033718ff62e1e9bc93a9d3a9122b"
|
||||
"sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de",
|
||||
"sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"
|
||||
],
|
||||
"version": "==4.3.2"
|
||||
"version": "==4.4.0"
|
||||
},
|
||||
"docutils": {
|
||||
"hashes": [
|
||||
|
|
@ -596,18 +660,17 @@
|
|||
},
|
||||
"ipdb": {
|
||||
"hashes": [
|
||||
"sha256:7081c65ed7bfe7737f83fa4213ca8afd9617b42ff6b3f1daf9a3419839a2a00a"
|
||||
"sha256:dce2112557edfe759742ca2d0fee35c59c97b0cc7a05398b791079d78f1519ce"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.11"
|
||||
"version": "==0.12"
|
||||
},
|
||||
"ipython": {
|
||||
"hashes": [
|
||||
"sha256:6a9496209b76463f1dec126ab928919aaf1f55b38beb9219af3fe202f6bbdd12",
|
||||
"sha256:f69932b1e806b38a7818d9a1e918e5821b685715040b48e59c657b3c7961b742"
|
||||
"sha256:b038baa489c38f6d853a3cfc4c635b0cda66f2864d136fe8f40c1a6e334e2a6b",
|
||||
"sha256:f5102c1cd67e399ec8ea66bcebe6e3968ea25a8977e53f012963e5affeb1fe38"
|
||||
],
|
||||
"markers": "python_version >= '3.3'",
|
||||
"version": "==7.2.0"
|
||||
"version": "==7.4.0"
|
||||
},
|
||||
"ipython-genutils": {
|
||||
"hashes": [
|
||||
|
|
@ -618,17 +681,17 @@
|
|||
},
|
||||
"jedi": {
|
||||
"hashes": [
|
||||
"sha256:571702b5bd167911fe9036e5039ba67f820d6502832285cde8c881ab2b2149fd",
|
||||
"sha256:c8481b5e59d34a5c7c42e98f6625e633f6ef59353abea6437472c7ec2093f191"
|
||||
"sha256:2bb0603e3506f708e792c7f4ad8fc2a7a9d9c2d292a358fbbd58da531695595b",
|
||||
"sha256:2c6bcd9545c7d6440951b12b44d373479bf18123a401a52025cf98563fbd826c"
|
||||
],
|
||||
"version": "==0.13.2"
|
||||
"version": "==0.13.3"
|
||||
},
|
||||
"jmespath": {
|
||||
"hashes": [
|
||||
"sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64",
|
||||
"sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63"
|
||||
"sha256:3720a4b1bd659dd2eecad0666459b9788813e032b83e7ba58578e48254e0a0e6",
|
||||
"sha256:bde2aef6f44302dfb30320115b17d030798de8c4110e28d5cf6cf91a7a31074c"
|
||||
],
|
||||
"version": "==0.9.3"
|
||||
"version": "==0.9.4"
|
||||
},
|
||||
"parso": {
|
||||
"hashes": [
|
||||
|
|
@ -654,11 +717,11 @@
|
|||
},
|
||||
"prompt-toolkit": {
|
||||
"hashes": [
|
||||
"sha256:88002cc618cacfda8760c4539e76c3b3f148ecdb7035a3d422c7ecdc90c2a3ba",
|
||||
"sha256:c6655a12e9b08edb8cf5aeab4815fd1e1bdea4ad73d3bbf269cf2e0c4eb75d5e",
|
||||
"sha256:df5835fb8f417aa55e5cafadbaeb0cf630a1e824aad16989f9f0493e679ec010"
|
||||
"sha256:11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780",
|
||||
"sha256:2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1",
|
||||
"sha256:977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55"
|
||||
],
|
||||
"version": "==2.0.8"
|
||||
"version": "==2.0.9"
|
||||
},
|
||||
"ptyprocess": {
|
||||
"hashes": [
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ aliases:
|
|||
- echo "This pipeline rules!"
|
||||
- *setup-tests
|
||||
- npm install --prefix client
|
||||
# - npm run "install:cypress" --prefix client
|
||||
# - npm run "install:cypress" --prefix client
|
||||
- psql -U $DATABASE_USER -h $DATABASE_HOST -c "create database $DATABASE_NAME"
|
||||
- python server/manage.py dummy_data
|
||||
- python server/manage.py runserver &
|
||||
|
|
@ -55,6 +55,7 @@ pipelines:
|
|||
branches:
|
||||
master:
|
||||
- step: *unittest-python
|
||||
- step: *cypress-test
|
||||
|
||||
develop:
|
||||
- step: *unittest-python
|
||||
|
|
@ -67,4 +68,5 @@ pipelines:
|
|||
custom:
|
||||
prod:
|
||||
- step: *unittest-python
|
||||
- step: *cypress-test
|
||||
- step: *deploy-prod
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ describe('The Login Page', () => {
|
|||
cy.get('#id_password').type(`${password}{enter}`);
|
||||
|
||||
cy.getCookie('sessionid').should('exist');
|
||||
cy.get('.start-page__title').should('contain', 'skillbox')
|
||||
cy.get('.start-page__header').should('exist')
|
||||
});
|
||||
// it('logs in programmatically without using the UI', () => {
|
||||
// cy.visit('/accounts/login/'); // have to get a csrf token by getting the base page first
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
describe('New project', () => {
|
||||
it('creates a new project and displays it', () => {
|
||||
cy.viewport('macbook-15');
|
||||
cy.login('rahel.cueni', 'test');
|
||||
|
||||
cy.visit('/portfolio');
|
||||
cy.get('[data-cy=add-project-button]').click();
|
||||
cy.get('[data-cy=page-form-input-titel]').type('Some random title');
|
||||
cy.get('[data-cy=page-form-input-beschreibung]').type('This description rocks');
|
||||
cy.get('[data-cy=page-form-input-ziele]').type('Git gud');
|
||||
cy.get('[data-cy=save-project-button]').click();
|
||||
cy.get('.project-widget:first').contains('random');
|
||||
})
|
||||
});
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
|
||||
<title>skillbox</title>
|
||||
|
||||
<link href='https://fonts.googleapis.com/css?family=Material+Icons' rel="stylesheet" type="text/css">
|
||||
|
|
|
|||
|
|
@ -3042,6 +3042,12 @@
|
|||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"dev": true
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.22.2",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
|
||||
"integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz",
|
||||
|
|
@ -7191,10 +7197,9 @@
|
|||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.22.2",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
|
||||
"integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=",
|
||||
"dev": true
|
||||
"version": "2.24.0",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
|
||||
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
|
||||
},
|
||||
"move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
"graphql-tag": "^2.9.2",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"lodash": "^4.17.10",
|
||||
"moment": "^2.24.0",
|
||||
"node-notifier": "^5.1.2",
|
||||
"node-sass": "^4.9.2",
|
||||
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<template>
|
||||
<div :class="{'no-scroll': showModal}">
|
||||
<div :class="{'no-scroll': showModal || showMobileNavigation}" class="app">
|
||||
<component :is="showModal" v-if="showModal"></component>
|
||||
<component :is="layout"></component>
|
||||
<mobile-navigation v-if="showMobileNavigation"></mobile-navigation>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -10,6 +11,7 @@
|
|||
import SimpleLayout from '@/layouts/SimpleLayout';
|
||||
import BlankLayout from '@/layouts/BlankLayout';
|
||||
import Modal from '@/components/Modal';
|
||||
import MobileNavigation from '@/components/MobileNavigation';
|
||||
import NewContentBlockWizard from '@/components/content-block-form/NewContentBlockWizard';
|
||||
import EditContentBlockWizard from '@/components/content-block-form/EditContentBlockWizard';
|
||||
import NewRoomEntryWizard from '@/components/rooms/room-entries/NewRoomEntryWizard';
|
||||
|
|
@ -19,6 +21,9 @@
|
|||
import NewProjectEntryWizard from '@/components/portfolio/NewProjectEntryWizard';
|
||||
import FullscreenImage from '@/components/FullscreenImage';
|
||||
import FullscreenInfographic from '@/components/FullscreenInfographic';
|
||||
import FullscreenVideo from '@/components/FullscreenVideo';
|
||||
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
|
|
@ -28,6 +33,7 @@
|
|||
SimpleLayout,
|
||||
BlankLayout,
|
||||
Modal,
|
||||
MobileNavigation,
|
||||
NewContentBlockWizard,
|
||||
EditContentBlockWizard,
|
||||
NewRoomEntryWizard,
|
||||
|
|
@ -36,16 +42,15 @@
|
|||
EditObjectiveGroupWizard,
|
||||
NewProjectEntryWizard,
|
||||
FullscreenImage,
|
||||
FullscreenInfographic
|
||||
FullscreenInfographic,
|
||||
FullscreenVideo
|
||||
},
|
||||
|
||||
computed: {
|
||||
layout() {
|
||||
return (this.$route.meta.layout || 'default') + '-layout';
|
||||
},
|
||||
showModal() {
|
||||
return this.$store.state.showModal
|
||||
}
|
||||
...mapGetters(['showModal', 'showMobileNavigation'])
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
|
@ -56,6 +61,18 @@
|
|||
<style lang="scss">
|
||||
@import "styles/main.scss";
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.app {
|
||||
overflow-y: auto;
|
||||
height: 100vh;
|
||||
/*for IE10+*/
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.no-scroll {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,15 +37,20 @@
|
|||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.add-objective-group-button {
|
||||
display: grid;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<component :is="component" v-bind="properties" class="add-widget" @click="$emit('click')" :class="{ 'add-widget--reverse': reverse }">
|
||||
<component :is="component" v-bind="properties" class="add-widget" @click="$emit('click')"
|
||||
:class="{ 'add-widget--reverse': reverse }">
|
||||
<add-icon class="add-widget__add"></add-icon>
|
||||
</component>
|
||||
</template>
|
||||
|
|
@ -47,12 +48,16 @@
|
|||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.add-widget {
|
||||
display: flex;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@include widget-shadow;
|
||||
cursor: pointer;
|
||||
|
||||
@include desktop {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__add {
|
||||
width: 80px;
|
||||
fill: $color-grey;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<div class="room-colors">
|
||||
<div class="color-chooser">
|
||||
<div v-for="(color, index) in colors"
|
||||
:key="index"
|
||||
class="room-colors__color-wrapper"
|
||||
class="color-chooser__color-wrapper"
|
||||
@click="$emit('input', color.name)"
|
||||
:class="{'room-colors__color-wrapper--selected': selectedColor === color.name}">
|
||||
<div class="room-colors__color" :class="'room-colors__color--' + color.name">
|
||||
<tick class="room-colors__selected-icon" v-if="selectedColor === color.name"></tick>
|
||||
:class="{'color-chooser__color-wrapper--selected': selectedColor === color.name}">
|
||||
<div class="color-chooser__color" :class="'color-chooser__color--' + color.name">
|
||||
<tick class="color-chooser__selected-icon" v-if="selectedColor === color.name"></tick>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.room-colors {
|
||||
.color-chooser {
|
||||
display: flex;
|
||||
|
||||
&__color-wrapper {
|
||||
|
|
@ -69,7 +69,11 @@
|
|||
width: 46px;
|
||||
height: 46px;
|
||||
border-radius: 23px;
|
||||
display: grid;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@supports (display: grid) {
|
||||
display: grid
|
||||
}
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<modal class="fullscreen-video" :hide-header="true" :fullscreen="true">
|
||||
<iframe :src="src"
|
||||
width="2000"
|
||||
height="1000"
|
||||
class="fullscreen-video__embed"
|
||||
frameborder="0" webkitallowfullscreen
|
||||
mozallowfullscreen allowfullscreen></iframe>
|
||||
</modal>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Modal
|
||||
},
|
||||
|
||||
computed: {
|
||||
vimeoId() {
|
||||
return this.$store.state.vimeoId;
|
||||
},
|
||||
src() {
|
||||
return `https://player.vimeo.com/video/${this.vimeoId}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.fullscreen-video {
|
||||
&__embed {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: 95vh;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
<template>
|
||||
<header class="header-bar">
|
||||
<top-navigation></top-navigation>
|
||||
<router-link to="/" class="header-bar__logo"><logo></logo></router-link>
|
||||
<div class="user-header">
|
||||
<user-widget v-bind="me"></user-widget>
|
||||
<logout-widget></logout-widget>
|
||||
</div>
|
||||
<book-navigation v-if="showSubnavigation">
|
||||
</book-navigation>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TopNavigation from '@/components/TopNavigation.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 ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TopNavigation,
|
||||
UserWidget,
|
||||
LogoutWidget,
|
||||
BookNavigation,
|
||||
Logo
|
||||
},
|
||||
|
||||
computed: {
|
||||
showSubnavigation() {
|
||||
return this.$route.meta.subnavigation;
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
me: {}
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: {
|
||||
query: ME_QUERY,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.header-bar {
|
||||
display: -ms-grid;
|
||||
@supports (display: grid) {
|
||||
display: none;
|
||||
|
||||
@include desktop {
|
||||
display: grid;
|
||||
}
|
||||
}
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
background-color: $color-white;
|
||||
grid-auto-rows: 50px;
|
||||
width: 100%;
|
||||
|
||||
@include desktop {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
-ms-grid-columns: 1fr 1fr 1fr;
|
||||
-ms-grid-rows: 50px 50px;
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
& > :nth-child(1) {
|
||||
-ms-grid-column: 1;
|
||||
-ms-grid-row-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-column: 3;
|
||||
-ms-grid-row-align: center;
|
||||
-ms-grid-column-align: end;
|
||||
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
& > :nth-child(4) {
|
||||
-ms-grid-row: 2;
|
||||
-ms-grid-column: 1;
|
||||
-ms-grid-column-span: 3;
|
||||
}
|
||||
|
||||
&__logo {
|
||||
color: #17A887;
|
||||
font-size: 36px;
|
||||
font-weight: 800;
|
||||
font-family: $sans-serif-font-family;
|
||||
display: flex;
|
||||
justify-self: center;
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
-ms-grid-column: 2;
|
||||
-ms-grid-row-align: center;
|
||||
-ms-grid-column-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.user-header {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
&__logout {
|
||||
font-family: $sans-serif-font-family;
|
||||
line-height: 16px;
|
||||
margin: 0 15px 0 20px;
|
||||
margin: 0 15px 0 $large-spacing;
|
||||
background: none;
|
||||
color: inherit;
|
||||
border: none;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div class="mobile-header">
|
||||
<router-link to="/">
|
||||
<logo></logo>
|
||||
</router-link>
|
||||
|
||||
<a @click="showMobileNavigation">
|
||||
<hamburger class="mobile-header__hamburger"></hamburger>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Logo from '@/components/icons/Logo';
|
||||
import Hamburger from '@/components/icons/Hamburger';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Logo,
|
||||
Hamburger
|
||||
},
|
||||
|
||||
methods: {
|
||||
showMobileNavigation() {
|
||||
this.$store.dispatch('showMobileNavigation', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.mobile-header {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
display: flex;
|
||||
|
||||
@include desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
padding: 0 $medium-spacing;
|
||||
|
||||
&__hamburger {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
fill: $color-grey;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<div class="mobile-navigation">
|
||||
<top-navigation class="mobile-navigation__main" :mobile="true"></top-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">
|
||||
<user-widget class="mobile-navigation__user-widget" v-bind="me"></user-widget>
|
||||
<logout-widget class="mobile-navigation__logout-widget"></logout-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 {meQuery} from '@/graphql/queries';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TopNavigation,
|
||||
Cross,
|
||||
UserWidget,
|
||||
LogoutWidget
|
||||
},
|
||||
|
||||
methods: {
|
||||
hideMobileNavigation() {
|
||||
this.$store.dispatch('showMobileNavigation', false);
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: meQuery
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
me: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.mobile-navigation {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
background-color: white;
|
||||
z-index: 20;
|
||||
|
||||
display: grid;
|
||||
|
||||
grid-template-columns: 1fr 50px;
|
||||
grid-template-rows: 50px 100px auto 100px;
|
||||
|
||||
grid-template-areas: "m m" "m m" "s s";
|
||||
|
||||
&--with-subnavigation {
|
||||
grid-template-areas: "m m" "m m" "sub sub" "s s";
|
||||
}
|
||||
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
|
||||
@include desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__main {
|
||||
background-color: $color-brand;
|
||||
padding: $medium-spacing;
|
||||
grid-area: m;
|
||||
}
|
||||
|
||||
&__main-link {
|
||||
}
|
||||
|
||||
&__close-button {
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
&__close-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
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>
|
||||
|
|
@ -59,9 +59,13 @@
|
|||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.15);
|
||||
border: 1px solid $color-lightgrey;
|
||||
display: grid;
|
||||
display: -ms-grid;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
grid-template-rows: auto 1fr 65px;
|
||||
grid-template-areas: "header" "body" "footer";
|
||||
-ms-grid-rows: auto 1fr 65px;
|
||||
position: relative;
|
||||
|
||||
&--hide-header {
|
||||
|
|
@ -81,6 +85,7 @@
|
|||
width: 95vw;
|
||||
height: auto;
|
||||
grid-template-rows: 1fr;
|
||||
-ms-grid-rows: 1fr;
|
||||
grid-template-areas: "body";
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
@ -107,7 +112,11 @@
|
|||
}
|
||||
|
||||
&__backdrop {
|
||||
display: grid;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
|
@ -119,12 +128,14 @@
|
|||
|
||||
&__header {
|
||||
grid-area: header;
|
||||
-ms-grid-row: 1;
|
||||
padding: 10px $modal-lateral-padding;
|
||||
border-bottom: 1px solid $color-lightgrey;
|
||||
}
|
||||
|
||||
&__body {
|
||||
grid-area: body;
|
||||
-ms-grid-row: 2;
|
||||
padding: 10px $modal-lateral-padding;
|
||||
overflow: auto;
|
||||
box-sizing: border-box;
|
||||
|
|
@ -150,6 +161,7 @@
|
|||
|
||||
&__footer {
|
||||
grid-area: footer;
|
||||
-ms-grid-row: 3;
|
||||
border-top: 1px solid $color-lightgrey;
|
||||
padding: 16px $modal-lateral-padding;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
<a :href="url" target="_blank" class="teaser__title">{{title}}</a>
|
||||
</h4>
|
||||
<a :href="url" target="_blank" class="teaser__date">
|
||||
{{date}}
|
||||
</a>
|
||||
{{date}}
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -18,10 +18,21 @@
|
|||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_functions.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.news-teaser {
|
||||
display: flex;
|
||||
border-left: 1px solid $color-lightgrey;
|
||||
border-bottom: 1px solid $color-lightgrey;
|
||||
padding-bottom: $large-spacing;
|
||||
text-align: center;
|
||||
|
||||
@include desktop {
|
||||
border-bottom: 0;
|
||||
border-left: 1px solid $color-lightgrey;
|
||||
padding-bottom: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
padding-left: $medium-spacing;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<nav class="top-navigation">
|
||||
<nav class="top-navigation" :class="{'top-navigation--mobile': mobile}">
|
||||
<router-link to="/book/topic/geld-und-kauf" active-class="top-navigation__link--active"
|
||||
:class="{'top-navigation__link--active': isActive('book')}"
|
||||
class="top-navigation__link">Inhalte
|
||||
|
|
@ -13,6 +13,12 @@
|
|||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mobile: {
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
isActive(linkName) {
|
||||
return linkName === 'book' && this.$route.path.indexOf('module') > -1;
|
||||
|
|
@ -22,4 +28,39 @@
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.top-navigation {
|
||||
display: flex;
|
||||
|
||||
&__link {
|
||||
font-size: 1.0625rem;
|
||||
padding: 0 24px;
|
||||
font-family: $sans-serif-font-family;
|
||||
font-weight: $font-weight-regular;
|
||||
color: $color-grey;
|
||||
|
||||
&--active {
|
||||
color: $color-brand;
|
||||
}
|
||||
}
|
||||
|
||||
$parent: &;
|
||||
|
||||
&--mobile {
|
||||
flex-direction: column;
|
||||
|
||||
#{$parent}__link {
|
||||
color: rgba($color-white, 0.6);
|
||||
@include heading-4;
|
||||
line-height: 2em;
|
||||
padding: 0;
|
||||
|
||||
&--active {
|
||||
color: $color-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -12,10 +12,15 @@
|
|||
import UserIcon from '@/components/icons/UserIcon';
|
||||
|
||||
export default {
|
||||
props: ['firstName', 'lastName', 'avatar', 'date', 'isProfile'],
|
||||
props: ['firstName', 'lastName', 'avatar', 'date'],
|
||||
|
||||
components: {
|
||||
UserIcon
|
||||
},
|
||||
computed: {
|
||||
isProfile() {
|
||||
return this.$route.meta.isProfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
<template>
|
||||
<div class="widget-footer">
|
||||
<a @click="showMenu = !showMenu" class="widget-footer__more-link">
|
||||
<a @click="toggleMenu"
|
||||
class="widget-footer__more-link">
|
||||
<ellipses></ellipses>
|
||||
</a>
|
||||
<widget-popover :entity="entity"
|
||||
@delete="onDelete"
|
||||
@hide-me="showMenu = false"
|
||||
@edit="onEdit"
|
||||
:id="id"
|
||||
v-if="showMenu"></widget-popover>
|
||||
<widget-popover v-if="showMenu"
|
||||
@hide-me="showMenu = false">
|
||||
<slot :hide="toggleMenu"></slot>
|
||||
</widget-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -17,7 +16,6 @@
|
|||
import WidgetPopover from '@/components/rooms/WidgetPopover';
|
||||
|
||||
export default {
|
||||
props: ['on-delete', 'on-edit', 'id', 'entity'],
|
||||
|
||||
components: {
|
||||
Ellipses,
|
||||
|
|
@ -28,12 +26,19 @@
|
|||
return {
|
||||
showMenu: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleMenu: function () {
|
||||
this.showMenu = !this.showMenu
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.widget-footer {
|
||||
background-color: $color-grey--lighter;
|
||||
|
|
@ -43,6 +48,11 @@
|
|||
position: relative;
|
||||
border-bottom-left-radius: $default-border-radius;
|
||||
border-bottom-right-radius: $default-border-radius;
|
||||
visibility: hidden;
|
||||
|
||||
@include desktop {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
<template>
|
||||
<img :src="value.path" alt="" class="image-block">
|
||||
<img :src="value.path" alt="" class="image-block" @click="openFullscreen">
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['value']
|
||||
props: ['value'],
|
||||
methods: {
|
||||
openFullscreen() {
|
||||
this.$store.dispatch('showFullscreenImage', this.value.path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -66,8 +66,12 @@
|
|||
@import "@/styles/_functions.scss";
|
||||
|
||||
.content-block-element-chooser-widget {
|
||||
display: grid;
|
||||
display: -ms-grid;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
-ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-column-gap: 0px;
|
||||
font-family: $sans-serif-font-family;
|
||||
text-align: center;
|
||||
|
|
@ -78,6 +82,31 @@
|
|||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
|
||||
/*IE10+*/
|
||||
& > :nth-child(1) {
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
|
||||
& > :nth-child(2) {
|
||||
-ms-grid-column: 2;
|
||||
}
|
||||
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-column: 3;
|
||||
}
|
||||
|
||||
& > :nth-child(4) {
|
||||
-ms-grid-column: 4;
|
||||
}
|
||||
|
||||
& > :nth-child(5) {
|
||||
-ms-grid-column: 5;
|
||||
}
|
||||
|
||||
& > :nth-child(6) {
|
||||
-ms-grid-column: 6;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<h3 class="text-form-with-help-text__heading"><span class="text-form-with-help-text__title">{{title}}</span>
|
||||
<info-icon class="text-form-with-help-text__icon"></info-icon>
|
||||
</h3>
|
||||
<text-form @text-change-value="$emit('change', $event.target.value)" :value="v"></text-form>
|
||||
<text-form @text-change-value="$emit('change', $event)" :value="v"></text-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<path d="M15,50a2.48,2.48,0,0,0,2.49,2.5h65a2.5,2.5,0,0,0,0-5h-65A2.5,2.5,0,0,0,15,50Z"/>
|
||||
<path d="M15,20.5A2.48,2.48,0,0,0,17.49,23h65a2.5,2.5,0,0,0,0-5h-65A2.5,2.5,0,0,0,15,20.5Z"/>
|
||||
<path d="M15,79.5A2.48,2.48,0,0,0,17.49,82h65a2.5,2.5,0,0,0,0-5h-65A2.5,2.5,0,0,0,15,79.5Z"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<svg class="logo" xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1350 250">
|
||||
<path
|
||||
d="M304.4,242.15a60,60,0,0,1-19.59-3.1,64.2,64.2,0,0,1-17.6-9.63l-2.94-2.22,21.17-34,3.58,3.21a21.91,21.91,0,0,0,6,4,15.21,15.21,0,0,0,5.81,1.09c4,0,6.51-1.44,8.08-4.68l1.15-2.19L263.73,85.72H313.8L334.27,143l17.38-57.3h48.8L353,208.39c-4.53,11.34-10.91,19.87-19,25.41h0C326,239.34,316,242.15,304.4,242.15Zm-29.33-17a53.63,53.63,0,0,0,12.38,6.3,51.94,51.94,0,0,0,17,2.66c10,0,18.42-2.33,25.12-6.94h0c6.71-4.62,12.1-11.92,16-21.71L388.67,93.79h-31l-22.74,75-26.79-75H275.94L319,195l-2.88,5.47c-2.87,5.92-8.18,9.11-15.29,9.11a23.28,23.28,0,0,1-8.88-1.69,24.83,24.83,0,0,1-4.58-2.53Z"
|
||||
style="fill:#36c0a1"/>
|
||||
<path
|
||||
d="M458.66,113a12.63,12.63,0,0,0-6.43,1.39,4.55,4.55,0,0,0-2.36,4.18q0,3.22,4.4,5.25a93.59,93.59,0,0,0,14,4.61,178.08,178.08,0,0,1,21.33,7.29,40.28,40.28,0,0,1,14.79,11q6.32,7.39,6.33,19,0,17.8-14,28.19t-37.19,10.4A102.76,102.76,0,0,1,430,200.15a84.64,84.64,0,0,1-25.4-12.33l13.29-27.22a97.33,97.33,0,0,0,21.76,10.72A64.21,64.21,0,0,0,460.16,175a14.94,14.94,0,0,0,7.07-1.39,4.33,4.33,0,0,0,2.57-4q0-3.22-4.18-5.25a84.51,84.51,0,0,0-13.83-4.61A157.5,157.5,0,0,1,431,152.67a40,40,0,0,1-14.58-10.93q-6.22-7.29-6.22-18.86,0-18,13.72-28.51t36-10.5q26.79,0,51.23,14.15l-14.36,27.22Q473,113,458.66,113Z"
|
||||
style="fill:#36c0a1"/>
|
||||
<path d="M604.69,202.4l-21.22-40.51-8.79,9.22v31.3h-43.3V43.35h43.3v77.38l32.15-34.94h48.87l-42.66,45,42.87,71.6Z"
|
||||
style="fill:#36c0a1"/>
|
||||
<path
|
||||
d="M712.25,36.49q6.22,6.22,6.22,16.08t-6.22,16.08q-6.22,6.22-16.08,6.22T680,68.64q-6.33-6.21-6.32-16.08T680,36.49q6.32-6.21,16.18-6.22T712.25,36.49Zm-37.51,49.3H718V202.4h-43.3Z"
|
||||
style="fill:#36c0a1"/>
|
||||
<path d="M748.47,43.35h43.3V202.4h-43.3Z" style="fill:#36c0a1"/>
|
||||
<path d="M823.5,43.35h43.3V202.4H823.5Z" style="fill:#36c0a1"/>
|
||||
<path
|
||||
d="M1002.06,91.79A50.33,50.33,0,0,1,1021,113q6.75,13.72,6.75,31.73,0,17.8-6.54,31.19a48.35,48.35,0,0,1-18.54,20.69q-12,7.29-27.87,7.29A44,44,0,0,1,956.19,200a40.21,40.21,0,0,1-14.36-11.15v13.5h-43.3V43.35h43.3V99.29a38.85,38.85,0,0,1,13.93-11.15,41.53,41.53,0,0,1,18-3.86Q989.85,84.29,1002.06,91.79Zm-23.8,70.63q5.79-7.18,5.79-18.76t-5.79-18.76a18.82,18.82,0,0,0-15.43-7.18,18.59,18.59,0,0,0-15.22,7.18q-5.79,7.19-5.79,18.76t5.79,18.76a18.58,18.58,0,0,0,15.22,7.18A18.8,18.8,0,0,0,978.27,162.42Z"
|
||||
style="fill:#36c0a1"/>
|
||||
<path
|
||||
d="M1142.8,91.69a54.24,54.24,0,0,1,22.62,20.9q8,13.5,8,31.51,0,17.8-8,31.4a54,54,0,0,1-22.62,21q-14.58,7.4-34.08,7.4t-34.19-7.4a53.86,53.86,0,0,1-22.73-21q-8-13.61-8-31.4,0-18,8-31.51a54.08,54.08,0,0,1,22.73-20.9q14.68-7.4,34.19-7.4T1142.8,91.69Zm-49.52,34.08q-5.79,7.18-5.79,18.76,0,11.79,5.79,18.86a18.92,18.92,0,0,0,15.43,7.07,18.7,18.7,0,0,0,15.22-7.07q5.79-7.07,5.79-18.86,0-11.58-5.79-18.76a18.6,18.6,0,0,0-15.22-7.18A18.81,18.81,0,0,0,1093.28,125.77Z"
|
||||
style="fill:#36c0a1"/>
|
||||
<path
|
||||
d="M1176.45,85.79h49.73L1242.26,116l18-30.23h47.16L1271,142.6l39,59.81h-49.73l-18-33-20.58,33h-47.59l39-59.59Z"
|
||||
style="fill:#36c0a1"/>
|
||||
<path
|
||||
d="M245,105.8A38.35,38.35,0,0,0,229.9,89.74h0a46.56,46.56,0,0,0-46.21,1.09A41.77,41.77,0,0,0,171.45,103a38.76,38.76,0,0,0-11.67-12,42.9,42.9,0,0,0-24.06-6.82,44.09,44.09,0,0,0-21.4,5.16,41.05,41.05,0,0,0-8.13,5.83v-9.4H58V201.83h48.19V144.37c0-5.32,1.23-9.42,3.77-12.55a11.7,11.7,0,0,1,9.27-4.46,9.48,9.48,0,0,1,7.75,3.35c2.09,2.45,3.11,5.75,3.11,10.09v61h48.19V144.37c0-5.26,1.24-9.49,3.69-12.59a11.44,11.44,0,0,1,9.15-4.43,9.48,9.48,0,0,1,7.75,3.35c2.09,2.45,3.11,5.75,3.11,10.09v61h48.19V129.28A51.17,51.17,0,0,0,245,105.8Zm-2.87,88h-32v-53c0-6.25-1.7-11.41-5-15.33a17.51,17.51,0,0,0-14-6.18h0a19.38,19.38,0,0,0-15.37,7.49c-3.61,4.55-5.44,10.48-5.44,17.6v49.39h-32v-53c0-6.25-1.7-11.41-5-15.33a17.53,17.53,0,0,0-14-6.18h0a19.66,19.66,0,0,0-15.44,7.45c-3.69,4.56-5.57,10.49-5.57,17.63v49.39h-32v-100h32v18.16h5.19l2.25-3.54a34.63,34.63,0,0,1,12.63-12,36.13,36.13,0,0,1,17.53-4.17,35,35,0,0,1,19.62,5.49,31.51,31.51,0,0,1,12.17,15.38l.46,1.18h6.52l.45-1a36.75,36.75,0,0,1,50.91-16.55,30,30,0,0,1,11.93,12.74,43.2,43.2,0,0,1,4.33,19.81Z"
|
||||
style="fill:#36c0a1"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.logo {
|
||||
width: 250px;
|
||||
height: 48px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<path d="M50,0a50,50,0,1,0,50,50A50,50,0,0,0,50,0ZM38,74V26L70,50Z" style="fill:#17a887"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
|
@ -137,7 +137,7 @@
|
|||
width: 640px;
|
||||
}
|
||||
flex-direction: column;
|
||||
padding: 0 15px;
|
||||
padding: $large-spacing 15px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div>
|
||||
<nav class="module-navigation">
|
||||
<nav v-if="false" class="module-navigation">
|
||||
<div class="module-navigation__module-content">
|
||||
<router-link
|
||||
tag="h3"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
<template>
|
||||
<div class="page-form__page">
|
||||
<form class="page-form" @submit.prevent="$emit('save')">
|
||||
<div class="page-form__content">
|
||||
<h1 class="page-form__heading">{{title}}</h1>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="page-form__footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['title']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.page-form {
|
||||
width: 710px;
|
||||
min-height: 760px;
|
||||
max-height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: $color-white;
|
||||
border-radius: $default-border-radius;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
grid-template-rows: 1fr 55px;
|
||||
|
||||
&__page {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&__content {
|
||||
padding: $medium-spacing;
|
||||
}
|
||||
|
||||
&__heading {
|
||||
@include heading-2;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
border-top: 1px solid $color-lightgrey;
|
||||
padding: $small-spacing $medium-spacing;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<div class="page-form-input">
|
||||
<label class="page-form-input__label" :for="id">{{label}}</label>
|
||||
<component :is="type" :class="classes"
|
||||
:value.prop="value"
|
||||
:data-cy="cyId"
|
||||
:id="id" @input="$emit('input', $event.target.value)"></component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
label: {
|
||||
type: String
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'input'
|
||||
},
|
||||
value: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.id = this._uid;
|
||||
},
|
||||
|
||||
computed: {
|
||||
classes() {
|
||||
return `page-form-input__${this.type} skillbox-${this.type}`;
|
||||
},
|
||||
cyId() {
|
||||
return `page-form-input-${this.label.toLowerCase()}`
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
id: null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.page-form-input {
|
||||
&__label {
|
||||
@include page-form-input-heading;
|
||||
}
|
||||
|
||||
&__input, &__textarea {
|
||||
width: 100%;
|
||||
margin-bottom: $large-spacing;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<add-widget route="/new-project"></add-widget>
|
||||
<add-widget route="/new-project" data-cy="add-project-button"></add-widget>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -6,14 +6,15 @@
|
|||
import AddWidget from '@/components/AddWidget';
|
||||
|
||||
export default {
|
||||
props: ['project'],
|
||||
|
||||
components: {
|
||||
AddWidget
|
||||
},
|
||||
|
||||
methods: {
|
||||
addProjectEntry() {
|
||||
console.log('click');
|
||||
this.$store.dispatch('addProjectEntry', '');
|
||||
this.$store.dispatch('addProjectEntry', this.project);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<project-form
|
||||
:project="project"
|
||||
@save="updateProject"
|
||||
></project-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProjectForm from '@/components/portfolio/ProjectForm';
|
||||
|
||||
import UPDATE_PROJECT_MUTATION from '@/graphql/gql/mutations/updateProject.gql';
|
||||
|
||||
export default {
|
||||
props: ['project'],
|
||||
|
||||
components: {
|
||||
ProjectForm
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateProject(project) {
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_PROJECT_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
project: {
|
||||
id: project.id,
|
||||
title: project.title,
|
||||
description: project.description,
|
||||
appearance: project.appearance,
|
||||
objectives: project.objectives
|
||||
}
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
this.$router.push('/portfolio');
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,13 +1,17 @@
|
|||
<template>
|
||||
<modal :hide-header="true">
|
||||
<div class="project-entry-modal">
|
||||
<text-form-with-help-text title="Tätigkeit" :value="value">
|
||||
<text-form-with-help-text title="Tätigkeit" :value="activity" @change="activity = $event">
|
||||
</text-form-with-help-text>
|
||||
<text-form-with-help-text title="Reflexion" :value="value">
|
||||
<text-form-with-help-text title="Reflexion" :value="reflection" @change="reflection = $event">
|
||||
</text-form-with-help-text>
|
||||
<text-form-with-help-text title="Nächste Schritte" :value="value">
|
||||
<text-form-with-help-text title="Nächste Schritte" :value="nextSteps" @change="nextSteps = $event">
|
||||
</text-form-with-help-text>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<a class="button button--primary" data-cy="modal-save-button" v-on:click="save">Speichern</a>
|
||||
<a class="button" v-on:click="hideModal">Abbrechen</a>
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
|
|
@ -15,15 +19,65 @@
|
|||
import Modal from '@/components/Modal';
|
||||
import TextFormWithHelpText from '@/components/content-forms/TextFormWithHelpText';
|
||||
|
||||
import NEW_PROJECT_ENTRY_MUTATION from '@/graphql/gql/mutations/addProjectEntry.gql';
|
||||
import PROJECT_QUERY from '@/graphql/gql/projectQuery.gql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Modal,
|
||||
TextFormWithHelpText
|
||||
},
|
||||
|
||||
computed: {
|
||||
project() {
|
||||
return this.$store.state.parentProject;
|
||||
},
|
||||
slug() {
|
||||
return this.$route.params.slug;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
save() {
|
||||
this.$apollo.mutate({
|
||||
mutation: NEW_PROJECT_ENTRY_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
projectEntry: Object.assign({}, {
|
||||
nextSteps: this.nextSteps,
|
||||
activity: this.activity,
|
||||
reflection: this.reflection,
|
||||
project: this.project
|
||||
})
|
||||
}
|
||||
},
|
||||
update: (store, {data: {addProjectEntry: {projectEntry}}}) => {
|
||||
const query = PROJECT_QUERY;
|
||||
const variables = {slug: this.slug};
|
||||
const data = store.readQuery({query, variables});
|
||||
if (data.project && data.project.entries) {
|
||||
data.project.entries.edges.unshift({
|
||||
node: projectEntry,
|
||||
__typename: 'ProjectEntryNode'
|
||||
});
|
||||
store.writeQuery({query, variables, data});
|
||||
}
|
||||
}
|
||||
|
||||
}).then(() => {
|
||||
this.hideModal();
|
||||
});
|
||||
},
|
||||
hideModal() {
|
||||
this.$store.dispatch('hideModal');
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
value: ''
|
||||
activity: '',
|
||||
reflection: '',
|
||||
nextSteps: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
<template>
|
||||
<div class="portfolio">
|
||||
<add-project></add-project>
|
||||
|
||||
<project-widget
|
||||
v-for="project in projects"
|
||||
v-bind="project" :key="project.id"
|
||||
class="portfolio__project"
|
||||
></project-widget>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProjectWidget from '@/components/portfolio/ProjectWidget';
|
||||
import AddProject from '@/components/portfolio/AddProject';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ProjectWidget,
|
||||
AddProject
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
projects: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Quartalsarbeit: Mein Lehrbetrieb',
|
||||
appearance: 'green',
|
||||
slug: 'quartalsarbeit'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Mein Projekt 2',
|
||||
appearance: 'red',
|
||||
slug: 'mein-projekt-2'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Mein Projekt 3',
|
||||
appearance: 'blue',
|
||||
slug: 'mein-projekt-3'
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.portfolio {
|
||||
|
||||
display: -ms-grid;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
grid-row-gap: 30px;
|
||||
grid-auto-rows: 200px;
|
||||
width: 640px;
|
||||
justify-self: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,27 +2,30 @@
|
|||
<div class="project-entry">
|
||||
<h3 class="project-entry__heading">Tätigkeit</h3>
|
||||
<p class="project-entry__paragraph">
|
||||
Ich führe das Interview mit meiner Kollegin durch.
|
||||
{{activity}}
|
||||
</p>
|
||||
<h3 class="project-entry__heading">Reflexion</h3>
|
||||
<p class="project-entry__paragraph">
|
||||
Da ich geeignete Fragen hatte, konnte meine Kollegin umfangreiche Antworten zum Thema geben. Die Eingangshalle
|
||||
eignete sich nicht als Interviewort, da es viele Nebengeräusche hatte. Wir fanden aber dann ein freies
|
||||
Klassenzimmer. Nicht nur die Fragen sind wichtig. Auch die Ortswahl, wo man das Interview aufzeichnen möchte,
|
||||
ist sehr wichtig für ein erfolgreiches Interview.
|
||||
{{reflection}}
|
||||
</p>
|
||||
<h3 class="project-entry__heading">
|
||||
Nächste Schritte
|
||||
</h3>
|
||||
<p class="project-entry__paragraph">
|
||||
Interview im Raum „Mein Lehrbetrieb“ ablegen.
|
||||
{{nextSteps}}
|
||||
</p>
|
||||
<div class="project-entry__date">
|
||||
21. Juni 2018
|
||||
{{created | date }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['activity', 'reflection', 'nextSteps', 'created']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_functions.scss";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
<template>
|
||||
<page-form @save="$emit('save', localProject)" title="Neues Projekt">
|
||||
<page-form-input label="Titel" v-model="localProject.title"></page-form-input>
|
||||
<page-form-input label="Beschreibung" type="textarea" v-model="localProject.description"></page-form-input>
|
||||
<page-form-input label="Ziele" type="textarea" v-model="localProject.objectives"></page-form-input>
|
||||
<color-chooser
|
||||
:selected-color="localProject.appearance"
|
||||
v-on:input="updateColor"
|
||||
></color-chooser>
|
||||
<template slot="footer">
|
||||
<button
|
||||
type="submit"
|
||||
class="button button--primary"
|
||||
data-cy="save-project-button"
|
||||
:class="{'button--disabled': !formValid}"
|
||||
:disabled="!formValid"
|
||||
>Speichern
|
||||
</button>
|
||||
<router-link to="/portfolio" tag="button" class="button">Abbrechen</router-link>
|
||||
</template>
|
||||
</page-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageForm from '@/components/page-form/PageForm';
|
||||
import PageFormInput from '@/components/page-form/PageFormInput';
|
||||
import ColorChooser from '@/components/ColorChooser';
|
||||
|
||||
export default {
|
||||
props: ['project'],
|
||||
|
||||
components: {
|
||||
PageForm,
|
||||
PageFormInput,
|
||||
ColorChooser
|
||||
},
|
||||
|
||||
computed: {
|
||||
formValid() {
|
||||
return this.localProject.title && this.localProject.description && this.localProject.objectives;
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
localProject: Object.assign({}, this.project),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateColor(newColor) {
|
||||
this.localProject.appearance = newColor;
|
||||
this.$store.dispatch('setSpecialContainerClass', newColor);
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$store.dispatch('setSpecialContainerClass', this.localProject.appearance);
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.$store.dispatch('setSpecialContainerClass', '');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,15 +1,19 @@
|
|||
<template>
|
||||
<div class="project-widget" :class="widgetClass">
|
||||
<router-link :to="{name: 'project', params: {slug: slug}}" tag="div" class="project-widget__content">
|
||||
<h3 class="project-widget__title">{{title}}</h3>
|
||||
|
||||
<entry-count-widget entry-count="4"></entry-count-widget>
|
||||
<owner-widget name="Hans Muster"></owner-widget>
|
||||
<h3 class="project-widget__title">{{title}}</h3>
|
||||
|
||||
<entry-count-widget :entry-count="entriesCount"></entry-count-widget>
|
||||
<owner-widget :name="owner"></owner-widget>
|
||||
</router-link>
|
||||
<widget-footer
|
||||
entity="Eintrag"
|
||||
></widget-footer>
|
||||
<widget-footer v-if="isOwner" class="project-widget__footer">
|
||||
<template slot-scope="scope">
|
||||
<li class="popover-links__link"><a @click="$emit('delete', id)">Projekt löschen</a></li>
|
||||
<li class="popover-links__link"><a @click="$emit('edit', id)">Projekt bearbeiten</a></li>
|
||||
<li v-if="!final" class="popover-links__link"><a @click="share(scope)">Projekt teilen</a></li>
|
||||
<li v-if="final" class="popover-links__link"><a @click="unshare(scope)">Projekt nicht mehr teilen</a></li>
|
||||
</template>
|
||||
</widget-footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -19,7 +23,7 @@
|
|||
import WidgetFooter from '@/components/WidgetFooter';
|
||||
|
||||
export default {
|
||||
props: ['title', 'appearance', 'slug'],
|
||||
props: ['title', 'appearance', 'slug', 'id', 'final', 'student', 'entriesCount', 'userId'],
|
||||
|
||||
components: {
|
||||
WidgetFooter,
|
||||
|
|
@ -28,8 +32,27 @@
|
|||
},
|
||||
|
||||
computed: {
|
||||
widgetClass() {
|
||||
widgetClass () {
|
||||
return `project-widget--${this.appearance}`;
|
||||
},
|
||||
isOwner () {
|
||||
return this.student.id === this.userId;
|
||||
},
|
||||
owner () {
|
||||
return `${this.student.firstName} ${this.student.lastName}`
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
share: function (scope) {
|
||||
this.updateShare(scope, true);
|
||||
},
|
||||
unshare: function (scope) {
|
||||
this.updateShare(scope, false);
|
||||
},
|
||||
updateShare: function (scope, state) {
|
||||
scope.hide();
|
||||
this.$emit('updateShare', this.id, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,14 +70,35 @@
|
|||
box-sizing: border-box;
|
||||
|
||||
display: -ms-grid;
|
||||
margin-bottom: $large-spacing;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
grid-template-rows: 150px 1fr;
|
||||
-ms-grid-rows: 150px 48px;
|
||||
-ms-grid-columns: 1fr;
|
||||
|
||||
&__content {
|
||||
padding: 23px;
|
||||
cursor: pointer;
|
||||
-ms-grid-row: 1;
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
display: -ms-grid;
|
||||
-ms-grid-rows: 50px 30px 30px;
|
||||
& > :nth-child(1) {
|
||||
-ms-grid-row: 1;
|
||||
}
|
||||
& > :nth-child(2) {
|
||||
-ms-grid-row: 2;
|
||||
}
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-row: 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&__title {
|
||||
|
|
@ -62,6 +106,10 @@
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
-ms-grid-row: 2;
|
||||
}
|
||||
|
||||
@include skillbox-colors;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
<template>
|
||||
<room-form
|
||||
:room="room"
|
||||
@save="addRoom"
|
||||
></room-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import RoomForm from '@/components/rooms/RoomForm';
|
||||
|
||||
import ADD_ROOM_MUTATION from '@/graphql/gql/mutations/addRoom.gql';
|
||||
import ROOMS_QUERY from '@/graphql/gql/roomsQuery.gql';
|
||||
|
||||
const defaultColor = 'blue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
RoomForm
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
room: {
|
||||
appearance: defaultColor,
|
||||
title: '',
|
||||
description: '',
|
||||
schoolClass: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addRoom(room) {
|
||||
this.$apollo.mutate({
|
||||
mutation: ADD_ROOM_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
room: room
|
||||
}
|
||||
},
|
||||
update: (store, {data: {addRoom: {room}}}) => {
|
||||
try {
|
||||
const data = store.readQuery({query: ROOMS_QUERY});
|
||||
if (data.rooms) {
|
||||
data.rooms.edges.push({
|
||||
node: room,
|
||||
__typename: 'RoomNode'
|
||||
});
|
||||
store.writeQuery({query: ROOMS_QUERY, data});
|
||||
}
|
||||
} catch (e) {
|
||||
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
this.$router.push('/rooms');
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
@ -4,13 +4,13 @@
|
|||
<a @click="showMenu = !showMenu" class="room-entry__more-link">
|
||||
<ellipses class="room-entry__ellipses"></ellipses>
|
||||
</a>
|
||||
<widget-popover entity="Eintrag"
|
||||
@delete="deleteRoomEntry"
|
||||
@edit="editRoomEntry"
|
||||
@hide-me="showMenu = false"
|
||||
<widget-popover @hide-me="showMenu = false"
|
||||
:id="id"
|
||||
class="room-entry__popover"
|
||||
v-if="showMenu"></widget-popover>
|
||||
v-if="showMenu">
|
||||
<li class="popover-links__link"><a @click="deleteRoomEntry(id)">Raum löschen</a></li>
|
||||
<li class="popover-links__link"><a @click="editRoomEntry(id)">Raum bearbeiten</a></li>
|
||||
</widget-popover>
|
||||
</div>
|
||||
<router-link :to="{name: 'article', params: { slug: slug }}" tag="div" class="room-entry__router-link">
|
||||
<div class="room-entry__header" v-if="image">
|
||||
|
|
|
|||
|
|
@ -1,33 +1,31 @@
|
|||
<template>
|
||||
<form class="room-form" @submit.prevent="$emit('save', localRoom)">
|
||||
<div class="room-form__content">
|
||||
<h1 class="room-form__heading">Neues Board</h1>
|
||||
<label class="room-form__property-heading" for="room-title">Titel</label>
|
||||
<input class="skillbox-input room-form__input" v-model="localRoom.title" id="room-title">
|
||||
<label class="room-form__property-heading" for="room-description">Beschreibung</label>
|
||||
<textarea class="skillbox-textarea room-form__textarea" v-model="localRoom.description"
|
||||
id="room-description"></textarea>
|
||||
<label class="room-form__property-heading" for="room-class">Klasse</label>
|
||||
<select
|
||||
class="skillbox-input room-form__input"
|
||||
id="room-class"
|
||||
v-model="localRoom.schoolClass"
|
||||
>
|
||||
<option :value="{}" disabled hidden>Klasse wählen</option>
|
||||
<option
|
||||
v-for="schoolClass in schoolClasses"
|
||||
:key="schoolClass.id"
|
||||
v-bind:value="schoolClass"
|
||||
>{{schoolClass.name}}
|
||||
</option>
|
||||
</select>
|
||||
<h2 class="room-form__property-heading">Farbe</h2>
|
||||
<room-colors
|
||||
:selected-color="localRoom.appearance"
|
||||
v-on:input="updateColor"
|
||||
></room-colors>
|
||||
</div>
|
||||
<div class="room-form__footer">
|
||||
<page-form class="room-form" @save="$emit('save', localRoom)" title="Neues Board">
|
||||
<page-form-input v-model="localRoom.title" label="Titel">
|
||||
</page-form-input>
|
||||
|
||||
<page-form-input v-model="localRoom.description" label="Beschreibung" type="textarea">
|
||||
</page-form-input>
|
||||
|
||||
<label class="room-form__property-heading" for="room-class">Klasse</label>
|
||||
<select
|
||||
class="skillbox-input room-form__input"
|
||||
id="room-class"
|
||||
v-model="localRoom.schoolClass"
|
||||
>
|
||||
<option :value="{}" disabled hidden>Klasse wählen</option>
|
||||
<option
|
||||
v-for="schoolClass in schoolClasses"
|
||||
:key="schoolClass.id"
|
||||
v-bind:value="schoolClass"
|
||||
>{{schoolClass.name}}
|
||||
</option>
|
||||
</select>
|
||||
<h2 class="room-form__property-heading">Farbe</h2>
|
||||
<color-chooser
|
||||
:selected-color="localRoom.appearance"
|
||||
v-on:input="updateColor"
|
||||
></color-chooser>
|
||||
<template slot="footer">
|
||||
<button
|
||||
type="submit"
|
||||
class="button button--primary room-form__save-button"
|
||||
|
|
@ -36,12 +34,14 @@
|
|||
>Speichern
|
||||
</button>
|
||||
<router-link to="/rooms" tag="button" class="button">Abbrechen</router-link>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
</page-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import RoomColors from '@/components/rooms/RoomColors';
|
||||
import ColorChooser from '@/components/ColorChooser';
|
||||
import PageForm from '@/components/page-form/PageForm';
|
||||
import PageFormInput from '@/components/page-form/PageFormInput';
|
||||
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
|
||||
|
|
@ -49,7 +49,9 @@
|
|||
props: ['room'],
|
||||
|
||||
components: {
|
||||
RoomColors
|
||||
ColorChooser,
|
||||
PageForm,
|
||||
PageFormInput
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
@ -93,37 +95,11 @@
|
|||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_functions.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.room-form {
|
||||
width: 710px;
|
||||
min-height: 760px;
|
||||
max-height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: $color-white;
|
||||
border-radius: $default-border-radius;
|
||||
display: grid;
|
||||
grid-template-rows: 1fr 65px;
|
||||
|
||||
&__heading {
|
||||
font-size: toRem(35px);
|
||||
}
|
||||
|
||||
&__content {
|
||||
padding: 26px;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
border-top: 1px solid $color-lightgrey;
|
||||
padding: 16px 26px;
|
||||
}
|
||||
|
||||
&__property-heading {
|
||||
display: block;
|
||||
font-size: toRem(21px);
|
||||
font-weight: 800;
|
||||
margin-bottom: 24px;
|
||||
font-family: $sans-serif-font-family;
|
||||
@include page-form-input-heading;
|
||||
}
|
||||
|
||||
&__input,
|
||||
|
|
|
|||
|
|
@ -5,13 +5,9 @@
|
|||
<room-group-widget v-bind="schoolClass"></room-group-widget>
|
||||
<entry-count-widget :entryCount="entryCount"></entry-count-widget>
|
||||
</router-link>
|
||||
<widget-footer
|
||||
v-if="canEditRoom"
|
||||
:on-delete="deleteRoom"
|
||||
:on-edit="editRoom"
|
||||
:id="id"
|
||||
entity="Raum"
|
||||
>
|
||||
<widget-footer v-if="canEditRoom">
|
||||
<li class="popover-links__link"><a @click="deleteRoom()">Raum löschen</a></li>
|
||||
<li class="popover-links__link"><a @click="editRoom()">Raum bearbeiten</a></li>
|
||||
</widget-footer>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -58,27 +54,28 @@
|
|||
},
|
||||
|
||||
methods: {
|
||||
deleteRoom(id) {
|
||||
deleteRoom() {
|
||||
const theId = this.id
|
||||
this.$apollo.mutate({
|
||||
mutation: DELETE_ROOM_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
id
|
||||
id: theId
|
||||
}
|
||||
},
|
||||
update(store, {data: {deleteRoom: {success}}}) {
|
||||
if (success) {
|
||||
const data = store.readQuery({query: ROOMS_QUERY});
|
||||
if (data) {
|
||||
data.rooms.edges.splice(data.rooms.edges.findIndex(edge => edge.node.id === id), 1);
|
||||
data.rooms.edges.splice(data.rooms.edges.findIndex(edge => edge.node.id === theId), 1);
|
||||
store.writeQuery({query: ROOMS_QUERY, data});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
editRoom(id) {
|
||||
this.$router.push({name: 'edit-room', params: {id: id}});
|
||||
editRoom() {
|
||||
this.$router.push({name: 'edit-room', params: {id: this.id}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,6 +90,7 @@
|
|||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
height: 260px;
|
||||
grid-template-rows: 210px 1fr;
|
||||
/*overflow: hidden;*/
|
||||
@include widget-shadow;
|
||||
|
|
@ -116,6 +114,21 @@
|
|||
padding: 22px;
|
||||
color: $color-darkgrey-1;
|
||||
cursor: pointer;
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
display: -ms-grid;
|
||||
-ms-grid-rows: 80px 30px 30px;
|
||||
& > :nth-child(1) {
|
||||
-ms-grid-row: 1;
|
||||
}
|
||||
& > :nth-child(2) {
|
||||
-ms-grid-row: 2;
|
||||
}
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-row: 3;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
<template>
|
||||
<div class="room-popover" v-click-outside="hidePopover">
|
||||
<a class="room-popover__link" @click="$emit('delete', id)">{{entity}} löschen</a>
|
||||
<a class="room-popover__link" @click="$emit('edit', id)">{{entity}} bearbeiten</a>
|
||||
<div class="widget-popover" v-click-outside="hidePopover">
|
||||
<ul class="widget-popover__links popover-links">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['id', 'entity'],
|
||||
|
||||
methods: {
|
||||
hidePopover() {
|
||||
this.$emit('hide-me');
|
||||
|
|
@ -21,23 +20,33 @@
|
|||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.room-popover {
|
||||
.widget-popover {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -110px;
|
||||
display: grid;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: $color-white;
|
||||
padding: 20px;
|
||||
z-index: 10;
|
||||
@include widget-shadow;
|
||||
}
|
||||
|
||||
.popover-links {
|
||||
|
||||
list-style: none;
|
||||
display: grid;
|
||||
|
||||
&__link {
|
||||
color: $color-grey;
|
||||
font-family: $sans-serif-font-family;
|
||||
font-size: toRem(14px);
|
||||
line-height: 1.5;
|
||||
padding: 5px 0;
|
||||
cursor: pointer;
|
||||
& > a {
|
||||
display: inline-block;
|
||||
color: $color-grey;
|
||||
font-family: $sans-serif-font-family;
|
||||
font-size: toRem(14px);
|
||||
line-height: 1.5;
|
||||
padding: 5px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
import moment from 'moment';
|
||||
|
||||
moment.locale('de');
|
||||
|
||||
export const dateFilter = value => {
|
||||
if (value) {
|
||||
return moment(String(value)).format('DD. MMMM YYYY');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#import "./fragments/projectParts.gql"
|
||||
query ProjectsQuery {
|
||||
projects {
|
||||
edges {
|
||||
node {
|
||||
...ProjectParts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
fragment ProjectEntryParts on ProjectEntryNode {
|
||||
id
|
||||
activity
|
||||
reflection
|
||||
nextSteps
|
||||
created
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
fragment ProjectParts on ProjectNode {
|
||||
id
|
||||
title
|
||||
appearance
|
||||
description
|
||||
slug
|
||||
objectives
|
||||
final
|
||||
student {
|
||||
firstName
|
||||
lastName
|
||||
id
|
||||
}
|
||||
entriesCount
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#import "../fragments/projectParts.gql"
|
||||
mutation AddProjectMutation($input: AddProjectInput!){
|
||||
addProject(input: $input){
|
||||
project {
|
||||
...ProjectParts
|
||||
}
|
||||
errors
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#import "../fragments/projectEntryParts.gql"
|
||||
mutation AddProjectEntryMutation($input: AddProjectEntryInput!) {
|
||||
addProjectEntry(input: $input) {
|
||||
projectEntry {
|
||||
...ProjectEntryParts
|
||||
}
|
||||
errors
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
mutation DeleteProject($input: DeleteProjectInput!) {
|
||||
deleteProject(input: $input) {
|
||||
success
|
||||
errors
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#import "../fragments/projectParts.gql"
|
||||
mutation UpdateProjectMutation($input: UpdateProjectInput!){
|
||||
updateProject(input: $input) {
|
||||
project {
|
||||
...ProjectParts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#import "./fragments/projectParts.gql"
|
||||
#import "./fragments/projectEntryParts.gql"
|
||||
query ProjectQuery($id: ID, $slug: String){
|
||||
project(slug: $slug, id: $id) {
|
||||
...ProjectParts
|
||||
entries {
|
||||
edges {
|
||||
node {
|
||||
...ProjectEntryParts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ query Topic($slug: String!){
|
|||
title
|
||||
teaser
|
||||
description
|
||||
vimeoId
|
||||
modules {
|
||||
edges {
|
||||
node {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
<style lang="scss">
|
||||
.blank-layout {
|
||||
/*
|
||||
For IE11
|
||||
*/
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,67 +1,38 @@
|
|||
<template>
|
||||
<div class="container skillbox" :class="specialContainerClass">
|
||||
<header class="header skillbox__header">
|
||||
<top-navigation></top-navigation>
|
||||
<router-link to="/" class="skillbox__header-logo">skillbox</router-link>
|
||||
<div class="user-header">
|
||||
<user-widget v-bind="me" :isProfile="isProfile"></user-widget>
|
||||
<logout-widget></logout-widget>
|
||||
</div>
|
||||
<book-navigation v-if="showSubnavigation">
|
||||
</book-navigation>
|
||||
</header>
|
||||
<header-bar class="header skillbox__header">
|
||||
</header-bar>
|
||||
|
||||
<filter-bar v-if="showFilter"></filter-bar>
|
||||
<mobile-header class="header skillbox__header skillbox__header--mobile"></mobile-header>
|
||||
|
||||
<router-view></router-view>
|
||||
<filter-bar v-if="showFilter" class="skillbox__filter-bar"></filter-bar>
|
||||
|
||||
<router-view class="skillbox__content"></router-view>
|
||||
<footer class="skillbox__footer">Footer</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TopNavigation from '@/components/TopNavigation.vue';
|
||||
import BookNavigation from '@/components/book-navigation/BookNavigation';
|
||||
import UserWidget from '@/components/UserWidget.vue';
|
||||
import FilterBar from '@/components/FilterBar.vue';
|
||||
import LogoutWidget from '@/components/LogoutWidget.vue';
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import FilterBar from '@/components/FilterBar';
|
||||
import HeaderBar from '@/components/HeaderBar';
|
||||
import MobileHeader from '@/components/MobileHeader';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TopNavigation,
|
||||
UserWidget,
|
||||
FilterBar,
|
||||
LogoutWidget,
|
||||
BookNavigation
|
||||
HeaderBar,
|
||||
MobileHeader
|
||||
},
|
||||
|
||||
computed: {
|
||||
showFilter() {
|
||||
return this.$route.meta.filter;
|
||||
},
|
||||
showSubnavigation() {
|
||||
return this.$route.meta.subnavigation;
|
||||
},
|
||||
specialContainerClass() {
|
||||
let cls = this.$store.state.specialContainerClass;
|
||||
return [cls ? `skillbox--${cls}` : '', {'skillbox--show-filter': this.showFilter}]
|
||||
},
|
||||
isProfile() {
|
||||
return this.$route.meta.isProfile;
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
me: {}
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: {
|
||||
query: ME_QUERY,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -72,7 +43,9 @@
|
|||
.skillbox {
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
grid-template-rows: auto 1fr;
|
||||
min-height: 100vh;
|
||||
grid-auto-rows: 1fr;
|
||||
|
|
@ -82,81 +55,41 @@
|
|||
|
||||
&--show-filter {
|
||||
grid-template-rows: auto auto 1fr;
|
||||
-ms-grid-rows: 50px 50px 30px 1fr; // 1 extra row for gap
|
||||
grid-template-areas: "h" "." "c";
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
|
||||
&--show-filter &__content {
|
||||
-ms-grid-row: 4;
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
|
||||
&--show-filter &__filter-bar {
|
||||
-ms-grid-row: 2;
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
display: -ms-grid;
|
||||
-ms-grid-rows: auto 32px 1fr; // 1 extra row for gap
|
||||
-ms-grid-rows: 50px 30px 1fr; // 1 extra row for gap
|
||||
-ms-grid-columns: 1fr;
|
||||
|
||||
@include skillbox-colors;
|
||||
|
||||
&__header {
|
||||
grid-area: h;
|
||||
display: -ms-grid;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
background-color: $color-white;
|
||||
grid-auto-rows: 50px;
|
||||
width: 100%;
|
||||
|
||||
@include desktop {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
-ms-grid-columns: 1fr 1fr 1fr;
|
||||
-ms-grid-rows: 60px 60px;
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
& > :nth-child(1) {
|
||||
-ms-grid-column: 1;
|
||||
-ms-grid-row-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-column: 3;
|
||||
-ms-grid-row-align: center;
|
||||
-ms-grid-column-align: end;
|
||||
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
& > :nth-child(4) {
|
||||
-ms-grid-row: 2;
|
||||
-ms-grid-column: 1;
|
||||
-ms-grid-column-span: 3;
|
||||
}
|
||||
|
||||
-ms-grid-row: 1;
|
||||
}
|
||||
|
||||
&__header-logo {
|
||||
color: #17A887;
|
||||
font-size: 36px;
|
||||
font-weight: 800;
|
||||
font-family: $sans-serif-font-family;
|
||||
display: flex;
|
||||
justify-self: center;
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
-ms-grid-column: 2;
|
||||
-ms-grid-row-align: center;
|
||||
-ms-grid-column-align: center;
|
||||
&__content {
|
||||
-ms-grid-row: 3;
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
|
|
@ -168,12 +101,12 @@
|
|||
* For IE10+
|
||||
*/
|
||||
& > :nth-child(2) {
|
||||
-ms-grid-row: 3;
|
||||
|
||||
}
|
||||
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-row: 4;
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.user-header {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -13,14 +13,19 @@
|
|||
.layout {
|
||||
&--simple {
|
||||
display: -ms-grid;
|
||||
display: grid;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
|
||||
@include desktop {
|
||||
grid-template-columns: 1fr 640px 1fr;
|
||||
-ms-grid-columns: 1fr 640px 1fr;
|
||||
|
||||
& > :nth-child(2) {
|
||||
grid-column: 2;
|
||||
-ms-grid-column: 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -31,8 +36,12 @@
|
|||
justify-self: end;
|
||||
cursor: pointer;
|
||||
|
||||
display:flex;
|
||||
justify-content:end;
|
||||
|
||||
@include desktop {
|
||||
grid-column: 3;
|
||||
-ms-grid-column: 3;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import VueAnalytics from 'vue-analytics';
|
|||
import { Validator, install as VeeValidate } from 'vee-validate/dist/vee-validate.minimal.esm.js';
|
||||
import { required, min } from 'vee-validate/dist/rules.esm.js';
|
||||
import veeDe from 'vee-validate/dist/locale/de';
|
||||
import {dateFilter} from './filters/date-filter'
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
|
|
@ -105,6 +106,8 @@ Vue.use(VeeValidate, {
|
|||
locale: 'de'
|
||||
});
|
||||
|
||||
Vue.filter('date', dateFilter);
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.book {
|
||||
padding-top: $large-spacing;
|
||||
|
||||
&__content {
|
||||
display: -ms-grid;
|
||||
@supports (display: grid) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<div class="edit-project-page">
|
||||
<edit-project :project="project" v-if="this.project.id"></edit-project>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// todo: refactor this, we don't need 2 components, remove editRoom or EditRoom component
|
||||
import EditProject from '@/components/portfolio/EditProject';
|
||||
|
||||
import PROJECT_QUERY from '@/graphql/gql/projectQuery.gql';
|
||||
|
||||
export default {
|
||||
props: ['id'],
|
||||
|
||||
components: {
|
||||
EditProject
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
project: {}
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
project: {
|
||||
query: PROJECT_QUERY,
|
||||
variables() {
|
||||
return {
|
||||
id: this.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
// todo: refactor this, we don't need 2 components, remove editRoom or EditRoom component
|
||||
import EditRoom from '@/components/rooms/EditRoom';
|
||||
|
||||
import ROOM_QUERY from '@/graphql/gql/roomQuery.gql';
|
||||
|
|
@ -41,11 +42,3 @@
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.edit-room-page {
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<project-form
|
||||
@save="saveProject"
|
||||
:project="project"
|
||||
></project-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProjectForm from '@/components/portfolio/ProjectForm';
|
||||
|
||||
import ADD_PROJECT_MUTATION from '@/graphql/gql/mutations/addProject.gql';
|
||||
import PROJECTS_QUERY from '@/graphql/gql/allProjects.gql';
|
||||
|
||||
const defaultAppearance = 'blue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ProjectForm
|
||||
},
|
||||
|
||||
computed: {
|
||||
project() {
|
||||
return {
|
||||
title: '',
|
||||
description: '',
|
||||
objectives: '',
|
||||
appearance: defaultAppearance
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
saveProject(project) {
|
||||
this.$apollo.mutate({
|
||||
mutation: ADD_PROJECT_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
project: project
|
||||
}
|
||||
},
|
||||
update: (store, {data: {addProject: {project}}}) => {
|
||||
try {
|
||||
const data = store.readQuery({query: PROJECTS_QUERY});
|
||||
if (data.projects) {
|
||||
data.projects.edges.unshift({
|
||||
node: project,
|
||||
__typename: 'ProjectNode'
|
||||
});
|
||||
store.writeQuery({query: PROJECTS_QUERY, data});
|
||||
}
|
||||
} catch (e) {
|
||||
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
this.$router.push('/portfolio');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,23 +1,61 @@
|
|||
<template>
|
||||
<div class="new-room-page">
|
||||
<new-room></new-room>
|
||||
</div>
|
||||
<room-form
|
||||
:room="room"
|
||||
@save="addRoom"
|
||||
></room-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NewRoom from '@/components/rooms/NewRoom';
|
||||
import RoomForm from '@/components/rooms/RoomForm';
|
||||
|
||||
import ADD_ROOM_MUTATION from '@/graphql/gql/mutations/addRoom.gql';
|
||||
import ROOMS_QUERY from '@/graphql/gql/roomsQuery.gql';
|
||||
|
||||
const defaultAppearance = 'blue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NewRoom
|
||||
}
|
||||
RoomForm
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
room: {
|
||||
appearance: defaultAppearance,
|
||||
title: '',
|
||||
description: '',
|
||||
schoolClass: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addRoom(room) {
|
||||
this.$apollo.mutate({
|
||||
mutation: ADD_ROOM_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
room: room
|
||||
}
|
||||
},
|
||||
update: (store, {data: {addRoom: {room}}}) => {
|
||||
try {
|
||||
const data = store.readQuery({query: ROOMS_QUERY});
|
||||
if (data.rooms) {
|
||||
data.rooms.edges.push({
|
||||
node: room,
|
||||
__typename: 'RoomNode'
|
||||
});
|
||||
store.writeQuery({query: ROOMS_QUERY, data});
|
||||
}
|
||||
} catch (e) {
|
||||
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
this.$router.push('/rooms');
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.new-room-page {
|
||||
display: grid;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,143 @@
|
|||
<template>
|
||||
<div class="portfolio-page">
|
||||
<portfolio></portfolio>
|
||||
<div class="portfolio__page">
|
||||
<div class="portfolio">
|
||||
<add-project class="portfolio__add-project"></add-project>
|
||||
|
||||
<project-widget
|
||||
v-for="project in projects"
|
||||
v-bind="project"
|
||||
:userId="userId"
|
||||
@delete="deleteProject"
|
||||
@updateShare="updateShareState"
|
||||
@edit="editProject"
|
||||
:key="project.id"
|
||||
class="portfolio__project"
|
||||
></project-widget>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Portfolio from '@/components/portfolio/Portfolio';
|
||||
import ProjectWidget from '@/components/portfolio/ProjectWidget';
|
||||
import AddProject from '@/components/portfolio/AddProject';
|
||||
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import PROJECTS_QUERY from '@/graphql/gql/allProjects.gql';
|
||||
import DELETE_PROJECT_MUTATION from '@/graphql/gql/mutations/deleteProject.gql';
|
||||
import UPDATE_PROJECT_MUTATION from '@/graphql/gql/mutations/updateProject.gql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Portfolio
|
||||
ProjectWidget,
|
||||
AddProject
|
||||
},
|
||||
|
||||
apollo: {
|
||||
projects: {
|
||||
query: PROJECTS_QUERY,
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).projects
|
||||
}
|
||||
},
|
||||
me: {
|
||||
query: ME_QUERY
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
projects: [],
|
||||
me: {}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
userId () {
|
||||
return this.me.id;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
deleteProject(id) {
|
||||
this.$apollo.mutate({
|
||||
mutation: DELETE_PROJECT_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
id
|
||||
}
|
||||
},
|
||||
update(store, {data: {deleteProject: {success}}}) {
|
||||
if (success) {
|
||||
const data = store.readQuery({query: PROJECTS_QUERY});
|
||||
|
||||
if (data) {
|
||||
data.projects.edges.splice(data.projects.edges.findIndex(edge => edge.node.id === id), 1);
|
||||
store.writeQuery({query: PROJECTS_QUERY, data});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
editProject(id) {
|
||||
this.$router.push({name: 'edit-project', params: { id }});
|
||||
},
|
||||
updateShareState(id, state) {
|
||||
const project = this.projects.filter(project => project.id === id)[0];
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_PROJECT_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
project: {
|
||||
id: project.id,
|
||||
title: project.title,
|
||||
description: project.description,
|
||||
appearance: project.appearance,
|
||||
objectives: project.objectives,
|
||||
final: state
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.portfolio-page {
|
||||
display: grid;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
|
||||
.portfolio {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
grid-row-gap: 30px;
|
||||
grid-auto-rows: 200px;
|
||||
max-width: 640px;
|
||||
width: auto;
|
||||
justify-self: center;
|
||||
box-sizing: border-box;
|
||||
padding: $large-spacing $medium-spacing;
|
||||
|
||||
&__page {
|
||||
display: flex;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
|
||||
padding-top: $large-spacing;
|
||||
}
|
||||
|
||||
/*IE10*/
|
||||
&__add-project {
|
||||
margin-bottom: $large-spacing;
|
||||
@supports (display: grid) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,28 +1,20 @@
|
|||
<template>
|
||||
<div class="project">
|
||||
<div class="project__header">
|
||||
<h1 class="project__title">Quartalsarbeit: Mein Lehrbetrieb</h1>
|
||||
<h1 class="project__title">{{project.title}}</h1>
|
||||
<p class="project__description">
|
||||
Das ist eine Beschreibung und kann maximal 200 Zeichen enthalten. Das ist eine Beschreibung und kann maximal 200
|
||||
Zeichen enthalten. Das ist eine Beschreibung und kann maximal 200 Zeichen enthalten.
|
||||
{{project.description}}
|
||||
</p>
|
||||
|
||||
<h2 class="project__objectives-title">Ziele</h2>
|
||||
<ul class="project__objectives">
|
||||
<li class="project__objective">Ich kann ein Interview mit geeigneten Fragen vorbereiten.</li>
|
||||
<li class="project__objective">Ich kann ein Interview führen und auf interessante oder ausweichende
|
||||
Antworten näher eingehen.
|
||||
</li>
|
||||
<li class="project__objective">Ich kann ein mündlich geführtes Interview in Standardsprache
|
||||
aufzeichnen.
|
||||
</li>
|
||||
<li class="project__objective" :key="index" v-for="(objective, index) in objectives">{{objective}}</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="project__content">
|
||||
<add-project-entry class="project__add-entry"></add-project-entry>
|
||||
<project-entry></project-entry>
|
||||
<project-entry></project-entry>
|
||||
<add-project-entry class="project__add-entry" :project="project.id"></add-project-entry>
|
||||
<project-entry v-bind="entry" v-for="(entry, index) in project.entries" :key="index"></project-entry>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -31,13 +23,42 @@
|
|||
import ProjectEntry from '@/components/portfolio/ProjectEntry';
|
||||
import AddProjectEntry from '@/components/portfolio/AddProjectEntry';
|
||||
|
||||
import PROJECT_QUERY from '@/graphql/gql/projectQuery.gql';
|
||||
|
||||
export default {
|
||||
props: ['slug'],
|
||||
|
||||
components: {
|
||||
AddProjectEntry,
|
||||
ProjectEntry
|
||||
},
|
||||
|
||||
computed: {
|
||||
objectives() {
|
||||
return this.project.objectives ? this.project.objectives.split('\n') : [];
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
project: {
|
||||
query: PROJECT_QUERY,
|
||||
variables() {
|
||||
return {
|
||||
slug: this.slug
|
||||
}
|
||||
},
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).project || {};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
project: {}
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$store.dispatch('setSpecialContainerClass', 'red');
|
||||
},
|
||||
|
|
@ -53,10 +74,8 @@
|
|||
@import "@/styles/_functions.scss";
|
||||
|
||||
.project {
|
||||
margin-bottom: -50px;
|
||||
|
||||
&__header {
|
||||
padding: 30px;
|
||||
padding: $large-spacing;
|
||||
}
|
||||
|
||||
&__add-entry {
|
||||
|
|
@ -88,12 +107,19 @@
|
|||
|
||||
&__content {
|
||||
background-color: $color-grey--lighter;
|
||||
display: grid;
|
||||
grid-template-columns: 840px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 840px;
|
||||
align-content: center;
|
||||
margin: 0 auto;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
width: auto;
|
||||
}
|
||||
grid-template-columns: minmax(max-content, 840px);
|
||||
grid-row-gap: 30px;
|
||||
justify-content: center;
|
||||
padding-top: 30px;
|
||||
padding-bottom: 50px;
|
||||
padding: $large-spacing $medium-spacing;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="rooms-page">
|
||||
<room-widget v-for="room in filteredRooms" v-bind="room" :key="room.name"></room-widget>
|
||||
<add-room v-if="canAddRoom" data-cy="add-room"></add-room>
|
||||
<add-room class="rooms-page__add-room" v-if="canAddRoom" data-cy="add-room"></add-room>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -63,7 +63,10 @@
|
|||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.rooms-page {
|
||||
display: -ms-grid;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: start;
|
||||
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
|
|
@ -71,6 +74,7 @@
|
|||
padding: 50px 15px;
|
||||
@include desktop {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
-ms-grid-columns: 1fr 30px 1fr 30px 1fr;
|
||||
padding: 50px 45px;
|
||||
}
|
||||
grid-column-gap: 30px;
|
||||
|
|
@ -81,26 +85,22 @@
|
|||
justify-self: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
-ms-grid-columns: 1fr 1fr 1fr;
|
||||
-ms-grid-rows: 260px;
|
||||
&__add-room {
|
||||
visibility: hidden;
|
||||
|
||||
/*
|
||||
* SHAME SHAME SHAME
|
||||
* this is very hacky, but we have a dynamic amount of elements. better to be safe than sorry
|
||||
* SHAME SHAME SHAME
|
||||
*/
|
||||
@for $i from 1 to 101 {
|
||||
& > :nth-child(#{$i}) {
|
||||
@if ($i%3) == 0 {
|
||||
-ms-grid-column: 3;
|
||||
} @else {
|
||||
-ms-grid-column: ($i%3);
|
||||
}
|
||||
@include desktop {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
-ms-grid-row: floor(($i - 1)/3)+1;
|
||||
& > div {
|
||||
flex: 0 0 30%;
|
||||
margin-bottom: $large-spacing;
|
||||
margin-right: 1%;
|
||||
|
||||
@supports (display: grid) {
|
||||
margin-bottom: inherit;
|
||||
margin-right: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<div class="start-page">
|
||||
<h1 class="start-page__title h1"><span class="start-page__my">my</span>skillbox</h1>
|
||||
<header-bar class="start-page__header"></header-bar>
|
||||
|
||||
<mobile-header class="start-page__header start-page__header--mobile"></mobile-header>
|
||||
|
||||
<div class="start-page__sections start-sections">
|
||||
|
||||
<section-block
|
||||
|
|
@ -43,20 +46,22 @@
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import SectionBlock from '@/components/SectionBlock.vue';
|
||||
import NewsTeaser from '@/components/NewsTeaser.vue';
|
||||
import HeaderBar from '@/components/HeaderBar';
|
||||
|
||||
import ContentsIllustration from '@/components/illustrations/ContentsIllustration';
|
||||
import PortfolioIllustration from '@/components/illustrations/PortfolioIllustration';
|
||||
import RoomsIllustration from '@/components/illustrations/RoomsIllustration';
|
||||
|
||||
import {meQuery} from '@/graphql/queries';
|
||||
import MobileHeader from '@/components/MobileHeader';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MobileHeader,
|
||||
HeaderBar,
|
||||
SectionBlock,
|
||||
NewsTeaser,
|
||||
ContentsIllustration,
|
||||
|
|
@ -97,11 +102,21 @@
|
|||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.start-page {
|
||||
display: grid;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
justify-content: stretch;
|
||||
}
|
||||
grid-template-rows: auto 1fr auto;
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
box-sizing: border-box;
|
||||
padding-top: 2*$large-spacing;
|
||||
|
||||
&__header {
|
||||
|
||||
}
|
||||
|
||||
&__title {
|
||||
color: $color-brand;
|
||||
|
|
@ -132,6 +147,8 @@
|
|||
padding-right: 120px;
|
||||
}
|
||||
display: -ms-grid;
|
||||
-ms-grid-column-align: center;
|
||||
-ms-grid-columns: 1fr 1fr 1fr;
|
||||
margin-bottom: 90px;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
|
|
@ -143,6 +160,24 @@
|
|||
grid-row-gap: 15px;
|
||||
grid-column-gap: 50px;
|
||||
justify-items: start;
|
||||
align-items: center;
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
& > :nth-child(1) {
|
||||
-ms-grid-row: 1;
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
& > :nth-child(2) {
|
||||
-ms-grid-row: 1;
|
||||
-ms-grid-column: 2;
|
||||
}
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-row: 1;
|
||||
-ms-grid-column: 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.news {
|
||||
|
|
@ -150,8 +185,39 @@
|
|||
color: $color-white;
|
||||
padding-top: $large-spacing;
|
||||
padding-bottom: $large-spacing;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
-ms-grid-columns: 1fr 1fr 1fr;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
grid-row-gap: $large-spacing;
|
||||
|
||||
@include desktop {
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
}
|
||||
|
||||
/*
|
||||
* For IE10+
|
||||
*/
|
||||
& > :nth-child(1) {
|
||||
-ms-grid-row: 1;
|
||||
-ms-grid-column: 1;
|
||||
}
|
||||
& > :nth-child(2) {
|
||||
-ms-grid-row: 1;
|
||||
-ms-grid-column: 2;
|
||||
}
|
||||
& > :nth-child(3) {
|
||||
-ms-grid-row: 1;
|
||||
-ms-grid-column: 3;
|
||||
}
|
||||
& > :nth-child(4) {
|
||||
-ms-grid-row: 1;
|
||||
-ms-grid-column: 4;
|
||||
}
|
||||
|
||||
@include desktop {
|
||||
/*padding-left: 120px;*/
|
||||
|
|
@ -166,29 +232,21 @@
|
|||
padding-bottom: 24px;
|
||||
text-align: center;
|
||||
color: inherit;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&__more {
|
||||
color: $color-white;
|
||||
font-family: $sans-serif-font-family;
|
||||
border-left: 1px solid $color-lightgrey;
|
||||
line-height: $default-line-height;
|
||||
padding-left: $medium-spacing;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
|
||||
&__teasers {
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
text-align: center;
|
||||
|
||||
@include desktop {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
text-align: left;
|
||||
border-left: 1px solid $color-lightgrey;
|
||||
}
|
||||
|
||||
grid-row-gap: 15px;
|
||||
grid-column-gap: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<div class="submissions-page">
|
||||
<div>
|
||||
<a class="button button--primary submissions-page__back" @click="back">Zurück zur Aufgabe</a>
|
||||
</div>
|
||||
|
||||
<assignment-with-submissions v-if="!$apollo.queries.assignment.loading"
|
||||
:assignment="assignment"></assignment-with-submissions>
|
||||
</div>
|
||||
|
|
@ -32,6 +36,12 @@
|
|||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
back() {
|
||||
this.$router.go(-1);
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
assignment: {
|
||||
|
|
@ -46,6 +56,11 @@
|
|||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.submissions-page {
|
||||
display: grid;
|
||||
|
||||
grid-row-gap: $large-spacing;
|
||||
grid-template-rows: auto 1fr;
|
||||
|
||||
@include desktop {
|
||||
width: 800px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@
|
|||
<p class="topic__teaser">
|
||||
{{topic.teaser}}
|
||||
</p>
|
||||
<div v-if="topic.vimeoId" class="topic__video-link" @click="openVideo">
|
||||
<play class="topic__video-link-icon"></play>
|
||||
<span class="topic__video-link-description">Video schauen</span>
|
||||
</div>
|
||||
<div class="topic__modules">
|
||||
<module-teaser v-for="module in modules" :key="module.id" v-bind="module"></module-teaser>
|
||||
</div>
|
||||
|
|
@ -12,11 +16,13 @@
|
|||
|
||||
<script>
|
||||
import ModuleTeaser from '@/components/modules/ModuleTeaser.vue';
|
||||
import Play from '@/components/icons/Play';
|
||||
import TOPIC_QUERY from '@/graphql/gql/topicQuery.gql';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ModuleTeaser
|
||||
ModuleTeaser,
|
||||
Play
|
||||
},
|
||||
|
||||
apollo: {
|
||||
|
|
@ -39,6 +45,12 @@
|
|||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
openVideo() {
|
||||
this.$store.dispatch('showFullscreenVideo', this.topic.vimeoId);
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
topic: {
|
||||
|
|
@ -60,6 +72,23 @@
|
|||
color: $color-darkgrey-1;
|
||||
width: 90%;
|
||||
@include lead-paragraph;
|
||||
margin-bottom: $large-spacing;
|
||||
}
|
||||
|
||||
&__video-link {
|
||||
margin-bottom: $large-spacing;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__video-link-icon {
|
||||
width: 40px;
|
||||
margin-right: $medium-spacing;
|
||||
}
|
||||
|
||||
&__video-link-description {
|
||||
@include heading-3;
|
||||
}
|
||||
|
||||
&__modules {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import newRoom from '@/pages/newRoom'
|
|||
import editRoom from '@/pages/editRoom'
|
||||
import article from '@/pages/article'
|
||||
import basicknowledge from '@/pages/basicknowledge'
|
||||
import basicknowledgeOverview from '@/pages/basicknowledge-overview'
|
||||
import basicknowledgeOverview from '@/pages/basicknowledgeOverview'
|
||||
import submissions from '@/pages/submissions'
|
||||
import p404 from '@/pages/p404'
|
||||
import start from '@/pages/start'
|
||||
|
|
@ -22,6 +22,10 @@ import passwordChange from '@/pages/passwordChange'
|
|||
import myClasses from '@/pages/myClasses'
|
||||
import activity from '@/pages/activity'
|
||||
import Router from 'vue-router'
|
||||
import editProject from '@/pages/editProject'
|
||||
import newProject from '@/pages/newProject'
|
||||
|
||||
import store from '@/store/index';
|
||||
|
||||
const routes = [
|
||||
{path: '/', component: start, meta: {layout: 'blank'}},
|
||||
|
|
@ -50,11 +54,18 @@ const routes = [
|
|||
{path: '/edit-room/:id', name: 'edit-room', component: editRoom, props: true},
|
||||
{path: '/room/:slug', name: 'room', component: room, props: true},
|
||||
{path: '/article/:slug', name: 'article', component: article, meta: {layout: 'simple'}},
|
||||
{path: '/basic-knowledge/', name: 'basic-knowledge-overview', component: basicknowledgeOverview, meta: {subnavigation: true}},
|
||||
{
|
||||
path: '/basic-knowledge/',
|
||||
name: 'basic-knowledge-overview',
|
||||
component: basicknowledgeOverview,
|
||||
meta: {subnavigation: true}
|
||||
},
|
||||
{path: '/basic-knowledge/:slug', name: 'basic-knowledge', component: basicknowledge, meta: {layout: 'simple'}},
|
||||
{path: '/submission/:id', name: 'submission', component: submission, meta: {layout: 'simple'}},
|
||||
{path: '/portfolio', name: 'portfolio', component: portfolio},
|
||||
{path: '/portfolio/:slug', name: 'project', component: project},
|
||||
{path: '/portfolio/:slug', name: 'project', component: project, props: true},
|
||||
{path: '/new-project/', name: 'new-project', component: newProject},
|
||||
{path: '/edit-project/:id', name: 'edit-project', component: editProject, props: true},
|
||||
{
|
||||
path: '/book',
|
||||
name: 'book',
|
||||
|
|
@ -83,7 +94,8 @@ const routes = [
|
|||
];
|
||||
|
||||
Vue.use(Router);
|
||||
export default new Router({
|
||||
|
||||
const router = new Router({
|
||||
routes,
|
||||
mode: 'history',
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
|
|
@ -92,4 +104,8 @@ export default new Router({
|
|||
}
|
||||
return {x: 0, y: 0}
|
||||
}
|
||||
})
|
||||
});
|
||||
router.afterEach((to, from) => {
|
||||
store.dispatch('showMobileNavigation', false);
|
||||
});
|
||||
export default router;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ export default new Vuex.Store({
|
|||
state: {
|
||||
specialContainerClass: '',
|
||||
showModal: '',
|
||||
showMobileNavigation: false,
|
||||
contentBlockPosition: {},
|
||||
scrollPosition: 0,
|
||||
filterForSchoolClass: '',
|
||||
|
|
@ -23,10 +24,18 @@ export default new Vuex.Store({
|
|||
infographic: {
|
||||
id: 0,
|
||||
type: ''
|
||||
}
|
||||
},
|
||||
vimeoId: null
|
||||
},
|
||||
|
||||
getters: {},
|
||||
getters: {
|
||||
showModal: state => {
|
||||
return state.showModal
|
||||
},
|
||||
showMobileNavigation: state => {
|
||||
return state.showMobileNavigation
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
setSpecialContainerClass({commit}, payload) {
|
||||
|
|
@ -51,6 +60,7 @@ export default new Vuex.Store({
|
|||
id: 0,
|
||||
type: ''
|
||||
});
|
||||
commit('setVimeoId', null);
|
||||
},
|
||||
resetContentBlockPosition({commit}) {
|
||||
commit('setContentBlockPosition', {});
|
||||
|
|
@ -102,6 +112,13 @@ export default new Vuex.Store({
|
|||
commit('setInfographic', payload);
|
||||
dispatch('showModal', 'fullscreen-infographic');
|
||||
},
|
||||
showFullscreenVideo({commit, dispatch}, payload) {
|
||||
commit('setVimeoId', payload);
|
||||
dispatch('showModal', 'fullscreen-video');
|
||||
},
|
||||
showMobileNavigation({commit}, payload) {
|
||||
commit('setShowMobileNavigation', payload);
|
||||
}
|
||||
},
|
||||
|
||||
mutations: {
|
||||
|
|
@ -149,6 +166,12 @@ export default new Vuex.Store({
|
|||
},
|
||||
setInfographic(state, payload) {
|
||||
state.infographic = payload;
|
||||
},
|
||||
setVimeoId(state, payload) {
|
||||
state.vimeoId = payload;
|
||||
},
|
||||
setShowMobileNavigation(state, payload) {
|
||||
state.showMobileNavigation = payload;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,15 +2,24 @@
|
|||
|
||||
&__header {
|
||||
grid-template-rows: 50px minmax(50px, max-content) auto;
|
||||
-ms-grid-rows: 50px 50px auto;
|
||||
grid-row-gap: 30px;
|
||||
display: -ms-grid;
|
||||
display: grid;
|
||||
display: -ms-flex;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
}
|
||||
|
||||
&__meta {
|
||||
border-bottom: 1px solid $color-lightgrey;
|
||||
align-self: end;
|
||||
padding: 20px 0;
|
||||
width: 100%;
|
||||
|
||||
margin-bottom: $large-spacing;
|
||||
@supports (display: grid) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
|
|
@ -24,8 +33,11 @@
|
|||
}
|
||||
|
||||
&__content {
|
||||
display: -ms-grid;
|
||||
display: grid;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
grid-row-gap: 40px;
|
||||
padding-bottom: 40px;
|
||||
|
||||
|
|
|
|||
|
|
@ -132,3 +132,9 @@
|
|||
font-family: $serif-font-family;
|
||||
font-size: toRem(18px);
|
||||
}
|
||||
|
||||
@mixin page-form-input-heading {
|
||||
display: block;
|
||||
margin-bottom: $medium-spacing;
|
||||
@include heading-3;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
|
||||
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"core-js": "^2.5.0",
|
||||
"regenerator-runtime": "^0.10.5"
|
||||
"babel-runtime": "6.26.0",
|
||||
"core-js": "2.5.7",
|
||||
"regenerator-runtime": "0.10.5"
|
||||
}
|
||||
},
|
||||
"babel-runtime": {
|
||||
|
|
@ -19,8 +19,8 @@
|
|||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||
"requires": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
"core-js": "2.5.7",
|
||||
"regenerator-runtime": "0.11.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"regenerator-runtime": {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
[report]
|
||||
omit =
|
||||
*/site-packages/*
|
||||
|
|
@ -5,3 +5,4 @@ USE_AWS=False
|
|||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_STORAGE_BUCKET_NAME=
|
||||
SENDGRID_API_KEY=
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ from books.schema.queries import BookQuery
|
|||
from core.schema.mutations.main import CoreMutations
|
||||
from objectives.mutations import ObjectiveMutations
|
||||
from objectives.schema import ObjectivesQuery
|
||||
from portfolio.mutations import PortfolioMutations
|
||||
from portfolio.schema import PortfolioQuery
|
||||
from rooms.mutations import RoomMutations
|
||||
from rooms.schema import RoomsQuery
|
||||
from users.schema import UsersQuery
|
||||
|
|
@ -20,15 +22,16 @@ from users.mutations import ProfileMutations
|
|||
|
||||
|
||||
class Query(UsersQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery, StudentSubmissionQuery,
|
||||
BasicKnowledgeQuery, graphene.ObjectType):
|
||||
BasicKnowledgeQuery, PortfolioQuery, graphene.ObjectType):
|
||||
node = relay.Node.Field()
|
||||
|
||||
if settings.DEBUG:
|
||||
debug = graphene.Field(DjangoDebug, name='__debug')
|
||||
|
||||
|
||||
class Mutation(BookMutations, RoomMutations, AssignmentMutations, ObjectiveMutations, CoreMutations,
|
||||
class Mutation(BookMutations, RoomMutations, AssignmentMutations, ObjectiveMutations, CoreMutations, PortfolioMutations,
|
||||
ProfileMutations, graphene.ObjectType):
|
||||
|
||||
if settings.DEBUG:
|
||||
debug = graphene.Field(DjangoDebug, name='__debug')
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
from django.test import RequestFactory, TestCase
|
||||
from graphene.test import Client
|
||||
from api.schema import schema
|
||||
from users.models import User
|
||||
from users.services import create_users
|
||||
|
||||
|
||||
def create_client(user):
|
||||
request = RequestFactory().get('/')
|
||||
request.user = user
|
||||
return Client(schema=schema, context_value=request)
|
||||
|
||||
|
||||
class DefaultUserTestCase(TestCase):
|
||||
def setUp(self):
|
||||
create_users()
|
||||
|
||||
self.teacher = User.objects.get(username='teacher')
|
||||
self.teacher2 = User.objects.get(username='teacher2')
|
||||
self.student1 = User.objects.get(username='student1')
|
||||
self.student2 = User.objects.get(username='student2')
|
||||
self.student_second_class = User.objects.get(username='student_second_class')
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import io
|
||||
import os
|
||||
|
||||
from django.apps import apps
|
||||
from graphene_django.filter import DjangoFilterConnectionField
|
||||
from graphql_relay.node.node import from_global_id
|
||||
|
||||
|
|
@ -53,3 +54,14 @@ def get_graphql_mutation(filename):
|
|||
mutation = f.read()
|
||||
|
||||
return mutation
|
||||
|
||||
|
||||
def get_by_id_or_slug(model, **kwargs):
|
||||
slug = kwargs.get('slug')
|
||||
id = kwargs.get('id')
|
||||
|
||||
if id is not None:
|
||||
return get_object(model, id)
|
||||
if slug is not None:
|
||||
return model.objects.get(slug=slug)
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -1,25 +1,13 @@
|
|||
from django.test import RequestFactory, TestCase
|
||||
from graphene.test import Client
|
||||
from graphql_relay import to_global_id
|
||||
|
||||
from api.utils import get_graphql_mutation
|
||||
from api.test_utils import create_client, DefaultUserTestCase
|
||||
from assignments.models import Assignment, StudentSubmission
|
||||
from books.factories import ModuleFactory
|
||||
from ..factories import AssignmentFactory
|
||||
from users.models import User
|
||||
from users.services import create_users
|
||||
from api.schema import schema
|
||||
|
||||
|
||||
class AssignmentPermissionsTestCase(TestCase):
|
||||
class AssignmentPermissionsTestCase(DefaultUserTestCase):
|
||||
def setUp(self):
|
||||
create_users()
|
||||
|
||||
self.teacher = User.objects.get(username='teacher')
|
||||
self.teacher2 = User.objects.get(username='teacher2')
|
||||
self.student1 = User.objects.get(username='student1')
|
||||
self.student2 = User.objects.get(username='student2')
|
||||
self.student_second_class = User.objects.get(username='student_second_class')
|
||||
super(AssignmentPermissionsTestCase, self).setUp()
|
||||
self.assignment = AssignmentFactory(
|
||||
owner=self.teacher
|
||||
)
|
||||
|
|
@ -27,10 +15,6 @@ class AssignmentPermissionsTestCase(TestCase):
|
|||
self.assignment_id = to_global_id('AssignmentNode', self.assignment.pk)
|
||||
self.module_id = to_global_id('ModuleNode', self.assignment.module.pk)
|
||||
|
||||
def _create_client(self, user):
|
||||
request = RequestFactory().get('/')
|
||||
request.user = user
|
||||
return Client(schema=schema, context_value=request)
|
||||
|
||||
def _submit_submission(self, user=None):
|
||||
mutation = '''
|
||||
|
|
@ -53,9 +37,9 @@ class AssignmentPermissionsTestCase(TestCase):
|
|||
'''
|
||||
|
||||
if user is None:
|
||||
client = self._create_client(self.student1)
|
||||
client = create_client(self.student1)
|
||||
else:
|
||||
client = self._create_client(user)
|
||||
client = create_client(user)
|
||||
|
||||
return client.execute(mutation, variables={
|
||||
'input': {
|
||||
|
|
@ -82,7 +66,7 @@ class AssignmentPermissionsTestCase(TestCase):
|
|||
self.assertEqual(StudentSubmission.objects.count(), 1)
|
||||
|
||||
def _test_visibility(self, user, count):
|
||||
client = self._create_client(user)
|
||||
client = create_client(user)
|
||||
query = '''
|
||||
query AssignmentWithSubmissions($id: ID!) {
|
||||
assignment(id: $id) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.0.6 on 2019-03-11 15:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('books', '0008_auto_20190301_0954'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='topic',
|
||||
name='vimeo_id',
|
||||
field=models.CharField(default=None, max_length=200, null=True),
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.0.6 on 2019-03-12 13:06
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('books', '0009_topic_vimeo_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='topic',
|
||||
name='vimeo_id',
|
||||
field=models.CharField(blank=True, default=None, max_length=200, null=True),
|
||||
),
|
||||
]
|
||||
|
|
@ -18,11 +18,13 @@ class Topic(StrictHierarchyPage):
|
|||
order = models.PositiveIntegerField(null=False, blank=False, help_text='Order of the topic')
|
||||
teaser = models.TextField()
|
||||
description = RichTextField(features=DEFAULT_RICH_TEXT_FEATURES)
|
||||
vimeo_id = models.CharField(max_length=200, blank=True, null=True, default=None)
|
||||
|
||||
content_panels = [
|
||||
FieldPanel('title', classname="full title"),
|
||||
FieldPanel('order'),
|
||||
FieldPanel('teaser'),
|
||||
FieldPanel('vimeo_id'),
|
||||
FieldPanel('description'),
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ class TopicNode(DjangoObjectType):
|
|||
class Meta:
|
||||
model = Topic
|
||||
only_fields = [
|
||||
'slug', 'title', 'meta_title', 'teaser', 'description',
|
||||
'slug', 'title', 'meta_title', 'teaser', 'description', 'vimeo_id'
|
||||
]
|
||||
filter_fields = {
|
||||
'slug': ['exact', 'icontains', 'in'],
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ INSTALLED_APPS = [
|
|||
'rooms',
|
||||
'assignments',
|
||||
'basicknowledge',
|
||||
'portfolio',
|
||||
'statistics',
|
||||
|
||||
'wagtail.contrib.forms',
|
||||
|
|
@ -347,4 +348,8 @@ WAGTAIL_SITE_NAME = 'skillbox'
|
|||
GRAPHQL_QUERIES_DIR = os.path.join(BASE_DIR, '..', 'client', 'src', 'graphql', 'gql')
|
||||
GRAPHQL_MUTATIONS_DIR = os.path.join(GRAPHQL_QUERIES_DIR, 'mutations')
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
EMAIL_BACKEND = 'sendgrid_backend.SendgridBackend'
|
||||
|
||||
SENDGRID_API_KEY = os.environ.get("SENDGRID_API_KEY")
|
||||
SENDGRID_SANDBOX_MODE_IN_DEBUG = False
|
||||
DEFAULT_FROM_EMAIL='noreply@myskillbox.ch'
|
||||
|
|
|
|||
|
|
@ -10,3 +10,7 @@ class DisableMigrations(object):
|
|||
|
||||
|
||||
MIGRATION_MODULES = DisableMigrations()
|
||||
|
||||
# Email Settings
|
||||
SENDGRID_API_KEY = ""
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
|
|
@ -7,7 +7,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
|
||||
<title>{% block title %}skillBox{% endblock %}</title>
|
||||
<title>{% block title %}skillbox{% endblock %}</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="skillBox">
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block body %}
|
||||
|
||||
<h1 class="logo">skillbox</h1>
|
||||
<h1 class="logo">myskillbox</h1>
|
||||
|
||||
{% if next %}
|
||||
<div class="h4">{% trans 'Melde dich jetzt an.' %}</div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@
|
|||
{% endblock %}
|
||||
{% trans "Dein Benutzername lautet:" %} {{ user.get_username }}
|
||||
|
||||
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
|
||||
{% trans "Dein Skillbox Team" %}
|
||||
|
||||
{% endautoescape %}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from django.conf.urls import url, include
|
|||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
from django.urls import re_path
|
||||
from django.views.generic import RedirectView
|
||||
from wagtail.admin import urls as wagtailadmin_urls
|
||||
from wagtail.core import urls as wagtail_urls
|
||||
|
||||
|
|
@ -18,7 +19,10 @@ urlpatterns = [
|
|||
url(r'^cms/', include(wagtailadmin_urls)),
|
||||
|
||||
# graphql backend
|
||||
url(r'^api/', include('api.urls', namespace="api"))
|
||||
url(r'^api/', include('api.urls', namespace="api")),
|
||||
|
||||
#favicon
|
||||
url(r'^favicon\.ico$', RedirectView.as_view(url='/static/favicon@2x.png', permanent=True))
|
||||
]
|
||||
|
||||
if settings.DEBUG and not settings.USE_AWS:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import graphene
|
||||
from graphene import relay, InputObjectType
|
||||
from graphql_relay import from_global_id
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
from api.utils import get_object
|
||||
from books.models import Module
|
||||
|
|
@ -67,13 +68,18 @@ class AddObjectiveGroup(relay.ClientIDMutation):
|
|||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||
|
||||
owner = info.context.user
|
||||
if not owner.has_perm('users.can_manage_school_class_content'):
|
||||
raise PermissionDenied('Missing permissions')
|
||||
|
||||
objective_group_data = kwargs.get('objective_group')
|
||||
title = objective_group_data.get('title')
|
||||
if title != 'society':
|
||||
title = 'language_communication'
|
||||
module_id = objective_group_data.get('module')
|
||||
module = get_object(Module, module_id)
|
||||
owner = info.context.user
|
||||
|
||||
new_objective_group = ObjectiveGroup.objects.create(title=title, module=module, owner=owner)
|
||||
objectives = objective_group_data.get('objectives')
|
||||
for objective in objectives:
|
||||
|
|
@ -89,9 +95,15 @@ class UpdateObjectiveGroup(relay.ClientIDMutation):
|
|||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||
|
||||
user = info.context.user
|
||||
if not user.has_perm('users.can_manage_school_class_content'):
|
||||
raise PermissionDenied('Missing permissions')
|
||||
|
||||
objective_group_data = kwargs.get('objective_group')
|
||||
id = objective_group_data.get('id')
|
||||
objective_group = get_object(ObjectiveGroup, id)
|
||||
|
||||
objectives = objective_group_data.get('objectives')
|
||||
existing_objective_ids = list(objective_group.objectives.values_list('id', flat=True))
|
||||
for objective in objectives:
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ class ObjectiveGroupNode(DjangoObjectType):
|
|||
return self.owner is not None and self.owner.pk == info.context.user.pk
|
||||
|
||||
|
||||
|
||||
class ObjectiveNode(DjangoObjectType):
|
||||
pk = graphene.Int()
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
# Create your tests here.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue