diff --git a/backend/package.json b/backend/package.json index 3fe3bb21d..27c6fb4fc 100644 --- a/backend/package.json +++ b/backend/package.json @@ -58,7 +58,7 @@ "graphql-redis-subscriptions": "^2.2.1", "graphql-shield": "~7.2.2", "graphql-tag": "~2.10.3", - "helmet": "~3.22.0", + "helmet": "~7.0.0", "ioredis": "^4.16.1", "jsonwebtoken": "~8.5.1", "languagedetect": "^2.0.0", diff --git a/backend/src/server.js b/backend/src/server.js index bcbd84617..86cc2a753 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -82,7 +82,11 @@ const createServer = (options) => { const app = express() app.set('driver', driver) - app.use(helmet()) + // TODO: this exception is required for the graphql playground, since the playground loads external resources + // See: https://github.com/graphql/graphql-playground/issues/1283 + app.use( + helmet(CONFIG.DEBUG && { contentSecurityPolicy: false, crossOriginEmbedderPolicy: false }), + ) app.use('/.well-known/', webfinger()) app.use(express.static('public')) app.use(bodyParser.json({ limit: '10mb' })) diff --git a/backend/yarn.lock b/backend/yarn.lock index 293e189dc..18887b92a 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -3022,11 +3022,6 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -bowser@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.9.0.tgz#3bed854233b419b9a7422d9ee3e85504373821c9" - integrity sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA== - boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" @@ -3243,11 +3238,6 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -camelize@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" - integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= - caniuse-lite@^1.0.30001219: version "1.0.30001230" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71" @@ -3672,11 +3662,6 @@ content-disposition@0.5.3: dependencies: safe-buffer "5.1.2" -content-security-policy-builder@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz#0a2364d769a3d7014eec79ff7699804deb8cfcbb" - integrity sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ== - content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -3926,11 +3911,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -dasherize@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dasherize/-/dasherize-2.0.0.tgz#6d809c9cd0cf7bb8952d80fc84fa13d47ddb1308" - integrity sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg= - data-urls@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-4.0.0.tgz#333a454eca6f9a5b7b0f1013ff89074c3f522dd4" @@ -4093,11 +4073,6 @@ denque@^1.1.0: resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - depd@^1.1.2, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -4147,11 +4122,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dns-prefetch-control@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz#73988161841f3dcc81f47686d539a2c702c88624" - integrity sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q== - doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -4307,11 +4277,6 @@ domutils@^3.0.1: domelementtype "^2.3.0" domhandler "^5.0.1" -dont-sniff-mimetype@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz#c7d0427f8bcb095762751252af59d148b0a623b2" - integrity sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug== - dot-prop@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" @@ -4871,11 +4836,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect-ct@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/expect-ct/-/expect-ct-0.2.0.tgz#3a54741b6ed34cc7a93305c605f63cd268a54a62" - integrity sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g== - expect@^29.4.2: version "29.4.2" resolved "https://registry.yarnpkg.com/expect/-/expect-29.4.2.tgz#2ae34eb88de797c64a1541ad0f1e2ea8a7a7b492" @@ -5036,11 +4996,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -feature-policy@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/feature-policy/-/feature-policy-0.3.0.tgz#7430e8e54a40da01156ca30aaec1a381ce536069" - integrity sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ== - figures@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9" @@ -5203,11 +5158,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -frameguard@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/frameguard/-/frameguard-3.1.0.tgz#bd1442cca1d67dc346a6751559b6d04502103a22" - integrity sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g== - franc@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/franc/-/franc-4.0.0.tgz#365951bc787b92ffbb1c63c1c492d6b76cbd3a56" @@ -5734,46 +5684,10 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -helmet-crossdomain@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e" - integrity sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA== - -helmet-csp@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.10.0.tgz#685dde1747bc16c5e28ad9d91e229a69f0a85e84" - integrity sha512-Rz953ZNEFk8sT2XvewXkYN0Ho4GEZdjAZy4stjiEQV3eN7GDxg1QKmYggH7otDyIA7uGA6XnUMVSgeJwbR5X+w== - dependencies: - bowser "2.9.0" - camelize "1.0.0" - content-security-policy-builder "2.1.0" - dasherize "2.0.0" - -helmet@~3.22.0: - version "3.22.0" - resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.22.0.tgz#3a6f11d931799145f0aff15dbc563cff9e13131f" - integrity sha512-Xrqicn2nm1ZIUxP3YGuTBmbDL04neKsIT583Sjh0FkiwKDXYCMUqGqC88w3NUvVXtA75JyR2Jn6jw6ZEMOD+ZA== - dependencies: - depd "2.0.0" - dns-prefetch-control "0.2.0" - dont-sniff-mimetype "1.1.0" - expect-ct "0.2.0" - feature-policy "0.3.0" - frameguard "3.1.0" - helmet-crossdomain "0.4.0" - helmet-csp "2.10.0" - hide-powered-by "1.1.0" - hpkp "2.0.0" - hsts "2.2.0" - ienoopen "1.1.0" - nocache "2.1.0" - referrer-policy "1.2.0" - x-xss-protection "1.3.0" - -hide-powered-by@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hide-powered-by/-/hide-powered-by-1.1.0.tgz#be3ea9cab4bdb16f8744be873755ca663383fa7a" - integrity sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg== +helmet@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/helmet/-/helmet-7.0.0.tgz#ac3011ba82fa2467f58075afa58a49427ba6212d" + integrity sha512-MsIgYmdBh460ZZ8cJC81q4XJknjG567wzEmv46WOBblDb6TUd3z8/GhgmsM9pn8g2B80tAJ4m5/d3Bi1KrSUBQ== homedir-polyfill@^1.0.1: version "1.0.3" @@ -5787,18 +5701,6 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== -hpkp@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hpkp/-/hpkp-2.0.0.tgz#10e142264e76215a5d30c44ec43de64dee6d1672" - integrity sha1-EOFCJk52IVpdMMROxD3mTe5tFnI= - -hsts@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/hsts/-/hsts-2.2.0.tgz#09119d42f7a8587035d027dda4522366fe75d964" - integrity sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ== - dependencies: - depd "2.0.0" - html-encoding-sniffer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" @@ -5981,11 +5883,6 @@ ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ienoopen@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.1.0.tgz#411e5d530c982287dbdc3bb31e7a9c9e32630974" - integrity sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ== - ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -8082,11 +7979,6 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" -nocache@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f" - integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q== - node-environment-flags@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" @@ -9158,11 +9050,6 @@ redis-parser@^3.0.0: dependencies: redis-errors "^1.0.0" -referrer-policy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/referrer-policy/-/referrer-policy-1.2.0.tgz#b99cfb8b57090dc454895ef897a4cc35ef67a98e" - integrity sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA== - regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -11047,11 +10934,6 @@ ws@^8.13.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== -x-xss-protection@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/x-xss-protection/-/x-xss-protection-1.3.0.tgz#3e3a8dd638da80421b0e9fff11a2dbe168f6d52c" - integrity sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg== - xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" diff --git a/package.json b/package.json index 7002e99f9..a1a6336df 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "release": "yarn version --no-git-tag-version --no-commit-hooks --no-commit && auto-changelog --latest-version $(node -p -e \"require('./package.json').version\") && cd backend && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp/maintenance/source && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../../../package.json').version\")" }, "devDependencies": { - "@babel/core": "^7.21.4", - "@babel/preset-env": "^7.21.4", + "@babel/core": "^7.21.8", + "@babel/preset-env": "^7.21.5", "@babel/register": "^7.12.10", "@faker-js/faker": "5.1.0", "auto-changelog": "^2.3.0", @@ -34,7 +34,7 @@ "cypress": "^7.0.1", "cypress-cucumber-preprocessor": "^2.2.1", "cypress-file-upload": "^3.5.3", - "date-fns": "^2.25.0", + "date-fns": "^2.30.0", "dotenv": "^8.2.0", "expect": "^29.5.0", "graphql-request": "^2.0.0", diff --git a/webapp/Dockerfile b/webapp/Dockerfile index d4f1f3fe1..5bebf9542 100644 --- a/webapp/Dockerfile +++ b/webapp/Dockerfile @@ -1,7 +1,7 @@ ################################################################################## # BASE (Is pushed to DockerHub for rebranding) ################################### ################################################################################## -FROM node:19.9.0-alpine3.17 as base +FROM node:20.1.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame diff --git a/webapp/Dockerfile.maintenance b/webapp/Dockerfile.maintenance index 3d844e915..dbd7d9bac 100644 --- a/webapp/Dockerfile.maintenance +++ b/webapp/Dockerfile.maintenance @@ -1,7 +1,7 @@ ################################################################################## # BASE ########################################################################### ################################################################################## -FROM node:19.9.0-alpine3.17 as base +FROM node:20.1.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame diff --git a/webapp/assets/_new/icons/svgs/book.svg b/webapp/assets/_new/icons/svgs/book.svg new file mode 100644 index 000000000..305e367ac --- /dev/null +++ b/webapp/assets/_new/icons/svgs/book.svg @@ -0,0 +1,5 @@ + + +book + + diff --git a/webapp/assets/_new/icons/svgs/calendar.svg b/webapp/assets/_new/icons/svgs/calendar.svg new file mode 100644 index 000000000..5a67a8299 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/calendar.svg @@ -0,0 +1,5 @@ + + +calendar + + diff --git a/webapp/assets/_new/styles/mixins/buttonStates.css b/webapp/assets/_new/styles/mixins/buttonStates.css new file mode 100644 index 000000000..27b24b9ce --- /dev/null +++ b/webapp/assets/_new/styles/mixins/buttonStates.css @@ -0,0 +1 @@ +/*# sourceMappingURL=buttonStates.css.map */ \ No newline at end of file diff --git a/webapp/assets/_new/styles/mixins/buttonStates.css.map b/webapp/assets/_new/styles/mixins/buttonStates.css.map new file mode 100644 index 000000000..aa1b02a29 --- /dev/null +++ b/webapp/assets/_new/styles/mixins/buttonStates.css.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":"","file":"buttonStates.css"} \ No newline at end of file diff --git a/webapp/assets/_new/styles/resets.css b/webapp/assets/_new/styles/resets.css new file mode 100644 index 000000000..b9aeaa72e --- /dev/null +++ b/webapp/assets/_new/styles/resets.css @@ -0,0 +1,29 @@ +* { + box-sizing: border-box; +} + +button { + padding: 0; + background: transparent; + border: none; + font-family: inherit; + font-size: inherit; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p, +li { + margin: 0; +} + +ol, +ul { + list-style-type: none; + margin: 0; + padding: 0; +}/*# sourceMappingURL=resets.css.map */ \ No newline at end of file diff --git a/webapp/assets/_new/styles/resets.css.map b/webapp/assets/_new/styles/resets.css.map new file mode 100644 index 000000000..e759c9680 --- /dev/null +++ b/webapp/assets/_new/styles/resets.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["resets.scss","resets.css"],"names":[],"mappings":"AAAA;EACE,sBAAA;ACCF;;ADEA;EACE,UAAA;EACA,uBAAA;EACA,YAAA;EACA,oBAAA;EACA,kBAAA;ACCF;;ADEA;;;;;;;;EAQE,SAAA;ACCF;;ADEA;;EAEE,qBAAA;EACA,SAAA;EACA,UAAA;ACCF","file":"resets.css"} \ No newline at end of file diff --git a/webapp/assets/_new/styles/tokens.css b/webapp/assets/_new/styles/tokens.css new file mode 100644 index 000000000..45bac6085 --- /dev/null +++ b/webapp/assets/_new/styles/tokens.css @@ -0,0 +1,122 @@ +/** + * @tokens Color Brand + * @presenter Color + */ +/** + * @tokens Color Neutral + * @presenter Color + */ +/** + * @tokens Color Text + * @presenter Color + */ +/** + * @tokens Color Background + * @presenter Color + */ +/** + * @tokens Color Border + * @presenter Color + */ +/** + * @tokens Border Size + * @presenter Border + */ +/** + * @tokens Border Radius + * @presenter BorderRadius + */ +/** + * @tokens Font Size + * @presenter FontSize + */ +/** + * @tokens Font Space + * @presenter Spacing + */ +/** + * @tokens Font Family + * @presenter FontFamily + */ +/** + * @tokens Font Weight + * @presenter FontWeight + */ +/** + * @tokens Line Height + * @presenter LineHeight + */ +/** + * @tokens Letter Spacing + * @presenter Spacing + */ +/** + * @tokens Opacity + * @presenter Opacity + */ +/** + * @tokens Space + * @presenter Spacing + */ +/** + * @tokens Size Height + * @presenter Spacing + */ +/** + * @tokens Size Width + * @presenter Spacing + */ +/** + * @tokens Size Avatar + * @presenter Spacing + */ +/** + * @tokens Size Buttons + * @presenter Spacing + */ +/** + * @tokens Size Images + * @presenter Spacing + */ +/** + * @tokens Size Icons + * @presenter Spacing + */ +/** + * @tokens Shadow + * @presenter Shadow + */ +/** + * @tokens Effects + */ +/** + * @tokens Animation Duration + */ +/** + * @tokens Animation Ease + * @presenter Easing + */ +/** + * @tokens Z-Index + */ +/** + * @tokens Media Query + */ +/** + * @tokens Background Images + */ +/** + * @tokens Header Color + */ +/** + * @tokens Footer Color + */ +/** + * @tokens Locale Menu Color + */ +/** + * @tokens Donation Bar Color + */ +/** + * @tokens Toast Color + *//*# sourceMappingURL=tokens.css.map */ \ No newline at end of file diff --git a/webapp/assets/_new/styles/tokens.css.map b/webapp/assets/_new/styles/tokens.css.map new file mode 100644 index 000000000..5111f4b00 --- /dev/null +++ b/webapp/assets/_new/styles/tokens.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["tokens.scss"],"names":[],"mappings":"AAAA;;;EAAA;AA4BA;;;EAAA;AAmBA;;;EAAA;AAuBA;;;EAAA;AAgCA;;;EAAA;AAeA;;;EAAA;AASA;;;EAAA;AAYA;;;EAAA;AAgBA;;;EAAA;AAgBA;;;EAAA;AAUA;;;EAAA;AAQA;;;EAAA;AAUA;;;EAAA;AAWA;;;EAAA;AASA;;;EAAA;AAgBA;;;EAAA;AAaA;;;EAAA;AASA;;;EAAA;AASA;;;EAAA;AASA;;;EAAA;AAUA;;;EAAA;AAQA;;;EAAA;AAcA;;EAAA;AAMA;;EAAA;AAUA;;;EAAA;AAWA;;EAAA;AAaA;;EAAA;AAUA;;EAAA;AAIA;;EAAA;AAMA;;EAAA;AAOA;;EAAA;AAMA;;EAAA;AAOA;;EAAA","file":"tokens.css"} \ No newline at end of file diff --git a/webapp/components/ContributionForm/ContributionForm.vue b/webapp/components/ContributionForm/ContributionForm.vue index f740e1f05..ae887d1d3 100644 --- a/webapp/components/ContributionForm/ContributionForm.vue +++ b/webapp/components/ContributionForm/ContributionForm.vue @@ -30,6 +30,7 @@ + + + +
+
+ + + + +
+ +
+
+ + + +
+
+ + + + + +
+ + + +
+ + {{ formData.eventVenue.length }}/{{ formSchema.eventVenue.max }} + + +
+
+ + +
+ + {{ formData.eventLocationName.length }}/{{ formSchema.eventLocationName.max }} + + +
+
+
+ +
+ + {{ $t('post.viewEvent.eventIsOnline') }} +
+
+ + - diff --git a/webapp/components/FilterMenu/CategoriesFilter.vue b/webapp/components/FilterMenu/CategoriesFilter.vue index bcbfc7d1c..8b96245fd 100644 --- a/webapp/components/FilterMenu/CategoriesFilter.vue +++ b/webapp/components/FilterMenu/CategoriesFilter.vue @@ -17,18 +17,22 @@ @@ -95,3 +99,13 @@ export default { }, } + diff --git a/webapp/components/FilterMenu/FilterMenuComponent.vue b/webapp/components/FilterMenu/FilterMenuComponent.vue index 7a582a7c4..708c3bc7c 100644 --- a/webapp/components/FilterMenu/FilterMenuComponent.vue +++ b/webapp/components/FilterMenu/FilterMenuComponent.vue @@ -3,6 +3,7 @@

