resolve conflicts
This commit is contained in:
commit
aca36b8a66
|
|
@ -40,3 +40,5 @@ server/media/
|
|||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
.coverage
|
||||
|
|
|
|||
1
Pipfile
1
Pipfile
|
|
@ -36,3 +36,4 @@ bleach = "*"
|
|||
newrelic = "*"
|
||||
sentry-sdk = "==0.7.2"
|
||||
"django-sendgrid-v5" = "*"
|
||||
coverage = "*"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "c0e186a3fb465dc3cb6985204c534ea52652af00103c61601d0f859bacdee533"
|
||||
"sha256": "97ff5ca56ac835d40353e34e32ec8333ccb23822bcf971644b7641429d9774e1"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
|
@ -41,19 +41,18 @@
|
|||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:39e9b6516a72864f5a6b69f38edac087cc4ba623095f4528b916620e63de32b3",
|
||||
"sha256:a3eb22bb975a200a69084ec2bb69819e483ad531bf05e7b73861fc1b333aad42"
|
||||
"sha256:3927beac97e5467f869d63d60920b83c2d39964f69fbf944bc1db724116bfe1a",
|
||||
"sha256:be88cae6f16bb9fe3b850b6c8259b297f60b46855175cadae57594c9a403c582"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.9.120"
|
||||
"version": "==1.9.124"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:2bf8768887bfb008406eec725eecf6f174307dac00f5fad244cdd5d39c6c2147",
|
||||
"sha256:c0f9c57e7a8c65f17a62a0926c3e73686f6ae1c08abf3b5a63cc3a5bcc4c437b"
|
||||
"sha256:bb756a8da2c6e3ccf42dccb0ac71c1df2e07844db339183da06f4e0285b251d0",
|
||||
"sha256:fc7560a2676df2f0bab4ef0638277b86e5a00944c2ce1c3bb124b3066e6d3d2a"
|
||||
],
|
||||
"markers": "python_version != '3.0.*' and python_version >= '2.6' and python_version != '3.1.*'",
|
||||
"version": "==1.12.120"
|
||||
"version": "==1.12.124"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
|
|
@ -74,9 +73,45 @@
|
|||
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
|
||||
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
|
||||
],
|
||||
"markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.3.*'",
|
||||
"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"
|
||||
|
|
@ -209,14 +244,12 @@
|
|||
"sha256:00b7011757c4907546f17d0e47df098b542ea2b04c966ee0e80a493aae2c13c8",
|
||||
"sha256:745ac8b9c9526e338696e07b7f2e206e5e317e5744e22fdd7c2894bf19af41f1"
|
||||
],
|
||||
"markers": "python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.0.*'",
|
||||
"version": "==1.0.4"
|
||||
},
|
||||
"future": {
|
||||
"hashes": [
|
||||
"sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"
|
||||
],
|
||||
"markers": "python_version != '3.1.*' and python_version != '3.2.*' and python_version != '3.0.*' and python_version >= '2.6'",
|
||||
"version": "==0.17.1"
|
||||
},
|
||||
"graphene": {
|
||||
|
|
@ -239,7 +272,6 @@
|
|||
"sha256:889e869be5574d02af77baf1f30b5db9ca2959f1c9f5be7b2863ead5a3ec6181",
|
||||
"sha256:9462e22e32c7f03b667373ec0a84d95fba10e8ce2ead08f29fbddc63b671b0c1"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version != '3.0.*' and python_version != '3.1.*'",
|
||||
"version": "==2.1"
|
||||
},
|
||||
"graphql-relay": {
|
||||
|
|
@ -261,7 +293,6 @@
|
|||
"sha256:20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3",
|
||||
"sha256:66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version != '3.0.*' and python_version != '3.1.*'",
|
||||
"version": "==1.0.1"
|
||||
},
|
||||
"idna": {
|
||||
|
|
@ -269,7 +300,6 @@
|
|||
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||
],
|
||||
"markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.3.*'",
|
||||
"version": "==2.8"
|
||||
},
|
||||
"jmespath": {
|
||||
|
|
@ -298,15 +328,14 @@
|
|||
"sha256:e8941881063691d50f9cc8b8d6d8fd7bec86a8c461b2a4fc87188a5fc44d6ba4",
|
||||
"sha256:f4b29b0c70d753c754a58aaad7c31ad3309ca4a26f9aa64e695157251f6832ad"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version != '3.0.*' and python_version != '3.1.*'",
|
||||
"version": "==0.18.0"
|
||||
},
|
||||
"newrelic": {
|
||||
"hashes": [
|
||||
"sha256:b0f2ef6c817d9b5389cb3ef0f06037abbd1c1ed1a4ae04f293dadeb0f78ea924"
|
||||
"sha256:1d08248dee0d33116a145de723a2ae86e57a10674145ce4c8af3c316423bd140"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.14.0.115"
|
||||
"version": "==4.16.0.116"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
|
|
@ -344,7 +373,6 @@
|
|||
"sha256:2ebbfc10b7abf6354403ed785fe4f04b9dfd421eb1a474ac8d187022228332af",
|
||||
"sha256:348f5f6c3edd4fd47c9cd65aed03ac1b31136d375aa63871a57d3e444c85655c"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version != '3.0.*' and python_version != '3.1.*'",
|
||||
"version": "==2.2.1"
|
||||
},
|
||||
"psycopg2": {
|
||||
|
|
@ -432,7 +460,6 @@
|
|||
"sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e",
|
||||
"sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"
|
||||
],
|
||||
"markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version < '4' and python_version >= '2.7' and python_version != '3.3.*'",
|
||||
"version": "==2.21.0"
|
||||
},
|
||||
"rjsmin": {
|
||||
|
|
@ -453,7 +480,6 @@
|
|||
"sha256:7b9ad3213bff7d357f888e0fab5101b56fa1a0548ee77d121c3a3dbfbef4cb2e",
|
||||
"sha256:f23d5cb7d862b104401d9021fc82e5fa0e0cf57b7660a1331425aab0c691d021"
|
||||
],
|
||||
"markers": "python_version != '3.0.*' and python_version >= '2.6' and python_version != '3.1.*'",
|
||||
"version": "==0.2.0"
|
||||
},
|
||||
"sendgrid": {
|
||||
|
|
@ -476,7 +502,6 @@
|
|||
"sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c",
|
||||
"sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8"
|
||||
],
|
||||
"markers": "python_version >= '2.6' and python_version != '3.0.*' and python_version != '3.1.*'",
|
||||
"version": "==3.4.0.3"
|
||||
},
|
||||
"six": {
|
||||
|
|
@ -484,7 +509,6 @@
|
|||
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
|
||||
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
|
||||
],
|
||||
"markers": "python_version != '3.0.*' and python_version >= '2.6' and python_version != '3.1.*'",
|
||||
"version": "==1.12.0"
|
||||
},
|
||||
"text-unidecode": {
|
||||
|
|
@ -553,21 +577,13 @@
|
|||
}
|
||||
},
|
||||
"develop": {
|
||||
"appnope": {
|
||||
"hashes": [
|
||||
"sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0",
|
||||
"sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"
|
||||
],
|
||||
"markers": "sys_platform == 'darwin'",
|
||||
"version": "==0.1.0"
|
||||
},
|
||||
"awscli": {
|
||||
"hashes": [
|
||||
"sha256:9cbc48eff6f8c9ee2072be2caf569dd5f18734d61e020556b792ba509bbb03f0",
|
||||
"sha256:e0b9afc24c591ecb04d02a34d9e8d3508a4bd25c713d10a358cdad09abbbcf8e"
|
||||
"sha256:87258e4719978f51dae8c62e15cd0486a778ddcb530645f3bc035239b800f184",
|
||||
"sha256:fbd9dc00ecd7060f36e5768122c9293672b82748fa224cb13e22e6322532d8db"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.16.130"
|
||||
"version": "==1.16.134"
|
||||
},
|
||||
"backcall": {
|
||||
"hashes": [
|
||||
|
|
@ -578,11 +594,10 @@
|
|||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:2bf8768887bfb008406eec725eecf6f174307dac00f5fad244cdd5d39c6c2147",
|
||||
"sha256:c0f9c57e7a8c65f17a62a0926c3e73686f6ae1c08abf3b5a63cc3a5bcc4c437b"
|
||||
"sha256:bb756a8da2c6e3ccf42dccb0ac71c1df2e07844db339183da06f4e0285b251d0",
|
||||
"sha256:fc7560a2676df2f0bab4ef0638277b86e5a00944c2ce1c3bb124b3066e6d3d2a"
|
||||
],
|
||||
"markers": "python_version != '3.0.*' and python_version >= '2.6' and python_version != '3.1.*'",
|
||||
"version": "==1.12.120"
|
||||
"version": "==1.12.124"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
|
|
@ -633,7 +648,6 @@
|
|||
"sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de",
|
||||
"sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"
|
||||
],
|
||||
"markers": "python_version != '3.0.*' and python_version >= '2.6' and python_version != '3.1.*'",
|
||||
"version": "==4.4.0"
|
||||
},
|
||||
"docutils": {
|
||||
|
|
@ -766,7 +780,6 @@
|
|||
"sha256:7b9ad3213bff7d357f888e0fab5101b56fa1a0548ee77d121c3a3dbfbef4cb2e",
|
||||
"sha256:f23d5cb7d862b104401d9021fc82e5fa0e0cf57b7660a1331425aab0c691d021"
|
||||
],
|
||||
"markers": "python_version != '3.0.*' and python_version >= '2.6' and python_version != '3.1.*'",
|
||||
"version": "==0.2.0"
|
||||
},
|
||||
"six": {
|
||||
|
|
@ -774,7 +787,6 @@
|
|||
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
|
||||
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
|
||||
],
|
||||
"markers": "python_version != '3.0.*' and python_version >= '2.6' and python_version != '3.1.*'",
|
||||
"version": "==1.12.0"
|
||||
},
|
||||
"traitlets": {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
describe('New project', () => {
|
||||
it('creates a new project and displays it', () => {
|
||||
cy.viewport('macbook-15');
|
||||
cy.login('rahel.cueni', 'test');
|
||||
|
||||
cy.visit('/portfolio');
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
@ -21,6 +23,8 @@
|
|||
import FullscreenInfographic from '@/components/FullscreenInfographic';
|
||||
import FullscreenVideo from '@/components/FullscreenVideo';
|
||||
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
|
||||
|
|
@ -29,6 +33,7 @@
|
|||
SimpleLayout,
|
||||
BlankLayout,
|
||||
Modal,
|
||||
MobileNavigation,
|
||||
NewContentBlockWizard,
|
||||
EditContentBlockWizard,
|
||||
NewRoomEntryWizard,
|
||||
|
|
@ -45,9 +50,7 @@
|
|||
layout() {
|
||||
return (this.$route.meta.layout || 'default') + '-layout';
|
||||
},
|
||||
showModal() {
|
||||
return this.$store.state.showModal
|
||||
}
|
||||
...mapGetters(['showModal', 'showMobileNavigation'])
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
|
@ -58,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;
|
||||
|
|
|
|||
|
|
@ -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,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;
|
||||
|
|
@ -23,6 +29,7 @@
|
|||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.top-navigation {
|
||||
display: flex;
|
||||
|
|
@ -38,5 +45,22 @@
|
|||
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>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
<style scoped lang="scss">
|
||||
@import "@/styles/_variables.scss";
|
||||
@import "@/styles/_mixins.scss";
|
||||
|
||||
.widget-footer {
|
||||
background-color: $color-grey--lighter;
|
||||
|
|
@ -47,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+
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -30,11 +30,19 @@
|
|||
box-sizing: border-box;
|
||||
background-color: $color-white;
|
||||
border-radius: $default-border-radius;
|
||||
display: grid;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
grid-template-rows: 1fr 55px;
|
||||
|
||||
&__page {
|
||||
display: grid;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<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>
|
||||
<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 v-if="isOwner">
|
||||
<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>
|
||||
|
|
@ -70,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 {
|
||||
|
|
@ -85,6 +106,10 @@
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
&__footer {
|
||||
-ms-grid-row: 2;
|
||||
}
|
||||
|
||||
@include skillbox-colors;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@
|
|||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
height: 260px;
|
||||
grid-template-rows: 210px 1fr;
|
||||
/*overflow: hidden;*/
|
||||
@include widget-shadow;
|
||||
|
|
@ -113,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 {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -110px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: $color-white;
|
||||
padding: 20px;
|
||||
z-index: 10;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
<style lang="scss">
|
||||
.blank-layout {
|
||||
/*
|
||||
For IE11
|
||||
*/
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,64 +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"></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}]
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
me: {}
|
||||
}
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: {
|
||||
query: ME_QUERY,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -69,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;
|
||||
|
|
@ -79,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 {
|
||||
|
|
@ -165,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 {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="portfolio__page">
|
||||
<div class="portfolio">
|
||||
<add-project></add-project>
|
||||
<add-project class="portfolio__add-project"></add-project>
|
||||
|
||||
<project-widget
|
||||
v-for="project in projects"
|
||||
|
|
@ -107,23 +107,37 @@
|
|||
@import "@/styles/_variables.scss";
|
||||
|
||||
.portfolio {
|
||||
display: -ms-grid;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@supports (display: grid) {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
grid-row-gap: 30px;
|
||||
grid-auto-rows: 200px;
|
||||
width: 640px;
|
||||
max-width: 640px;
|
||||
width: auto;
|
||||
justify-self: center;
|
||||
box-sizing: border-box;
|
||||
padding: $large-spacing $medium-spacing;
|
||||
|
||||
&__page {
|
||||
display: grid;
|
||||
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>
|
||||
|
|
|
|||
|
|
@ -107,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import project from '@/pages/project'
|
|||
import editProject from '@/pages/editProject'
|
||||
import newProject from '@/pages/newProject'
|
||||
|
||||
import store from '@/store/index';
|
||||
|
||||
const routes = [
|
||||
{path: '/', component: start, meta: {layout: 'blank'}},
|
||||
{
|
||||
|
|
@ -48,7 +50,12 @@ 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},
|
||||
|
|
@ -70,7 +77,8 @@ const routes = [
|
|||
];
|
||||
|
||||
Vue.use(Router);
|
||||
export default new Router({
|
||||
|
||||
const router = new Router({
|
||||
routes,
|
||||
mode: 'history',
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
|
|
@ -79,4 +87,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: '',
|
||||
|
|
@ -27,7 +28,14 @@ export default new Vuex.Store({
|
|||
vimeoId: null
|
||||
},
|
||||
|
||||
getters: {},
|
||||
getters: {
|
||||
showModal: state => {
|
||||
return state.showModal
|
||||
},
|
||||
showMobileNavigation: state => {
|
||||
return state.showMobileNavigation
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
setSpecialContainerClass({commit}, payload) {
|
||||
|
|
@ -108,6 +116,9 @@ export default new Vuex.Store({
|
|||
commit('setVimeoId', payload);
|
||||
dispatch('showModal', 'fullscreen-video');
|
||||
},
|
||||
showMobileNavigation({commit}, payload) {
|
||||
commit('setShowMobileNavigation', payload);
|
||||
}
|
||||
},
|
||||
|
||||
mutations: {
|
||||
|
|
@ -158,6 +169,9 @@ export default new Vuex.Store({
|
|||
},
|
||||
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;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
[report]
|
||||
omit =
|
||||
*/site-packages/*
|
||||
|
|
@ -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,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) {
|
||||
|
|
|
|||
|
|
@ -350,6 +350,6 @@ GRAPHQL_MUTATIONS_DIR = os.path.join(GRAPHQL_QUERIES_DIR, 'mutations')
|
|||
|
||||
EMAIL_BACKEND = 'sendgrid_backend.SendgridBackend'
|
||||
|
||||
SENDGRID_API_KEY = os.environ["SENDGRID_API_KEY"]
|
||||
SENDGRID_API_KEY = os.environ.get("SENDGRID_API_KEY")
|
||||
SENDGRID_SANDBOX_MODE_IN_DEBUG = False
|
||||
DEFAULT_FROM_EMAIL='noreply@myskillbox.ch'
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -4,12 +4,11 @@ from graphql_relay import to_global_id
|
|||
|
||||
from api.schema import schema
|
||||
from portfolio.factories import ProjectFactory
|
||||
from portfolio.models import Project
|
||||
from rooms.models import Room
|
||||
from users.factories import SchoolClassFactory
|
||||
from users.models import User, SchoolClass
|
||||
from users.models import User
|
||||
from users.services import create_users
|
||||
|
||||
from api.test_utils import create_client, DefaultUserTestCase
|
||||
from portfolio.models import Project
|
||||
|
||||
class ProjectQuery(TestCase):
|
||||
def setUp(self):
|
||||
|
|
@ -60,3 +59,30 @@ class ProjectQuery(TestCase):
|
|||
self.assertEqual(result.get('errors')[0]['message'], 'Permission denied: Incorrect project')
|
||||
|
||||
|
||||
class ProjectMutationsTestCase(DefaultUserTestCase):
|
||||
def test_add_project(self):
|
||||
client = create_client(self.student1)
|
||||
mutation = """
|
||||
mutation AddProjectMutation($input: AddProjectInput!){
|
||||
addProject(input: $input){
|
||||
project {
|
||||
id
|
||||
}
|
||||
errors
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
result = client.execute(mutation, variables={
|
||||
'input': {
|
||||
"project": {
|
||||
"title": "Rick Astley",
|
||||
"description": "She wants to dance with me",
|
||||
"objectives": "Dance with me",
|
||||
"appearance": "green"
|
||||
}
|
||||
}
|
||||
})
|
||||
self.assertIsNone(result.get('errors'))
|
||||
self.assertEqual(Project.objects.count(), 1)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.db import models
|
||||
from django_extensions.db.models import TitleDescriptionModel, TitleSlugDescriptionModel
|
||||
from django_extensions.db.models import TitleSlugDescriptionModel
|
||||
from wagtail.core.fields import StreamField
|
||||
|
||||
from books.blocks import ImageUrlBlock, LinkBlock, VideoBlock
|
||||
from books.models import ContentBlock, TextBlock
|
||||
from books.models import TextBlock
|
||||
from users.models import SchoolClass
|
||||
|
||||
|
||||
|
|
@ -37,3 +37,6 @@ class RoomEntry(TitleSlugDescriptionModel):
|
|||
|
||||
def __str__(self):
|
||||
return 'RoomEntry {}-{}-{}'.format(self.id, self.title, self.author)
|
||||
|
||||
def can_user_see_entry(self, user):
|
||||
return user.is_superuser or self.room.school_class.is_user_in_schoolclass(user)
|
||||
|
|
|
|||
|
|
@ -84,14 +84,24 @@ class MutateRoomEntry(relay.ClientIDMutation):
|
|||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||
room_entry_data = kwargs.get('room_entry')
|
||||
|
||||
if room_entry_data.get('room') is not None:
|
||||
room_entry_data['room'] = get_object(Room, room_entry_data.get('room')).id
|
||||
room_entry_data['author'] = info.context.user.pk
|
||||
|
||||
if room_entry_data.get('id') is not None:
|
||||
# update path
|
||||
instance = get_object(RoomEntry, room_entry_data.get('id'))
|
||||
|
||||
if not instance.room.school_class.is_user_in_schoolclass(info.context.user):
|
||||
raise Exception('You are in the wrong class')
|
||||
|
||||
if instance.author.pk != info.context.user.pk:
|
||||
raise Exception('You are not the author')
|
||||
|
||||
serializer = RoomEntrySerializer(instance, data=room_entry_data, partial=True)
|
||||
else:
|
||||
# add path
|
||||
room_entry_data['author'] = info.context.user.pk
|
||||
serializer = RoomEntrySerializer(data=room_entry_data)
|
||||
|
||||
if serializer.is_valid():
|
||||
|
|
|
|||
|
|
@ -56,14 +56,29 @@ class RoomsQuery(object):
|
|||
return Room.objects.filter(school_class__in=user.school_classes.all())
|
||||
|
||||
def resolve_room(self, info, **kwargs):
|
||||
return get_by_id_or_slug(Room, **kwargs)
|
||||
room = get_by_id_or_slug(Room, **kwargs)
|
||||
if room.school_class.is_user_in_schoolclass(info.context.user):
|
||||
return room
|
||||
else:
|
||||
return None
|
||||
|
||||
def resolve_room_entry(self, info, **kwargs):
|
||||
slug = kwargs.get('slug')
|
||||
id = kwargs.get('id')
|
||||
room_entry = None
|
||||
|
||||
if id is not None:
|
||||
return get_object(RoomEntry, id)
|
||||
room_entry = get_object(RoomEntry, id)
|
||||
if slug is not None:
|
||||
return RoomEntry.objects.get(slug=slug)
|
||||
return None
|
||||
room_entry = RoomEntry.objects.get(slug=slug)
|
||||
|
||||
if room_entry and room_entry.can_user_see_entry(info.context.user):
|
||||
return room_entry
|
||||
else:
|
||||
return None
|
||||
|
||||
def resolve_all_room_entries(self, info, **kwargs):
|
||||
if not info.context.user.is_superuser:
|
||||
return RoomEntry.objects.none()
|
||||
else:
|
||||
return RoomEntry.objects.all()
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ from core.factories import UserFactory
|
|||
from rooms.factories import RoomEntryFactory, RoomFactory
|
||||
from rooms.models import RoomEntry
|
||||
from users.factories import SchoolClassFactory
|
||||
from users.services import create_users
|
||||
|
||||
|
||||
class RoomEntryMutationsTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.user = UserFactory(username='aschi')
|
||||
self.another_user = UserFactory(username='pesche')
|
||||
self.yet_another_user = UserFactory(username='hansueli')
|
||||
s = SchoolClassFactory(users=[self.user, self.another_user])
|
||||
s2 = SchoolClassFactory(users=[self.yet_another_user])
|
||||
self.room_entry = RoomEntryFactory(author=self.user, room=RoomFactory(school_class=s))
|
||||
|
||||
request = RequestFactory().get('/')
|
||||
|
|
@ -64,3 +64,73 @@ class RoomEntryMutationsTestCase(TestCase):
|
|||
|
||||
self.assertIsNotNone(result.get('errors'))
|
||||
self.assertEqual(RoomEntry.objects.count(), 1)
|
||||
|
||||
def test_update_room_entry_not_owner_but_same_class(self):
|
||||
self.assertEqual(RoomEntry.objects.count(), 1)
|
||||
mutation = '''
|
||||
mutation UpdateRoomEntry($input: UpdateRoomEntryInput!){
|
||||
updateRoomEntry(input: $input) {
|
||||
roomEntry {
|
||||
title
|
||||
author {
|
||||
firstName
|
||||
}
|
||||
}
|
||||
errors
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
request = RequestFactory().get('/')
|
||||
request.user = self.another_user
|
||||
client = Client(schema=schema, context_value=request)
|
||||
|
||||
new_title = 'new title, Alte!'
|
||||
|
||||
result = client.execute(mutation, variables={
|
||||
'input': {
|
||||
'roomEntry': {
|
||||
'id': to_global_id('RoomEntryNode', self.room_entry.pk),
|
||||
'title': new_title
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
entry = RoomEntry.objects.get(pk=self.room_entry.pk)
|
||||
self.assertIsNotNone(result.get('errors'))
|
||||
self.assertEqual(entry.title, self.room_entry.title)
|
||||
|
||||
def test_update_room_entry_not_owner_from_other_class(self):
|
||||
self.assertEqual(RoomEntry.objects.count(), 1)
|
||||
mutation = '''
|
||||
mutation UpdateRoomEntry($input: UpdateRoomEntryInput!){
|
||||
updateRoomEntry(input: $input) {
|
||||
roomEntry {
|
||||
title
|
||||
author {
|
||||
firstName
|
||||
}
|
||||
}
|
||||
errors
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
request = RequestFactory().get('/')
|
||||
request.user = self.yet_another_user
|
||||
client = Client(schema=schema, context_value=request)
|
||||
|
||||
new_title = 'new title, Alte!'
|
||||
|
||||
result = client.execute(mutation, variables={
|
||||
'input': {
|
||||
'roomEntry': {
|
||||
'id': to_global_id('RoomEntryNode', self.room_entry.pk),
|
||||
'title': new_title
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
entry = RoomEntry.objects.get(pk=self.room_entry.pk)
|
||||
self.assertIsNotNone(result.get('errors'))
|
||||
self.assertEqual(entry.title, self.room_entry.title)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
from django.test import TestCase, RequestFactory
|
||||
from graphene.test import Client
|
||||
|
||||
from api.schema import schema
|
||||
from core.factories import UserFactory
|
||||
from rooms.factories import RoomFactory, RoomEntryFactory
|
||||
from users.factories import SchoolClassFactory
|
||||
|
||||
|
||||
class RoomQueryPermission(TestCase):
|
||||
|
||||
@staticmethod
|
||||
def get_first_contents(result):
|
||||
return result.get('data').get('rooms').get('edges')[0]
|
||||
|
||||
def setUp(self):
|
||||
self.user = UserFactory(username='aschi')
|
||||
self.another_user = UserFactory(username='pesche')
|
||||
sc1 = SchoolClassFactory(users=[self.user])
|
||||
sc2 = SchoolClassFactory(users=[self.another_user])
|
||||
self.room1 = RoomFactory(school_class=sc1)
|
||||
self.room2 = RoomFactory(school_class=sc2)
|
||||
|
||||
request = RequestFactory().get('/')
|
||||
request.user = self.user
|
||||
self.client = Client(schema=schema, context_value=request)
|
||||
|
||||
def test_student_should_only_see_rooms_of_class(self):
|
||||
|
||||
query = '''
|
||||
query {
|
||||
rooms {
|
||||
edges {
|
||||
node {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
result = self.client.execute(query)
|
||||
self.assertIsNone(result.get('errors'))
|
||||
self.assertEqual(len(result.get('data').get('rooms').get('edges')), 1)
|
||||
self.assertEqual(result.get('data').get('rooms').get('edges')[0].get('node').get('title'), self.room1.title)
|
||||
|
||||
def test_student_should_not_be_able_to_query_rooms_of_other_classes(self):
|
||||
|
||||
query = '''
|
||||
query RoomQuery($slug: String) {
|
||||
room(slug: $slug) {
|
||||
title
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
result = self.client.execute(query, variables={
|
||||
'slug': self.room2.slug
|
||||
})
|
||||
|
||||
self.assertIsNone(result.get('errors'))
|
||||
self.assertEqual(result.get('data').get('room'), None)
|
||||
|
||||
|
||||
class RoomEntryQueryPermissions(TestCase):
|
||||
|
||||
@staticmethod
|
||||
def get_first_contents(result):
|
||||
return result.get('data').get('rooms').get('edges')[0]
|
||||
|
||||
def setUp(self):
|
||||
self.user = UserFactory(username='aschi')
|
||||
self.another_user = UserFactory(username='pesche')
|
||||
sc1 = SchoolClassFactory(users=[self.user])
|
||||
sc2 = SchoolClassFactory(users=[self.another_user])
|
||||
room1 = RoomFactory(school_class=sc1)
|
||||
room2 = RoomFactory(school_class=sc2)
|
||||
self.roomEntry1 = RoomEntryFactory(room=room1, author=self.user)
|
||||
self.roomEntry2 = RoomEntryFactory(room=room2, author=self.another_user)
|
||||
|
||||
request = RequestFactory().get('/')
|
||||
request.user = self.user
|
||||
self.client = Client(schema=schema, context_value=request)
|
||||
|
||||
def test_user_should_see_room_entries_from_own_class(self):
|
||||
|
||||
query = '''
|
||||
query RoomEntryQuery($slug: String) {
|
||||
roomEntry(slug: $slug) {
|
||||
title
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
result = self.client.execute(query, variables={
|
||||
'slug': self.roomEntry1.slug
|
||||
})
|
||||
|
||||
self.assertIsNone(result.get('errors'))
|
||||
self.assertEqual(result.get('data').get('roomEntry').get('title'), self.roomEntry1.title)
|
||||
|
||||
def test_user_should_not_see_room_entries_from_orther_class(self):
|
||||
|
||||
query = '''
|
||||
query RoomEntryQuery($slug: String) {
|
||||
roomEntry(slug: $slug) {
|
||||
title
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
result = self.client.execute(query, variables={
|
||||
'slug': self.roomEntry2.slug
|
||||
})
|
||||
|
||||
self.assertIsNone(result.get('errors'))
|
||||
self.assertEqual(result.get('data').get('roomEntry'), None)
|
||||
|
|
@ -51,6 +51,9 @@ class SchoolClass(models.Model):
|
|||
def __str__(self):
|
||||
return 'SchoolClass {}-{}-{}'.format(self.id, self.name, self.year)
|
||||
|
||||
def is_user_in_schoolclass(self, user):
|
||||
return user.is_superuser or user.school_classes.filter(pk=self.id).count() > 0
|
||||
|
||||
|
||||
class Role(models.Model):
|
||||
key = models.CharField(_('Key'), max_length=100, blank=False, null=False, unique=True)
|
||||
|
|
|
|||
|
|
@ -45,3 +45,9 @@ class UsersQuery(object):
|
|||
|
||||
def resolve_me(self, info, **kwargs):
|
||||
return info.context.user
|
||||
|
||||
def resolve_all_users(self, info, **kwargs):
|
||||
if not info.context.user.is_superuser:
|
||||
return User.objects.none()
|
||||
else:
|
||||
return User.objects.all()
|
||||
|
|
|
|||
Loading…
Reference in New Issue