{{ $t('filter-menu.filter-by') }}

+
@@ -13,6 +14,7 @@ diff --git a/webapp/components/PostTeaser/PostTeaser.vue b/webapp/components/PostTeaser/PostTeaser.vue index 228c4c90c..0ef5f62b9 100644 --- a/webapp/components/PostTeaser/PostTeaser.vue +++ b/webapp/components/PostTeaser/PostTeaser.vue @@ -11,6 +11,7 @@ }" :highlight="isPinned" > + @@ -19,11 +20,37 @@

{{ post.title }}

+ + + + + + + {{ $t('post.viewEvent.eventIsOnline') }} + + + {{ post.eventLocationName }} + + + + + + + {{ getEventDateString }} + + + +
@@ -91,6 +118,7 @@ import UserTeaser from '~/components/UserTeaser/UserTeaser' import { mapGetters } from 'vuex' import PostMutations from '~/graphql/PostMutations' import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers' +import { format } from 'date-fns' export default { name: 'PostTeaser', @@ -152,6 +180,20 @@ export default { isPinned() { return this.post && this.post.pinned }, + ribbonText() { + if (this.post.pinned) return this.$t('post.pinned') + if (this.post.postType[0] === 'Event') return this.$t('post.event') + return this.$t('post.name') + }, + getEventDateString() { + if (this.post.eventEnd) { + const eventStart = format(new Date(this.post.eventStart), 'dd.MM.') + const eventEnd = format(new Date(this.post.eventEnd), 'dd.MM.yyyy') + return `${eventStart} - ${eventEnd}` + } else { + return format(new Date(this.post.eventStart), 'dd.MM.yyyy') + } + }, }, methods: { async deletePostCallback() { @@ -235,6 +277,12 @@ export default { margin-bottom: $space-small; } + & .event-info { + display: flex; + align-items: center; + gap: 2px; + } + > .footer { display: flex; justify-content: space-between; diff --git a/webapp/components/Ribbon/index.vue b/webapp/components/Ribbon/index.vue index f54b456e5..ea7fd273a 100644 --- a/webapp/components/Ribbon/index.vue +++ b/webapp/components/Ribbon/index.vue @@ -1,5 +1,5 @@ @@ -12,6 +12,10 @@ export default { type: String, default: '', }, + typ: { + type: String, + default: 'blue', + }, }, } @@ -43,4 +47,11 @@ export default { } } } +.eventBg { + background-color: $color-success-active; + + &::before { + border-color: $color-success-active transparent transparent $color-success-active; + } +} diff --git a/webapp/graphql/PostMutations.js b/webapp/graphql/PostMutations.js index 8880a93b0..b4ec6731c 100644 --- a/webapp/graphql/PostMutations.js +++ b/webapp/graphql/PostMutations.js @@ -4,21 +4,30 @@ export default () => { return { CreatePost: gql` mutation ( + $id: ID $title: String! + $slug: String $content: String! $categoryIds: [ID] $image: ImageInput $groupId: ID + $postType: PostType + $eventInput: _EventInput ) { CreatePost( + id: $id title: $title + slug: $slug content: $content categoryIds: $categoryIds image: $image groupId: $groupId + postType: $postType + eventInput: $eventInput ) { - title + id slug + title content contentExcerpt language @@ -26,6 +35,21 @@ export default () => { url sensitive } + disabled + deleted + postType + author { + name + } + categories { + id + } + eventStart + eventVenue + eventLocation { + lng + lat + } } } `, diff --git a/webapp/graphql/PostQuery.js b/webapp/graphql/PostQuery.js index 1c6c76276..83eec2a30 100644 --- a/webapp/graphql/PostQuery.js +++ b/webapp/graphql/PostQuery.js @@ -24,6 +24,12 @@ export default (i18n) => { query Post($id: ID!) { Post(id: $id) { + postType + eventStart + eventEnd + eventVenue + eventLocationName + eventIsOnline ...post ...postCounts ...tagsCategoriesAndPinned @@ -66,6 +72,12 @@ export const filterPosts = (i18n) => { query Post($filter: _PostFilter, $first: Int, $offset: Int, $orderBy: [_PostOrdering]) { Post(filter: $filter, first: $first, offset: $offset, orderBy: $orderBy) { + postType + eventStart + eventEnd + eventVenue + eventLocationName + eventIsOnline ...post ...postCounts ...tagsCategoriesAndPinned @@ -103,6 +115,10 @@ export const profilePagePosts = (i18n) => { $orderBy: [_PostOrdering] ) { profilePagePosts(filter: $filter, first: $first, offset: $offset, orderBy: $orderBy) { + postType + eventStart + eventVenue + eventLocationName ...post ...postCounts ...tagsCategoriesAndPinned diff --git a/webapp/locales/de.json b/webapp/locales/de.json index fe39eed69..82b7c7bd4 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -278,6 +278,7 @@ "inappropriatePicture": "Dieses Bild kann für einige Menschen unangemessen sein.", "languageSelectLabel": "Sprache Deines Beitrags", "languageSelectText": "Sprache wählen", + "newEvent": "Erstelle einen neue Veranstaltung", "newPost": "Erstelle einen neuen Beitrag", "success": "Gespeichert!", "teaserImage": { @@ -377,9 +378,11 @@ }, "filter-menu": { "all": "Alle", + "article": "Artikel", "categories": "Themen", "deleteFilter": "Filter löschen", "emotions": "Emotionen", + "events": "Veranstaltungen", "filter-by": "Filtern nach ...", "following": "Nutzer denen ich folge", "languages": "Sprachen", @@ -395,6 +398,7 @@ } }, "order-by": "Sortieren nach ...", + "post-type": "Beitrags-Typ", "save": { "error": "Themen konnten nicht gespeichert werden!", "success": "Themen gespeichert!" @@ -684,6 +688,12 @@ "submitted": "Kommentar gesendet", "updated": "Änderungen gespeichert" }, + "createNewEvent": { + "forGroup": { + "title": "Für die Gruppe „{name}“" + }, + "title": "Erstelle ein neues Event" + }, "createNewPost": { "forGroup": { "title": "Für die Gruppe „{name}“" @@ -697,6 +707,7 @@ }, "title": "Bearbeite deinen Beitrag" }, + "event": "Veranstaltung", "menu": { "delete": "Beitrag löschen", "edit": "Beitrag bearbeiten", @@ -710,6 +721,14 @@ "takeAction": { "name": "Aktiv werden" }, + "viewEvent": { + "eventEnd": "Ende", + "eventIsOnline": "Online Veranstaltung", + "eventLocationName": "Stadt", + "eventStart": "Beginn", + "eventVenue": "Veranstaltungsort", + "title": "Veranstaltung" + }, "viewPost": { "forGroup": { "title": "In der Gruppe „{name}“" diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 92f5687c2..45a241957 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -278,6 +278,7 @@ "inappropriatePicture": "This image may be inappropriate for some people.", "languageSelectLabel": "Language of your contribution", "languageSelectText": "Select Language", + "newEvent": "Create a new Event", "newPost": "Create a new Post", "success": "Saved!", "teaserImage": { @@ -377,9 +378,11 @@ }, "filter-menu": { "all": "All", + "article": "Article", "categories": "Topics", "deleteFilter": "Delete filter", "emotions": "Emotions", + "events": "Events", "filter-by": "Filter by ...", "following": "Users I follow", "languages": "Languages", @@ -395,6 +398,7 @@ } }, "order-by": "Order by ...", + "post-type": "Post type", "save": { "error": "Failed saving topic settings!", "success": "Topics saved!" @@ -684,6 +688,12 @@ "submitted": "Comment submitted!", "updated": "Changes saved!" }, + "createNewEvent": { + "forGroup": { + "title": "For The Group “{name}”" + }, + "title": "Create A New Event" + }, "createNewPost": { "forGroup": { "title": "For The Group “{name}”" @@ -697,6 +707,7 @@ }, "title": "Edit Your Post" }, + "event": "Event", "menu": { "delete": "Delete post", "edit": "Edit post", @@ -710,6 +721,14 @@ "takeAction": { "name": "Take action" }, + "viewEvent": { + "eventEnd": "End", + "eventIsOnline": "Online Event", + "eventLocationName": "City", + "eventStart": "Start", + "eventVenue": "Venue", + "title": "Event" + }, "viewPost": { "forGroup": { "title": "In The Group “{name}”" diff --git a/webapp/package.json b/webapp/package.json index 095cb12ee..9c0b91155 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -60,6 +60,7 @@ "vue-observe-visibility": "^1.0.0", "vue-scrollto": "^2.20.0", "vue-sweetalert-icons": "~4.3.1", + "vue2-datepicker": "^3.11.1", "vuex-i18n": "~1.13.1", "xregexp": "^4.3.0", "zxcvbn": "^4.4.2" diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 6e104bc53..aeab3bcb1 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -2,7 +2,7 @@
- {{ $t('post.viewPost.title') }} + {{ heading }} {{ $t('post.viewPost.forGroup.title', { name: post.group.name }) }} @@ -54,6 +54,33 @@

{{ post.title }}

+ + + + + {{ post.eventVenue }} + + - + {{ post.eventLocationName }} + + + - + {{ $t('post.viewEvent.eventIsOnline') }} + + + + + {{ getEventDateString }} + + + + {{ getEventTimeString }} + + @@ -147,6 +174,7 @@ import { groupQuery } from '~/graphql/groups' import PostMutations from '~/graphql/PostMutations' import links from '~/constants/links.js' import SortCategories from '~/mixins/sortCategoriesMixin.js' +import { format } from 'date-fns' export default { name: 'PostSlug', @@ -218,6 +246,10 @@ export default { }, ] }, + heading() { + if (this.post?.postType[0] === 'Event') return this.$t('post.viewEvent.title') + return this.$t('post.viewPost.title') + }, menuModalsData() { return postMenuModalsData( // "this.post" may not always be defined at the beginning … @@ -256,6 +288,24 @@ export default { !this.post.group || (this.group && ['usual', 'admin', 'owner'].includes(this.group.myRole)) ) }, + getEventDateString() { + if (this.post.eventEnd) { + const eventStart = format(new Date(this.post.eventStart), 'dd.MM.') + const eventEnd = format(new Date(this.post.eventEnd), 'dd.MM.yyyy') + return eventStart + ' - ' + eventEnd + } else { + return format(new Date(this.post.eventStart), 'dd.MM.yyyy') + } + }, + getEventTimeString() { + if (this.post.eventEnd) { + const eventStart = format(new Date(this.post.eventStart), 'HH:mm') + const eventEnd = format(new Date(this.post.eventEnd), 'HH:mm') + return eventStart + ' - ' + eventEnd + } else { + return format(new Date(this.post.eventStart), 'HH:mm') + } + }, }, methods: { reply(message) { @@ -374,6 +424,12 @@ export default { filter: blur($blur-radius); } + & .event-info { + display: flex; + align-items: center; + gap: 2px; + } + .blur-toggle { position: absolute; bottom: 0; diff --git a/webapp/pages/post/create.vue b/webapp/pages/post/create.vue index 60309480d..c8419d08f 100644 --- a/webapp/pages/post/create.vue +++ b/webapp/pages/post/create.vue @@ -1,15 +1,56 @@