Merge branch 'master' of https://github.com/Human-Connection/Human-Connection into C-1187-terms-and-conditions-confirmed-function

This commit is contained in:
ogerly 2019-08-29 13:45:12 +02:00
commit c09e9a0149
22 changed files with 817 additions and 848 deletions

View File

@ -49,7 +49,7 @@
"apollo-client": "~2.6.4", "apollo-client": "~2.6.4",
"apollo-link-context": "~1.0.18", "apollo-link-context": "~1.0.18",
"apollo-link-http": "~1.5.15", "apollo-link-http": "~1.5.15",
"apollo-server": "~2.9.0", "apollo-server": "~2.9.1",
"apollo-server-express": "^2.9.0", "apollo-server-express": "^2.9.0",
"babel-plugin-transform-runtime": "^6.23.0", "babel-plugin-transform-runtime": "^6.23.0",
"bcryptjs": "~2.4.3", "bcryptjs": "~2.4.3",
@ -68,7 +68,7 @@
"graphql-middleware-sentry": "^3.2.0", "graphql-middleware-sentry": "^3.2.0",
"graphql-shield": "~6.0.6", "graphql-shield": "~6.0.6",
"graphql-tag": "~2.10.1", "graphql-tag": "~2.10.1",
"helmet": "~3.20.0", "helmet": "~3.20.1",
"jsonwebtoken": "~8.5.1", "jsonwebtoken": "~8.5.1",
"linkifyjs": "~2.1.8", "linkifyjs": "~2.1.8",
"lodash": "~4.17.14", "lodash": "~4.17.14",
@ -91,7 +91,7 @@
"metascraper-youtube": "^5.6.3", "metascraper-youtube": "^5.6.3",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"neo4j-driver": "~1.7.5", "neo4j-driver": "~1.7.5",
"neo4j-graphql-js": "^2.7.1", "neo4j-graphql-js": "^2.7.2",
"neode": "^0.3.2", "neode": "^0.3.2",
"node-fetch": "~2.6.0", "node-fetch": "~2.6.0",
"nodemailer": "^6.3.0", "nodemailer": "^6.3.0",
@ -110,15 +110,15 @@
"@babel/plugin-proposal-throw-expressions": "^7.2.0", "@babel/plugin-proposal-throw-expressions": "^7.2.0",
"@babel/preset-env": "~7.5.5", "@babel/preset-env": "~7.5.5",
"@babel/register": "~7.5.5", "@babel/register": "~7.5.5",
"apollo-server-testing": "~2.9.0", "apollo-server-testing": "~2.9.1",
"babel-core": "~7.0.0-0", "babel-core": "~7.0.0-0",
"babel-eslint": "~10.0.3", "babel-eslint": "~10.0.3",
"babel-jest": "~24.9.0", "babel-jest": "~24.9.0",
"chai": "~4.2.0", "chai": "~4.2.0",
"cucumber": "~5.1.0", "cucumber": "~5.1.0",
"eslint": "~6.2.1", "eslint": "~6.2.2",
"eslint-config-prettier": "~6.1.0", "eslint-config-prettier": "~6.1.0",
"eslint-config-standard": "~14.0.1", "eslint-config-standard": "~14.1.0",
"eslint-plugin-import": "~2.18.2", "eslint-plugin-import": "~2.18.2",
"eslint-plugin-jest": "~22.15.2", "eslint-plugin-jest": "~22.15.2",
"eslint-plugin-node": "~9.1.0", "eslint-plugin-node": "~9.1.0",

View File

@ -1407,7 +1407,7 @@ acorn-globals@^4.1.0:
acorn "^6.0.1" acorn "^6.0.1"
acorn-walk "^6.0.1" acorn-walk "^6.0.1"
acorn-jsx@^5.0.0: acorn-jsx@^5.0.2:
version "5.0.2" version "5.0.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f"
integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==
@ -1538,13 +1538,13 @@ anymatch@^2.0.0:
micromatch "^3.1.4" micromatch "^3.1.4"
normalize-path "^2.1.1" normalize-path "^2.1.1"
apollo-cache-control@0.8.1: apollo-cache-control@0.8.2:
version "0.8.1" version "0.8.2"
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.8.1.tgz#707c0b958c02c5b47ddf49a02f60ea88a64783fb" resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.8.2.tgz#0687e323053f907fd9bb601c1921de10799e24a0"
integrity sha512-yQy5KB/OuX90PsdztWc4vfc4R//ZmW/AxNgXKWga0xW5OzEsysdJWHAsTzb40/rkJ9VNeQ+0N5wGikiS+jSCzg== integrity sha512-rvx4DdoAAbWhm3L0IoWrxN+Zq2Xk4uAYbaiZk0Nhuc/y4AQUww3JV/z4EfCp3O5cy5/lNMW/tPOozcqi941awA==
dependencies: dependencies:
apollo-server-env "2.4.1" apollo-server-env "2.4.2"
graphql-extensions "0.8.1" graphql-extensions "0.10.1"
apollo-cache-inmemory@~1.6.3: apollo-cache-inmemory@~1.6.3:
version "1.6.3" version "1.6.3"
@ -1579,13 +1579,13 @@ apollo-client@~2.6.4:
tslib "^1.9.3" tslib "^1.9.3"
zen-observable "^0.8.0" zen-observable "^0.8.0"
apollo-datasource@0.6.1: apollo-datasource@0.6.2:
version "0.6.1" version "0.6.2"
resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.6.1.tgz#697870f564da90bee53fa30d07875cb46c4d6b06" resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.6.2.tgz#3eeb8f9660304a223c3f7aecfe0274376c876307"
integrity sha512-oy7c+9Up8PSZwJ1qTK9Idh1acDpIocvw+C0zcHg14ycvNz7qWHSwLUSaAjuQMd9SYFzB3sxfyEhyfyhIogT2+Q== integrity sha512-GlqTfLjKFxNYxGGACDjDXUpm/vPfvXhUI/Qc/YdkY4ess/wn7EFdrmbZGIY56RJtXD5M7qjsQIH15t132KoPmQ==
dependencies: dependencies:
apollo-server-caching "0.5.0" apollo-server-caching "0.5.0"
apollo-server-env "2.4.1" apollo-server-env "2.4.2"
apollo-engine-reporting-protobuf@0.4.0: apollo-engine-reporting-protobuf@0.4.0:
version "0.4.0" version "0.4.0"
@ -1594,18 +1594,18 @@ apollo-engine-reporting-protobuf@0.4.0:
dependencies: dependencies:
protobufjs "^6.8.6" protobufjs "^6.8.6"
apollo-engine-reporting@1.4.3: apollo-engine-reporting@1.4.4:
version "1.4.3" version "1.4.4"
resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.4.3.tgz#0fcb67de7a24bef4e7e59990981f923267ffdd00" resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.4.4.tgz#ab232dcaa81fe9718fb23e9782457c66dc86e817"
integrity sha512-xv27qfc9dhi1yaWOhNQRmfF+SoLy74hl+M42arpIWdkoDe22fVTmTIqxqGwo4TFR3Z2OkAV5tNzuuOI/icd0Rg== integrity sha512-FOk/HooLMesoKHo/TGOPYZuc2t4q9YwoeM+z0AGRUY70hL2o5Ie3x0XiMb+I5IVibR+jBIRRKP2ngmSFJ+LqSg==
dependencies: dependencies:
apollo-engine-reporting-protobuf "0.4.0" apollo-engine-reporting-protobuf "0.4.0"
apollo-graphql "^0.3.3" apollo-graphql "^0.3.3"
apollo-server-caching "0.5.0" apollo-server-caching "0.5.0"
apollo-server-env "2.4.1" apollo-server-env "2.4.2"
apollo-server-types "0.2.1" apollo-server-types "0.2.2"
async-retry "^1.2.1" async-retry "^1.2.1"
graphql-extensions "0.9.1" graphql-extensions "0.10.1"
apollo-env@0.5.1: apollo-env@0.5.1:
version "0.5.1" version "0.5.1"
@ -1675,26 +1675,26 @@ apollo-server-caching@0.5.0:
dependencies: dependencies:
lru-cache "^5.0.0" lru-cache "^5.0.0"
apollo-server-core@2.9.0: apollo-server-core@2.9.1:
version "2.9.0" version "2.9.1"
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.0.tgz#5db251093ee121a5f4d90a24d51aa4c21e421243" resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.1.tgz#ed876cd2f954dc3f4f1e735b997d4dbf29a629a5"
integrity sha512-IvKIgqOqEEB8nszlpHWzlhAu4376So2PgNhFP6UrlfNTllt/WDti5YMOHnVimPWIDHmLPKFan0+wfzpsoRCRdg== integrity sha512-ZWPGNdZv/SiPjfEU7Wwut9N9oAucGlbVT+XCnpUl93agvkg3fbeTCLYBbjAdSA0Q6opq0tvWVGzwXPLpx6jZcQ==
dependencies: dependencies:
"@apollographql/apollo-tools" "^0.4.0" "@apollographql/apollo-tools" "^0.4.0"
"@apollographql/graphql-playground-html" "1.6.24" "@apollographql/graphql-playground-html" "1.6.24"
"@types/graphql-upload" "^8.0.0" "@types/graphql-upload" "^8.0.0"
"@types/ws" "^6.0.0" "@types/ws" "^6.0.0"
apollo-cache-control "0.8.1" apollo-cache-control "0.8.2"
apollo-datasource "0.6.1" apollo-datasource "0.6.2"
apollo-engine-reporting "1.4.3" apollo-engine-reporting "1.4.4"
apollo-server-caching "0.5.0" apollo-server-caching "0.5.0"
apollo-server-env "2.4.1" apollo-server-env "2.4.2"
apollo-server-errors "2.3.1" apollo-server-errors "2.3.2"
apollo-server-plugin-base "0.6.1" apollo-server-plugin-base "0.6.2"
apollo-server-types "0.2.1" apollo-server-types "0.2.2"
apollo-tracing "0.8.1" apollo-tracing "0.8.2"
fast-json-stable-stringify "^2.0.0" fast-json-stable-stringify "^2.0.0"
graphql-extensions "0.10.0" graphql-extensions "0.10.1"
graphql-tag "^2.9.2" graphql-tag "^2.9.2"
graphql-tools "^4.0.0" graphql-tools "^4.0.0"
graphql-upload "^8.0.2" graphql-upload "^8.0.2"
@ -1702,23 +1702,23 @@ apollo-server-core@2.9.0:
subscriptions-transport-ws "^0.9.11" subscriptions-transport-ws "^0.9.11"
ws "^6.0.0" ws "^6.0.0"
apollo-server-env@2.4.1: apollo-server-env@2.4.2:
version "2.4.1" version "2.4.2"
resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-2.4.1.tgz#58264ecfeb151919e0f480320b4e3769be9f18f3" resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-2.4.2.tgz#8549caa7c8f57af88aadad5c2a0bb7adbcc5f76e"
integrity sha512-J4G1Q6qyb7KjjqvQdVM5HUH3QDb52VK1Rv+MWL0rHcstJx9Fh/NK0sS+nujrMfKw57NVUs2d4KuYtl/EnW/txg== integrity sha512-Qyi8fP8CWsBRAKs0fawMFauJj03I6N3ncWcGaVTuDppYluo4zjV6LqHfZ+YPWOx6apBihFNZap19RAhSnSwJLg==
dependencies: dependencies:
node-fetch "^2.1.2" node-fetch "^2.1.2"
util.promisify "^1.0.0" util.promisify "^1.0.0"
apollo-server-errors@2.3.1: apollo-server-errors@2.3.2:
version "2.3.1" version "2.3.2"
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.1.tgz#033cf331463ebb99a563f8354180b41ac6714eb6" resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.2.tgz#86bbd1ff8f0b5f16bfdcbb1760398928f9fce539"
integrity sha512-errZvnh0vUQChecT7M4A/h94dnBSRL213dNxpM5ueMypaLYgnp4hiCTWIEaooo9E4yMGd1qA6WaNbLDG2+bjcg== integrity sha512-twVCP8tNHFzxOzU3jf84ppBFSvjvisZVWlgF82vwG+qEEUaAE5h5DVpeJbcI1vRW4VQPuFV+B+FIsnlweFKqtQ==
apollo-server-express@2.9.0, apollo-server-express@^2.9.0: apollo-server-express@2.9.1, apollo-server-express@^2.9.0:
version "2.9.0" version "2.9.1"
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.9.0.tgz#9d2a2d9823422ef26bca15931669d3153dc8a08b" resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.9.1.tgz#9a8cb7fba579e68ddfa1953dfd066b751bca32f0"
integrity sha512-+057V6Ui1BX69jUlV6YDQ7Xw9CCBfowN/GauvyF09KnsjYUJ+cB1xf4mkj/HAjaz4ReXQaALJNr2qPYPXS4R6w== integrity sha512-3mmuojt9s9Gyqdf8fbdKtbw23UFYrtVQtTNASgVW8zCabZqs2WjYnijMRf1aL4u9VSl+BFMOZUPMYaeBX+u38w==
dependencies: dependencies:
"@apollographql/graphql-playground-html" "1.6.24" "@apollographql/graphql-playground-html" "1.6.24"
"@types/accepts" "^1.3.5" "@types/accepts" "^1.3.5"
@ -1726,8 +1726,8 @@ apollo-server-express@2.9.0, apollo-server-express@^2.9.0:
"@types/cors" "^2.8.4" "@types/cors" "^2.8.4"
"@types/express" "4.17.1" "@types/express" "4.17.1"
accepts "^1.3.5" accepts "^1.3.5"
apollo-server-core "2.9.0" apollo-server-core "2.9.1"
apollo-server-types "0.2.1" apollo-server-types "0.2.2"
body-parser "^1.18.3" body-parser "^1.18.3"
cors "^2.8.4" cors "^2.8.4"
graphql-subscriptions "^1.0.0" graphql-subscriptions "^1.0.0"
@ -1736,47 +1736,47 @@ apollo-server-express@2.9.0, apollo-server-express@^2.9.0:
subscriptions-transport-ws "^0.9.16" subscriptions-transport-ws "^0.9.16"
type-is "^1.6.16" type-is "^1.6.16"
apollo-server-plugin-base@0.6.1: apollo-server-plugin-base@0.6.2:
version "0.6.1" version "0.6.2"
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.6.1.tgz#b9c209aa2102a26c6134f51bfa1e4a8307b63b11" resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.6.2.tgz#807e734e130c6750db680a58cd0e572cc0794184"
integrity sha512-gLLF0kz4QOOyczDGWuR2ZNDfa1nHfyFNG76ue8Es0/0ujnMT9KoSokXkx1hDh0X7FFTMj/MelYYoNEqgTH88zw== integrity sha512-f7grbfoI5fPxGJDmrvG0ulWq8vFHwvJSUrcEChhiUCSMFZlpBil/1TSaxJRESiQqnoZ9s5WrVhzuwejxODGMYw==
dependencies: dependencies:
apollo-server-types "0.2.1" apollo-server-types "0.2.2"
apollo-server-testing@~2.9.0: apollo-server-testing@~2.9.1:
version "2.9.0" version "2.9.1"
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.9.0.tgz#fb5276e0761992ed493d84e998eaa4f696914519" resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.9.1.tgz#29d2524e84722a1319d9c1524b4f9d44379d6a49"
integrity sha512-N6c+wx5MaDZ0mWPzA11nKkkJjX+E3ubATY3G5ejprUsN8BiHENyEQ0EZh+dO0yL9+q/mUHix3p7Utax9odxBcw== integrity sha512-TzlHIYNZgF1OkGji/ew3zPxboifvA9aGXDwWJFu54o1400svH0Uh5L7TMhsTZ8F992syQUsUuI+KKMOFNg73+w==
dependencies: dependencies:
apollo-server-core "2.9.0" apollo-server-core "2.9.1"
apollo-server-types@0.2.1: apollo-server-types@0.2.2:
version "0.2.1" version "0.2.2"
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.2.1.tgz#553da40ea1ad779ef0390c250ddad7eb782fdf64" resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.2.2.tgz#c26ff57ca0b45d67dfd72312094097e2b1c28980"
integrity sha512-ls26d6jjY7x91ctLWtbpQHGW0lcFR1LcOpDvBQUC2aCwQzuW/6yV7F3hfcEdLR9pjIxcA4yAtFQcKf5olDWVkA== integrity sha512-/G4yXUF4Kc6PVCIF12r+oB8AXkE4UVnJoyZHeHiPeDpXklrjwIAtov2WM2mTcSZuZe1EuEkeDci4+tj5zFD39Q==
dependencies: dependencies:
apollo-engine-reporting-protobuf "0.4.0" apollo-engine-reporting-protobuf "0.4.0"
apollo-server-caching "0.5.0" apollo-server-caching "0.5.0"
apollo-server-env "2.4.1" apollo-server-env "2.4.2"
apollo-server@~2.9.0: apollo-server@~2.9.1:
version "2.9.0" version "2.9.1"
resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.9.0.tgz#32685712215d420ff5f3298b3b34e972e21ec1c6" resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.9.1.tgz#16ff443d43ea38f72fe20adea0803c46037b2b3b"
integrity sha512-KouRjMWn8pnR4KvVsFXT1GZYzH53J0+v9KwnLUKrLNo2G4KiZu5KhP+tEkF7uTlpHzdPMQAIbwjdXKzOH/r6ew== integrity sha512-iCGoRBOvwTUkDz6Nq/rKguMyhDiQdL3VneF0GTjBGrelTIp3YTIxk/qBFkIr2Chtm9ZZYkS6o+ZldUnxYFKg7A==
dependencies: dependencies:
apollo-server-core "2.9.0" apollo-server-core "2.9.1"
apollo-server-express "2.9.0" apollo-server-express "2.9.1"
express "^4.0.0" express "^4.0.0"
graphql-subscriptions "^1.0.0" graphql-subscriptions "^1.0.0"
graphql-tools "^4.0.0" graphql-tools "^4.0.0"
apollo-tracing@0.8.1: apollo-tracing@0.8.2:
version "0.8.1" version "0.8.2"
resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.8.1.tgz#220aeac6ad598c67f9333739155b7a56bd63ccab" resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.8.2.tgz#2d1ebef434c4e2803f9a3adfc7d2409690b3c378"
integrity sha512-zhVNC7N6hg9IJEeSEXFDxcnXD5GJQAbHxaoKVBKEolcIIsz6EGd700ORdagJgFKLReVp9O65HPrZJCg66sVx7g== integrity sha512-4SVxHZkKZX/7E6/4hAvEJXdHm+1BjQqtgEkv3ywyiVXoaKn0YNJL8BVIOI4GAt0qoc3KzT9MDJ1nf+SurUFjLQ==
dependencies: dependencies:
apollo-server-env "2.4.1" apollo-server-env "2.4.2"
graphql-extensions "0.8.1" graphql-extensions "0.10.1"
apollo-utilities@1.3.2, apollo-utilities@^1.0.1, apollo-utilities@^1.3.0, apollo-utilities@^1.3.2: apollo-utilities@1.3.2, apollo-utilities@^1.0.1, apollo-utilities@^1.3.0, apollo-utilities@^1.3.2:
version "1.3.2" version "1.3.2"
@ -2148,6 +2148,11 @@ boolbase@~1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
bowser@2.5.3:
version "2.5.3"
resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.5.3.tgz#811b0a24219c566c9a6ab3402bc8a13f35a18a96"
integrity sha512-aWCA+CKfKNL/WGzNgjmK+Whp57JMzboZMwJ5gy2jDj2bEIjbMCb3ImGX+V++5wsJftyFiDIbOjRXl60ycniVqg==
boxen@^1.2.1: boxen@^1.2.1:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
@ -3285,10 +3290,10 @@ eslint-config-prettier@~6.1.0:
dependencies: dependencies:
get-stdin "^6.0.0" get-stdin "^6.0.0"
eslint-config-standard@~14.0.1: eslint-config-standard@~14.1.0:
version "14.0.1" version "14.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.0.1.tgz#375c3636fb4bd453cb95321d873de12e4eef790b" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz#b23da2b76fe5a2eba668374f246454e7058f15d4"
integrity sha512-1RWsAKTDTZgA8bIM6PSC9aTGDAUlKqNkYNJlTZ5xYD/HYkIM6GlcefFvgcJ8xi0SWG5203rttKYX28zW+rKNOg== integrity sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA==
eslint-import-resolver-node@^0.3.2: eslint-import-resolver-node@^0.3.2:
version "0.3.2" version "0.3.2"
@ -3395,10 +3400,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
eslint@~6.2.1: eslint@~6.2.2:
version "6.2.1" version "6.2.2"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.2.1.tgz#66c2e4fe8b6356b9f01e828adc3ad04030122df1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.2.2.tgz#03298280e7750d81fcd31431f3d333e43d93f24f"
integrity sha512-ES7BzEzr0Q6m5TK9i+/iTpKjclXitOdDK4vT07OqbkBT2/VcN/gO9EL1C4HlK3TAOXYv2ItcmbVR9jO1MR0fJg== integrity sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw==
dependencies: dependencies:
"@babel/code-frame" "^7.0.0" "@babel/code-frame" "^7.0.0"
ajv "^6.10.0" ajv "^6.10.0"
@ -3409,7 +3414,7 @@ eslint@~6.2.1:
eslint-scope "^5.0.0" eslint-scope "^5.0.0"
eslint-utils "^1.4.2" eslint-utils "^1.4.2"
eslint-visitor-keys "^1.1.0" eslint-visitor-keys "^1.1.0"
espree "^6.1.0" espree "^6.1.1"
esquery "^1.0.1" esquery "^1.0.1"
esutils "^2.0.2" esutils "^2.0.2"
file-entry-cache "^5.0.1" file-entry-cache "^5.0.1"
@ -3438,13 +3443,13 @@ eslint@~6.2.1:
text-table "^0.2.0" text-table "^0.2.0"
v8-compile-cache "^2.0.3" v8-compile-cache "^2.0.3"
espree@^6.1.0: espree@^6.1.1:
version "6.1.0" version "6.1.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.0.tgz#a1e8aa65bf29a331d70351ed814a80e7534e0884" resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de"
integrity sha512-boA7CHRLlVWUSg3iL5Kmlt/xT3Q+sXnKoRYYzj1YeM10A76TEJBbotV5pKbnK42hEUIr121zTv+QLRM5LsCPXQ== integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==
dependencies: dependencies:
acorn "^7.0.0" acorn "^7.0.0"
acorn-jsx "^5.0.0" acorn-jsx "^5.0.2"
eslint-visitor-keys "^1.1.0" eslint-visitor-keys "^1.1.0"
esprima@^3.1.3: esprima@^3.1.3:
@ -4072,32 +4077,14 @@ graphql-custom-directives@~0.2.14:
moment "^2.22.2" moment "^2.22.2"
numeral "^2.0.6" numeral "^2.0.6"
graphql-extensions@0.10.0: graphql-extensions@0.10.1:
version "0.10.0" version "0.10.1"
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.10.0.tgz#ceafc42e16554930b0dc90f64d5727ee2a9e9cf9" resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.10.1.tgz#9e1abd502f3f802a7ab60c3a28d2fe705e53d4cb"
integrity sha512-qz9Ev0NgsRxdTYqYSCpYwBWS9r1imm+vCBt3PmHzqZlE7SEpUPGddn9oKcLRB/P8uXT6dsr60hDmDHukIxiVOw== integrity sha512-RIlC/jgBKZ/qyrb+cAu7oJVYLC0dJh6al35tNy8dnqE9JImNucy/gFWVOPW7q3fAaXqCHzbBEtdb+ws1L43LgQ==
dependencies: dependencies:
"@apollographql/apollo-tools" "^0.4.0" "@apollographql/apollo-tools" "^0.4.0"
apollo-server-env "2.4.1" apollo-server-env "2.4.2"
apollo-server-types "0.2.1" apollo-server-types "0.2.2"
graphql-extensions@0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.8.1.tgz#f5f1fed5fe49620c4e70c5d08bdbd0039e91c402"
integrity sha512-d/L4x7/PPWhviJqi7jIWOVJPzfzagYgPizSQUpa+3hozbWhwpWEnfxwgL5/If5MnPUikBnqlkOLCyjHMNdipYA==
dependencies:
"@apollographql/apollo-tools" "^0.4.0"
apollo-server-env "2.4.1"
apollo-server-types "0.2.1"
graphql-extensions@0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.9.1.tgz#5d40b2c2cf57a35b686121d5e63783369dade5ef"
integrity sha512-JR/KStdwALd48B/xSG/Mi85zamuJd8THvVlzGM5juznPDN0wTYG5SARGzzvoqHxgxuUHYdzpvESwMAisORJdCQ==
dependencies:
"@apollographql/apollo-tools" "^0.4.0"
apollo-server-env "2.4.1"
apollo-server-types "0.2.1"
graphql-import@0.7.1: graphql-import@0.7.1:
version "0.7.1" version "0.7.1"
@ -4312,20 +4299,20 @@ helmet-crossdomain@0.4.0:
resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e" resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e"
integrity sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA== integrity sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA==
helmet-csp@2.8.0: helmet-csp@2.9.0:
version "2.8.0" version "2.9.0"
resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.8.0.tgz#746d329e24ef39c4ebc00278a48abd3c209e0378" resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.9.0.tgz#8524886b08c7f7d611cb5f36eae453dd604efd4c"
integrity sha512-MlCPeM0Sm3pS9RACRihx70VeTHmkQwa7sum9EK1tfw1VZyvFU0dBWym9nHh3CRkTRNlyNm/WFCMvuh9zXkOjNw== integrity sha512-DGGOQtOLM7ZQpjbf/uvUonq1yG/rFgsBuK10ZJt2AtxUJxqfkPvfmP9aLUmgH9IactiRiYoiFY72YYSPl1TLTQ==
dependencies: dependencies:
bowser "2.5.3"
camelize "1.0.0" camelize "1.0.0"
content-security-policy-builder "2.1.0" content-security-policy-builder "2.1.0"
dasherize "2.0.0" dasherize "2.0.0"
platform "1.3.5"
helmet@~3.20.0: helmet@~3.20.1:
version "3.20.0" version "3.20.1"
resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.20.0.tgz#8a9383bf8230a461cafe8bc763423fbde110d2fc" resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.20.1.tgz#802fcb39ac6865208cbc6879d3502e582c6f777e"
integrity sha512-Ob+TqmQFZ5f7WgP8kBbAzNPsbf6p1lOj5r+327/ymw/IILWih3wcx9u/u/S8Mwv5wbBkO7Li6x5s23t3COhUKw== integrity sha512-em+X5Wz/f0yqoRsBnpnVy3wJHSiIeskX3FQn30szBh1tILaOeSRRLkShuUVFlk/o4qTYjWxdHg4FrRe45iBWHg==
dependencies: dependencies:
depd "2.0.0" depd "2.0.0"
dns-prefetch-control "0.2.0" dns-prefetch-control "0.2.0"
@ -4334,7 +4321,7 @@ helmet@~3.20.0:
feature-policy "0.3.0" feature-policy "0.3.0"
frameguard "3.1.0" frameguard "3.1.0"
helmet-crossdomain "0.4.0" helmet-crossdomain "0.4.0"
helmet-csp "2.8.0" helmet-csp "2.9.0"
hide-powered-by "1.1.0" hide-powered-by "1.1.0"
hpkp "2.0.0" hpkp "2.0.0"
hsts "2.2.0" hsts "2.2.0"
@ -6197,10 +6184,10 @@ neo4j-driver@^1.7.3, neo4j-driver@^1.7.5, neo4j-driver@~1.7.5:
text-encoding-utf-8 "^1.0.2" text-encoding-utf-8 "^1.0.2"
uri-js "^4.2.2" uri-js "^4.2.2"
neo4j-graphql-js@^2.7.1: neo4j-graphql-js@^2.7.2:
version "2.7.1" version "2.7.2"
resolved "https://registry.yarnpkg.com/neo4j-graphql-js/-/neo4j-graphql-js-2.7.1.tgz#2d5bd151685b64644b0cf0645434cc396a923b5d" resolved "https://registry.yarnpkg.com/neo4j-graphql-js/-/neo4j-graphql-js-2.7.2.tgz#6a56c63874bc41e678cb83580c6c7647e6f61ccf"
integrity sha512-WrtcS0q//Rh56OMGJUUKZAucODJcTjDoSoShWCViu2Ft2tSD8V6ag06yHwmvQ2pO33elsAEQ0osTvWL1+s3Xiw== integrity sha512-nrhSmNAkiYgksNabNuHyMHYYaLloYZaVXRiYGrRVUcf84TLiwJdg5k9hIQVH9O6QQOvnK3lwBDlE7T0phpAIpg==
dependencies: dependencies:
"@babel/runtime" "^7.5.5" "@babel/runtime" "^7.5.5"
"@babel/runtime-corejs2" "^7.5.5" "@babel/runtime-corejs2" "^7.5.5"
@ -6886,11 +6873,6 @@ pkginfo@~0.4.0:
resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff"
integrity sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8= integrity sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=
platform@1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444"
integrity sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==
pn@^1.1.0: pn@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"

View File

@ -1,6 +1,16 @@
# End-to-End Testing # End-to-End Testing
## Configure cypress ## Setup with docker
Are you running everything through docker? You're so lucky you don't have to
setup anything!
Just:
```
docker-compose up
```
## Setup without docker
First, you have to tell cypress how to connect to your local neo4j database First, you have to tell cypress how to connect to your local neo4j database
among other things. You can copy our template configuration and change the new among other things. You can copy our template configuration and change the new
@ -11,16 +21,15 @@ Make sure you are at the root level of the project. Then:
# in the top level folder Human-Connection/ # in the top level folder Human-Connection/
$ cp cypress.env.template.json cypress.env.json $ cp cypress.env.template.json cypress.env.json
``` ```
To start the services that are required for cypress testing, run this:
## Run Tests
To run the tests, do this:
```bash ```bash
# in the top level folder Human-Connection/ # in the top level folder Human-Connection/
$ yarn cypress:setup $ yarn cypress:setup
``` ```
## Run cypress
After verifying that there are no errors with the servers starting, open another tab in your terminal and run the following command: After verifying that there are no errors with the servers starting, open another tab in your terminal and run the following command:
```bash ```bash
@ -29,13 +38,12 @@ $ yarn cypress:run
![Console output after running cypress test](../.gitbook/assets/grafik%20%281%29.png) ![Console output after running cypress test](../.gitbook/assets/grafik%20%281%29.png)
After the test runs, you will also get some video footage of the test run which you can then analyse in more detail.
## Open Interactive Test Console ### Open Interactive Test Console
If you are like me, you might want to see some visual output. The interactive cypress environment also helps at debugging your tests, you can even time travel between individual steps and see the exact state of the app. If you are like me, you might want to see some visual output. The interactive cypress environment also helps at debugging your tests, you can even time travel between individual steps and see the exact state of the app.
To use this feature, you will still run the `yarn cypress:setup` above, but instead of `yarn cypress:run` open another tab in your terminal and run the following command: To use this feature, instead of `yarn cypress:run` you would run the following command:
```bash ```bash
$ yarn cypress:open $ yarn cypress:open

View File

@ -7,20 +7,21 @@ metadata:
kubernetes.io/ingress.class: "nginx" kubernetes.io/ingress.class: "nginx"
certmanager.k8s.io/issuer: "letsencrypt-staging" certmanager.k8s.io/issuer: "letsencrypt-staging"
certmanager.k8s.io/acme-challenge-type: http01 certmanager.k8s.io/acme-challenge-type: http01
nginx.ingress.kubernetes.io/proxy-body-size: 6m
spec: spec:
tls: tls:
- hosts: - hosts:
# - nitro-mailserver.human-connection.org # - nitro-mailserver.human-connection.org
- nitro-staging.human-connection.org - nitro-staging.human-connection.org
secretName: tls secretName: tls
rules: rules:
- host: nitro-staging.human-connection.org - host: nitro-staging.human-connection.org
http: http:
paths: paths:
- path: / - path: /
backend: backend:
serviceName: nitro-web serviceName: nitro-web
servicePort: 3000 servicePort: 3000
# - host: nitro-mailserver.human-connection.org # - host: nitro-mailserver.human-connection.org
# http: # http:
# paths: # paths:

View File

@ -12,6 +12,6 @@
# On Windows this resolves to C:\Users\dornhoeschen\AppData\Local\Temp\mongo-export (MinGW) # On Windows this resolves to C:\Users\dornhoeschen\AppData\Local\Temp\mongo-export (MinGW)
EXPORT_PATH='/tmp/mongo-export/' EXPORT_PATH='/tmp/mongo-export/'
EXPORT_MONGOEXPORT_BIN='mongoexport' EXPORT_MONGOEXPORT_BIN='mongoexport'
MONGO_EXPORT_SPLIT_SIZE=100 MONGO_EXPORT_SPLIT_SIZE=4000
# On Windows use something like this # On Windows use something like this
# EXPORT_MONGOEXPORT_BIN='C:\Program Files\MongoDB\Server\3.6\bin\mongoexport.exe' # EXPORT_MONGOEXPORT_BIN='C:\Program Files\MongoDB\Server\3.6\bin\mongoexport.exe'

View File

@ -16,6 +16,30 @@ services:
- webapp_node_modules:/nitro-web/node_modules - webapp_node_modules:/nitro-web/node_modules
command: yarn run dev command: yarn run dev
user: root user: root
factories:
image: humanconnection/nitro-backend:builder
build:
context: backend
target: builder
ports:
- 4001:4001
networks:
- hc-network
volumes:
- ./backend:/nitro-backend
- factories_node_modules:/nitro-backend/node_modules
- uploads:/nitro-backend/public/uploads
depends_on:
- neo4j
environment:
- NEO4J_URI=bolt://neo4j:7687
- GRAPHQL_PORT=4000
- GRAPHQL_URI=http://localhost:4000
- CLIENT_URI=http://localhost:3000
- JWT_SECRET=b/&&7b78BF&fv/Vd
- MAPBOX_TOKEN=pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.KZ8KK9l70omjXbEkkbHGsQ
- PRIVATE_KEY_PASSPHRASE=a7dsf78sadg87ad87sfagsadg78
command: yarn run test:before:seeder
backend: backend:
image: humanconnection/nitro-backend:builder image: humanconnection/nitro-backend:builder
build: build:
@ -42,5 +66,6 @@ services:
volumes: volumes:
webapp_node_modules: webapp_node_modules:
backend_node_modules: backend_node_modules:
factories_node_modules:
neo4j-data: neo4j-data:
uploads: uploads:

View File

@ -23,7 +23,7 @@
"codecov": "^3.5.0", "codecov": "^3.5.0",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"cypress": "^3.4.1", "cypress": "^3.4.1",
"cypress-cucumber-preprocessor": "^1.15.0", "cypress-cucumber-preprocessor": "^1.15.1",
"cypress-file-upload": "^3.3.3", "cypress-file-upload": "^3.3.3",
"cypress-plugin-retries": "^1.2.2", "cypress-plugin-retries": "^1.2.2",
"dotenv": "^8.1.0", "dotenv": "^8.1.0",

View File

@ -62,12 +62,13 @@
</template> </template>
<script> <script>
import gql from 'graphql-tag'
import { mapGetters, mapMutations } from 'vuex' import { mapGetters, mapMutations } from 'vuex'
import HcUser from '~/components/User' import HcUser from '~/components/User'
import ContentMenu from '~/components/ContentMenu' import ContentMenu from '~/components/ContentMenu'
import ContentViewer from '~/components/Editor/ContentViewer' import ContentViewer from '~/components/Editor/ContentViewer'
import HcEditCommentForm from '~/components/EditCommentForm/EditCommentForm' import HcEditCommentForm from '~/components/EditCommentForm/EditCommentForm'
import CommentMutations from '~/graphql/CommentMutations'
import PostQuery from '~/graphql/PostQuery'
export default { export default {
data: function() { data: function() {
@ -142,16 +143,23 @@ export default {
}, },
async deleteCommentCallback() { async deleteCommentCallback() {
try { try {
var gqlMutation = gql`
mutation($id: ID!) {
DeleteComment(id: $id) {
id
}
}
`
await this.$apollo.mutate({ await this.$apollo.mutate({
mutation: gqlMutation, mutation: CommentMutations(this.$i18n).DeleteComment,
variables: { id: this.comment.id }, variables: { id: this.comment.id },
update: async store => {
const data = await store.readQuery({
query: PostQuery(this.$i18n),
variables: { id: this.post.id },
})
const index = data.Post[0].comments.findIndex(
deletedComment => deletedComment.id === this.comment.id,
)
if (index !== -1) {
data.Post[0].comments.splice(index, 1)
}
await store.writeQuery({ query: PostQuery(this.$i18n), data })
},
}) })
this.$toast.success(this.$t(`delete.comment.success`)) this.$toast.success(this.$t(`delete.comment.success`))
this.$emit('deleteComment') this.$emit('deleteComment')

View File

@ -80,13 +80,13 @@ export default {
postId: this.post.id, postId: this.post.id,
content: this.form.content, content: this.form.content,
}, },
update: (store, { data: { CreateComment } }) => { update: async (store, { data: { CreateComment } }) => {
const data = store.readQuery({ const data = await store.readQuery({
query: PostQuery(this.$i18n), query: PostQuery(this.$i18n),
variables: { id: this.post.id }, variables: { id: this.post.id },
}) })
data.Post[0].comments.push(CreateComment) data.Post[0].comments.push(CreateComment)
store.writeQuery({ query: PostQuery(this.$i18n), data }) await store.writeQuery({ query: PostQuery(this.$i18n), data })
}, },
}) })
.then(res => { .then(res => {

View File

@ -23,7 +23,7 @@
/> />
<small class="smallTag">{{ form.contentLength }}/{{ contentMax }}</small> <small class="smallTag">{{ form.contentLength }}/{{ contentMax }}</small>
</client-only> </client-only>
<ds-space margin-bottom="xxx-large" /> <ds-space margin-bottom="small" />
<hc-categories-select <hc-categories-select
model="categoryIds" model="categoryIds"
@updateCategories="updateCategories" @updateCategories="updateCategories"

View File

@ -0,0 +1,95 @@
<script>
import tippy from 'tippy.js'
export default {
props: {
content: Object,
node: Object,
},
methods: {
displayContextMenu(target, content, type) {
const placement = type === 'link' ? 'right' : 'top-start'
const trigger = type === 'link' ? 'click' : 'mouseenter'
const showOnInit = type !== 'link'
if (this.menu) {
return
}
this.menu = tippy(target, {
arrow: true,
arrowType: 'round',
content: content,
duration: [400, 200],
inertia: true,
interactive: true,
placement,
showOnInit,
theme: 'human-connection',
trigger,
onMount(instance) {
const input = instance.popper.querySelector('input')
if (input) {
input.focus({ preventScroll: true })
}
},
})
// we have to update tippy whenever the DOM is updated
if (MutationObserver) {
this.observer = new MutationObserver(() => {
this.menu.popperInstance.scheduleUpdate()
})
this.observer.observe(content, {
childList: true,
subtree: true,
characterData: true,
})
}
},
hideContextMenu() {
if (this.menu) {
this.menu.destroy()
this.menu = null
}
if (this.observer) {
this.observer.disconnect()
}
},
},
render() {
return null
},
}
</script>
<style lang="scss">
.tippy-tooltip.human-connection-theme {
background-color: $color-primary;
padding: 0;
font-size: 1rem;
text-align: inherit;
color: $color-neutral-100;
.tippy-backdrop {
display: none;
}
.tippy-roundarrow {
fill: $color-primary;
}
.tippy-popper[x-placement^='top'] & .tippy-arrow {
border-top-color: $color-primary;
}
.tippy-popper[x-placement^='bottom'] & .tippy-arrow {
border-bottom-color: $color-primary;
}
.tippy-popper[x-placement^='left'] & .tippy-arrow {
border-left-color: $color-primary;
}
.tippy-popper[x-placement^='right'] & .tippy-arrow {
border-right-color: $color-primary;
}
}
</style>

View File

@ -1,203 +1,52 @@
<template> <template>
<div class="editor"> <div class="editor">
<!-- Mention and Hashtag Suggestions Menu --> <menu-bar :editor="editor" :toggleLinkInput="toggleLinkInput" />
<div v-show="showSuggestions" ref="suggestions" class="suggestion-list"> <editor-content ref="editor" :editor="editor" class="ds-input editor-content" />
<!-- "filteredItems" array is not empty --> <context-menu ref="contextMenu" />
<template v-if="hasResults"> <suggestion-list
<div ref="suggestions"
v-for="(item, index) in filteredItems" :suggestion-type="suggestionType"
:key="item.id" :filtered-items="filteredItems"
class="suggestion-list__item" :navigated-item-index="navigatedItemIndex"
:class="{ 'is-selected': navigatedItemIndex === index }" :query="query"
@click="selectItem(item)" :select-item="selectItem"
> />
<div v-if="isMention">@{{ item.slug }}</div> <link-input
<div v-if="isHashtag">#{{ item.id }}</div> v-show="isLinkInputActive"
</div> ref="linkInput"
<div v-if="isHashtag"> :toggle-link-input="toggleLinkInput"
<!-- if query is not empty and is find fully in the suggestions array ... --> :set-link-url="setLinkUrl"
<div v-if="query && !filteredItems.find(el => el.id === query)"> />
<div class="suggestion-list__item is-empty">{{ $t('editor.hashtag.addHashtag') }}</div>
<div class="suggestion-list__item" @click="selectItem({ id: query })">#{{ query }}</div>
</div>
<!-- otherwise if sanitized query is empty advice the user to add a char -->
<div v-else-if="!query">
<div class="suggestion-list__item is-empty">{{ $t('editor.hashtag.addLetter') }}</div>
</div>
</div>
</template>
<!-- if "!hasResults" -->
<div v-else>
<div v-if="isMention" class="suggestion-list__item is-empty">
{{ $t('editor.mention.noUsersFound') }}
</div>
<div v-if="isHashtag">
<div v-if="query === ''" class="suggestion-list__item is-empty">
{{ $t('editor.hashtag.noHashtagsFound') }}
</div>
<!-- if "query" is not empty -->
<div v-else>
<div class="suggestion-list__item is-empty">{{ $t('editor.hashtag.addHashtag') }}</div>
<div class="suggestion-list__item" @click="selectItem({ id: query })">#{{ query }}</div>
</div>
</div>
</div>
</div>
<editor-menu-bubble :editor="editor">
<div
ref="menu"
slot-scope="{ commands, getMarkAttrs, isActive, menu }"
class="menububble tooltip"
x-placement="top"
:class="{ 'is-active': menu.isActive || linkMenuIsActive }"
:style="`left: ${menu.left}px; bottom: ${menu.bottom}px;`"
>
<div class="tooltip-wrapper">
<template v-if="linkMenuIsActive">
<ds-input
ref="linkInput"
v-model="linkUrl"
class="editor-menu-link-input"
placeholder="http://"
@blur.native.capture="hideMenu(menu.isActive)"
@keydown.native.esc.prevent="hideMenu(menu.isActive)"
@keydown.native.enter.prevent="setLinkUrl(commands.link, linkUrl)"
/>
</template>
<template v-else>
<ds-button
class="menububble__button"
size="small"
:hover="isActive.bold()"
ghost
@click.prevent="() => {}"
@mousedown.native.prevent="commands.bold"
>
<ds-icon name="bold" />
</ds-button>
<ds-button
class="menububble__button"
size="small"
:hover="isActive.italic()"
ghost
@click.prevent="() => {}"
@mousedown.native.prevent="commands.italic"
>
<ds-icon name="italic" />
</ds-button>
<ds-button
class="menububble__button"
size="small"
:hover="isActive.link()"
ghost
@click.prevent="() => {}"
@mousedown.native.prevent="showLinkMenu(getMarkAttrs('link'))"
>
<ds-icon name="link" />
</ds-button>
</template>
</div>
<div class="tooltip-arrow" />
</div>
</editor-menu-bubble>
<editor-floating-menu :editor="editor">
<div
slot-scope="{ commands, isActive, menu }"
class="editor__floating-menu"
:class="{ 'is-active': menu.isActive }"
:style="`top: ${menu.top}px`"
>
<ds-button
class="menubar__button"
size="small"
:ghost="!isActive.paragraph()"
@click.prevent="commands.paragraph()"
>
<ds-icon name="paragraph" />
</ds-button>
<ds-button
class="menubar__button"
size="small"
:ghost="!isActive.heading({ level: 3 })"
@click.prevent="commands.heading({ level: 3 })"
>
H3
</ds-button>
<ds-button
class="menubar__button"
size="small"
:ghost="!isActive.heading({ level: 4 })"
@click.prevent="commands.heading({ level: 4 })"
>
H4
</ds-button>
<ds-button
class="menubar__button"
size="small"
:ghost="!isActive.bullet_list()"
@click.prevent="commands.bullet_list()"
>
<ds-icon name="list-ul" />
</ds-button>
<ds-button
class="menubar__button"
size="small"
:ghost="!isActive.ordered_list()"
@click.prevent="commands.ordered_list()"
>
<ds-icon name="list-ol" />
</ds-button>
<ds-button
class="menubar__button"
size="small"
:ghost="!isActive.blockquote()"
@click.prevent="commands.blockquote"
>
<ds-icon name="quote-right" />
</ds-button>
<ds-button
class="menubar__button"
size="small"
:ghost="!isActive.horizontal_rule()"
@click.prevent="commands.horizontal_rule"
>
<ds-icon name="minus" />
</ds-button>
</div>
</editor-floating-menu>
<editor-content ref="editor" :editor="editor" />
</div> </div>
</template> </template>
<script> <script>
import defaultExtensions from './defaultExtensions.js' import { mapGetters } from 'vuex'
import { Editor, EditorContent } from 'tiptap'
import { History } from 'tiptap-extensions'
import linkify from 'linkify-it' import linkify from 'linkify-it'
import stringHash from 'string-hash' import stringHash from 'string-hash'
import Fuse from 'fuse.js'
import tippy from 'tippy.js' import * as key from '../../constants/keycodes'
import { Editor, EditorContent, EditorFloatingMenu, EditorMenuBubble } from 'tiptap' import { HASHTAG, MENTION } from '../../constants/editor'
import defaultExtensions from './defaultExtensions.js'
import EventHandler from './plugins/eventHandler.js' import EventHandler from './plugins/eventHandler.js'
import { History } from 'tiptap-extensions'
import Hashtag from './nodes/Hashtag.js' import Hashtag from './nodes/Hashtag.js'
import Mention from './nodes/Mention.js' import Mention from './nodes/Mention.js'
import { mapGetters } from 'vuex' import MenuBar from './MenuBar'
import ContextMenu from './ContextMenu'
import SuggestionList from './SuggestionList'
import LinkInput from './LinkInput'
let throttleInputEvent let throttleInputEvent
export default { export default {
components: { components: {
ContextMenu,
EditorContent, EditorContent,
EditorFloatingMenu, LinkInput,
EditorMenuBubble, MenuBar,
SuggestionList,
}, },
props: { props: {
users: { type: Array, default: () => null }, // If 'null', than the Mention extention is not assigned. users: { type: Array, default: () => null }, // If 'null', than the Mention extention is not assigned.
@ -206,189 +55,11 @@ export default {
doc: { type: Object, default: () => {} }, doc: { type: Object, default: () => {} },
}, },
data() { data() {
// Set array of optional extensions by analysing the props.
let optionalExtensions = []
// Don't change the following line. The functionallity is in danger!
if (this.users) {
optionalExtensions.push(
new Mention({
// a list of all suggested items
items: () => {
return this.users
},
// is called when a suggestion starts
onEnter: ({ items, query, range, command, virtualNode }) => {
this.suggestionType = this.mentionSuggestionType
this.query = query
this.filteredItems = items
this.suggestionRange = range
this.renderPopup(virtualNode)
// we save the command for inserting a selected mention
// this allows us to call it inside of our custom popup
// via keyboard navigation and on click
this.insertMentionOrHashtag = command
},
// is called when a suggestion has changed
onChange: ({ items, query, range, virtualNode }) => {
this.query = query
this.filteredItems = items
this.suggestionRange = range
this.navigatedItemIndex = 0
this.renderPopup(virtualNode)
},
// is called when a suggestion is cancelled
onExit: () => {
this.suggestionType = this.nullSuggestionType
// reset all saved values
this.query = null
this.filteredItems = []
this.suggestionRange = null
this.navigatedItemIndex = 0
this.destroyPopup()
},
// is called on every keyDown event while a suggestion is active
onKeyDown: ({ event }) => {
// pressing up arrow
if (event.keyCode === 38) {
this.upHandler()
return true
}
// pressing down arrow
if (event.keyCode === 40) {
this.downHandler()
return true
}
// pressing enter
if (event.keyCode === 13) {
this.enterHandler()
return true
}
return false
},
// is called when a suggestion has changed
// this function is optional because there is basic filtering built-in
// you can overwrite it if you prefer your own filtering
// in this example we use fuse.js with support for fuzzy search
onFilter: (items, query) => {
if (!query) {
return items
}
const fuse = new Fuse(items, {
threshold: 0.2,
keys: ['slug'],
})
return fuse.search(query)
},
}),
)
}
// Don't change the following line. The functionallity is in danger!
if (this.hashtags) {
optionalExtensions.push(
new Hashtag({
// a list of all suggested items
items: () => {
return this.hashtags
},
// is called when a suggestion starts
onEnter: ({ items, query, range, command, virtualNode }) => {
this.suggestionType = this.hashtagSuggestionType
this.query = this.sanitizedQuery(query)
this.filteredItems = items
this.suggestionRange = range
this.renderPopup(virtualNode)
// we save the command for inserting a selected mention
// this allows us to call it inside of our custom popup
// via keyboard navigation and on click
this.insertMentionOrHashtag = command
},
// is called when a suggestion has changed
onChange: ({ items, query, range, virtualNode }) => {
this.query = this.sanitizedQuery(query)
this.filteredItems = items
this.suggestionRange = range
this.navigatedItemIndex = 0
this.renderPopup(virtualNode)
},
// is called when a suggestion is cancelled
onExit: () => {
this.suggestionType = this.nullSuggestionType
// reset all saved values
this.query = null
this.filteredItems = []
this.suggestionRange = null
this.navigatedItemIndex = 0
this.destroyPopup()
},
// is called on every keyDown event while a suggestion is active
onKeyDown: ({ event }) => {
// pressing up arrow
if (event.keyCode === 38) {
this.upHandler()
return true
}
// pressing down arrow
if (event.keyCode === 40) {
this.downHandler()
return true
}
// pressing enter
if (event.keyCode === 13) {
this.enterHandler()
return true
}
// pressing space
if (event.keyCode === 32) {
this.spaceHandler()
return true
}
return false
},
// is called when a suggestion has changed
// this function is optional because there is basic filtering built-in
// you can overwrite it if you prefer your own filtering
// in this example we use fuse.js with support for fuzzy search
onFilter: (items, query) => {
query = this.sanitizedQuery(query)
if (!query) {
return items
}
return items.filter(item =>
JSON.stringify(item)
.toLowerCase()
.includes(query.toLowerCase()),
)
},
}),
)
}
return { return {
lastValueHash: null, lastValueHash: null,
editor: new Editor({ editor: null,
content: this.value || '', isLinkInputActive: false,
doc: this.doc, suggestionType: '',
extensions: [
...defaultExtensions(this),
new EventHandler(),
new History(),
...optionalExtensions,
],
onUpdate: e => {
clearTimeout(throttleInputEvent)
throttleInputEvent = setTimeout(() => this.onUpdate(e), 300)
},
}),
linkUrl: null,
linkMenuIsActive: false,
nullSuggestionType: '',
mentionSuggestionType: 'mention',
hashtagSuggestionType: 'hashtag',
suggestionType: this.nullSuggestionType,
query: null, query: null,
suggestionRange: null, suggestionRange: null,
filteredItems: [], filteredItems: [],
@ -399,17 +70,39 @@ export default {
}, },
computed: { computed: {
...mapGetters({ placeholder: 'editor/placeholder' }), ...mapGetters({ placeholder: 'editor/placeholder' }),
hasResults() { optionalExtensions() {
return this.filteredItems.length const extensions = []
}, // Don't change the following line. The functionallity is in danger!
showSuggestions() { if (this.users) {
return this.query || this.hasResults extensions.push(
}, new Mention({
isMention() { items: () => {
return this.suggestionType === this.mentionSuggestionType return this.users
}, },
isHashtag() { onEnter: props => this.openSuggestionList(props, MENTION),
return this.suggestionType === this.hashtagSuggestionType onChange: this.updateSuggestionList,
onExit: this.closeSuggestionList,
onKeyDown: this.navigateSuggestionList,
onFilter: this.filterSuggestionList,
}),
)
}
// Don't change the following line. The functionallity is in danger!
if (this.hashtags) {
extensions.push(
new Hashtag({
items: () => {
return this.hashtags
},
onEnter: props => this.openSuggestionList(props, HASHTAG),
onChange: this.updateSuggestionList,
onExit: this.closeSuggestionList,
onKeyDown: this.navigateSuggestionList,
onFilter: this.filterSuggestionList,
}),
)
}
return extensions
}, },
}, },
watch: { watch: {
@ -421,52 +114,110 @@ export default {
return return
} }
this.lastValueHash = contentHash this.lastValueHash = contentHash
this.editor.setContent(content) this.$nextTick(() => this.editor.setContent(content))
}, },
}, },
placeholder: { placeholder: {
immediate: true, immediate: true,
handler: function(val) { handler: function(val) {
if (!val) { if (!val || !this.editor) {
return return
} }
this.editor.extensions.options.placeholder.emptyNodeText = val this.editor.extensions.options.placeholder.emptyNodeText = val
}, },
}, },
}, },
created() {
this.editor = new Editor({
content: this.value || '',
doc: this.doc,
extensions: [
...defaultExtensions(this),
new EventHandler(),
new History(),
...this.optionalExtensions,
],
onUpdate: e => {
clearTimeout(throttleInputEvent)
throttleInputEvent = setTimeout(() => this.onUpdate(e), 300)
},
})
},
beforeDestroy() { beforeDestroy() {
this.editor.destroy() this.editor.destroy()
}, },
methods: { methods: {
sanitizedQuery(query) { openSuggestionList({ items, query, range, command, virtualNode }, suggestionType) {
// remove all not allowed chars this.suggestionType = suggestionType
query = query.replace(/[^a-zA-Z0-9]/gm, '')
// if the query is only made of digits, make it empty this.query = this.sanitizeQuery(query)
return query.replace(/[0-9]/gm, '') === '' ? '' : query this.filteredItems = items
this.suggestionRange = range
this.$refs.contextMenu.displayContextMenu(virtualNode, this.$refs.suggestions.$el)
this.insertMentionOrHashtag = command
}, },
// navigate to the previous item updateSuggestionList({ items, query, range, virtualNode }) {
// if it's the first item, navigate to the last one this.query = this.sanitizeQuery(query)
upHandler() { this.filteredItems = items
this.navigatedItemIndex = this.suggestionRange = range
(this.navigatedItemIndex + this.filteredItems.length - 1) % this.filteredItems.length this.navigatedItemIndex = 0
this.$refs.contextMenu.displayContextMenu(virtualNode, this.$refs.suggestions.$el)
}, },
// navigate to the next item closeSuggestionList() {
// if it's the last item, navigate to the first one this.suggestionType = ''
downHandler() { this.query = null
this.navigatedItemIndex = (this.navigatedItemIndex + 1) % this.filteredItems.length this.filteredItems = []
this.suggestionRange = null
this.navigatedItemIndex = 0
this.$refs.contextMenu.hideContextMenu()
}, },
// Handles pressing of enter. navigateSuggestionList({ event }) {
enterHandler() {
const item = this.filteredItems[this.navigatedItemIndex] const item = this.filteredItems[this.navigatedItemIndex]
if (item) {
this.selectItem(item) switch (event.keyCode) {
case key.ARROW_UP:
this.navigatedItemIndex =
(this.navigatedItemIndex + this.filteredItems.length - 1) % this.filteredItems.length
return true
case key.ARROW_DOWN:
this.navigatedItemIndex = (this.navigatedItemIndex + 1) % this.filteredItems.length
return true
case key.RETURN:
if (item) {
this.selectItem(item)
}
return true
case key.SPACE:
if (this.suggestionType === HASHTAG && this.query !== '') {
this.selectItem({ id: this.query })
}
return true
default:
return false
} }
}, },
// For hashtags handles pressing of space. filterSuggestionList(items, query) {
spaceHandler() { query = this.sanitizeQuery(query)
if (this.suggestionType === this.hashtagSuggestionType && this.query !== '') { if (!query) {
this.selectItem({ id: this.query }) return items
} }
return items.filter(item => {
const itemString = item.slug || item.id
return itemString.toLowerCase().includes(query.toLowerCase())
})
},
sanitizeQuery(query) {
if (this.suggestionType === HASHTAG) {
// remove all not allowed chars
query = query.replace(/[^a-zA-Z0-9]/gm, '')
// if the query is only made of digits, make it empty
return query.replace(/[0-9]/gm, '') === '' ? '' : query
}
return query
}, },
// we have to replace our suggestion text with a mention // we have to replace our suggestion text with a mention
// so it's important to pass also the position of your suggestion text // so it's important to pass also the position of your suggestion text
@ -487,45 +238,6 @@ export default {
}) })
this.editor.focus() this.editor.focus()
}, },
// renders a popup with suggestions
// tiptap provides a virtualNode object for using popper.js (or tippy.js) for popups
renderPopup(node) {
if (this.popup) {
return
}
this.popup = tippy(node, {
content: this.$refs.suggestions,
trigger: 'mouseenter',
interactive: true,
theme: 'dark',
placement: 'top-start',
inertia: true,
duration: [400, 200],
showOnInit: true,
arrow: true,
arrowType: 'round',
})
// we have to update tippy whenever the DOM is updated
if (MutationObserver) {
this.observer = new MutationObserver(() => {
this.popup.popperInstance.scheduleUpdate()
})
this.observer.observe(this.$refs.suggestions, {
childList: true,
subtree: true,
characterData: true,
})
}
},
destroyPopup() {
if (this.popup) {
this.popup.destroy()
this.popup = null
}
if (this.observer) {
this.observer.disconnect()
}
},
onUpdate(e) { onUpdate(e) {
const content = e.getHTML() const content = e.getHTML()
const contentHash = stringHash(content) const contentHash = stringHash(content)
@ -534,36 +246,28 @@ export default {
this.$emit('input', content) this.$emit('input', content)
} }
}, },
showLinkMenu(attrs) { toggleLinkInput(attrs, element) {
this.linkUrl = attrs.href if (!this.isLinkInputActive && attrs && element) {
this.linkMenuIsActive = true this.$refs.linkInput.linkUrl = attrs.href
this.$nextTick(() => { this.isLinkInputActive = true
try { this.$refs.contextMenu.displayContextMenu(element, this.$refs.linkInput.$el, 'link')
const $el = this.$refs.linkInput.$el.getElementsByTagName('input')[0] } else {
$el.focus() this.$refs.contextMenu.hideContextMenu()
$el.select() this.isLinkInputActive = false
} catch (err) {} this.editor.focus()
}) }
}, },
hideLinkMenu() { setLinkUrl(url) {
this.linkUrl = null const normalizedLinks = url ? linkify().match(url) : null
this.linkMenuIsActive = false const command = this.editor.commands.link
this.editor.focus() if (normalizedLinks) {
},
hideMenu(isActive) {
isActive = false
this.hideLinkMenu()
},
setLinkUrl(command, url) {
const links = linkify().match(url)
if (links) {
// add valid link // add valid link
command({ command({
href: links.pop().url, href: normalizedLinks.pop().url,
}) })
this.hideLinkMenu() this.toggleLinkInput()
this.editor.focus() this.editor.focus()
} else if (!url) { } else {
// remove link // remove link
command({ href: null }) command({ href: null })
} }
@ -576,70 +280,6 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
.suggestion-list {
padding: 0.2rem;
border: 2px solid rgba($color-neutral-0, 0.1);
font-size: 0.8rem;
font-weight: bold;
&__no-results {
padding: 0.2rem 0.5rem;
}
&__item {
border-radius: 5px;
padding: 0.2rem 0.5rem;
margin-bottom: 0.2rem;
cursor: pointer;
&:last-child {
margin-bottom: 0;
}
&.is-selected,
&:hover {
background-color: rgba($color-neutral-100, 0.2);
}
&.is-empty {
opacity: 0.5;
}
}
}
.tippy-tooltip.dark-theme {
background-color: $color-neutral-0;
padding: 0;
font-size: 1rem;
text-align: inherit;
color: $color-neutral-100;
border-radius: 5px;
.tippy-backdrop {
display: none;
}
.tippy-roundarrow {
fill: $color-neutral-0;
}
.tippy-popper[x-placement^='top'] & .tippy-arrow {
border-top-color: $color-neutral-0;
}
.tippy-popper[x-placement^='bottom'] & .tippy-arrow {
border-bottom-color: $color-neutral-0;
}
.tippy-popper[x-placement^='left'] & .tippy-arrow {
border-left-color: $color-neutral-0;
}
.tippy-popper[x-placement^='right'] & .tippy-arrow {
border-right-color: $color-neutral-0;
}
}
.ProseMirror {
padding: $space-base;
margin: -$space-base;
min-height: $space-large;
}
.ProseMirror:focus {
outline: none;
}
.editor p.is-empty:first-child::before { .editor p.is-empty:first-child::before {
content: attr(data-empty-text); content: attr(data-empty-text);
float: left; float: left;
@ -659,74 +299,40 @@ li > p {
} }
.editor { .editor {
.mention-suggestion { display: flex;
color: $color-primary; flex-direction: column;
}
.hashtag { .hashtag {
color: $color-primary; color: $color-primary;
} }
.hashtag-suggestion { .hashtag-suggestion {
color: $color-primary; color: $color-primary;
} }
&__floating-menu { .mention-suggestion {
position: absolute; color: $color-primary;
margin-top: -0.25rem;
margin-left: $space-xx-small;
visibility: hidden;
opacity: 0;
transition: opacity 0.2s, visibility 0.2s;
background-color: #fff;
&.is-active {
opacity: 1;
visibility: visible;
}
} }
.menububble { }
position: absolute;
// margin-top: -0.5rem;
visibility: hidden;
opacity: 0;
transition: opacity 200ms, visibility 200ms;
// transition-delay: 50ms;
transform: translate(-50%, -10%);
background-color: $background-color-inverse-soft; .editor-content {
// color: $text-color-inverse; flex-grow: 1;
border-radius: $border-radius-base; margin-top: $space-small;
padding: $space-xx-small; height: auto;
box-shadow: $box-shadow-large;
.ds-button { &:focus-within {
color: $text-color-inverse; border-color: $color-primary;
background-color: $color-neutral-100;
}
}
&.ds-button-hover, .ProseMirror {
&:hover { min-height: 100px;
color: $text-color-base;
}
}
&.is-active { &:focus {
opacity: 1; outline: none;
visibility: visible; }
}
.tooltip-arrow { p {
left: calc(50% - 10px); margin: 0 0 $space-x-small;
}
input,
button {
border: none;
border-radius: 2px;
}
.ds-input {
height: auto;
}
input {
padding: $space-xx-small $space-x-small;
}
} }
} }
</style> </style>

View File

@ -0,0 +1,33 @@
<template>
<div>
<ds-input
id="linkInputId"
v-model="linkUrl"
class="editor-menu-link-input"
placeholder="https://"
@blur.native.capture="toggleLinkInput()"
@keydown.native.esc.prevent="toggleLinkInput()"
@keydown.native.enter.prevent="enterLink()"
/>
</div>
</template>
<script>
export default {
props: {
toggleLinkInput: Function,
setLinkUrl: Function,
},
data() {
return {
linkUrl: null,
}
},
methods: {
enterLink() {
this.setLinkUrl(this.linkUrl)
this.linkUrl = null
},
},
}
</script>

View File

@ -0,0 +1,74 @@
<template>
<editor-menu-bar :editor="editor" v-slot="{ commands, isActive, getMarkAttrs }">
<div>
<menu-bar-button :isActive="isActive.bold()" :onClick="commands.bold" icon="bold" />
<menu-bar-button :isActive="isActive.italic()" :onClick="commands.italic" icon="italic" />
<menu-bar-button
ref="linkButton"
:isActive="isActive.link()"
:onClick="event => toggleLinkInput(getMarkAttrs('link'), event.currentTarget)"
icon="link"
/>
<menu-bar-button
:isActive="isActive.paragraph()"
:onClick="commands.paragraph"
icon="paragraph"
/>
<menu-bar-button
:isActive="isActive.heading({ level: 3 })"
:onClick="() => commands.heading({ level: 3 })"
label="H3"
/>
<menu-bar-button
:isActive="isActive.heading({ level: 4 })"
:onClick="() => commands.heading({ level: 4 })"
label="H4"
/>
<menu-bar-button
:isActive="isActive.bullet_list()"
:onClick="commands.bullet_list"
icon="list-ul"
/>
<menu-bar-button
:isActive="isActive.ordered_list()"
:onClick="commands.ordered_list"
icon="list-ol"
/>
<menu-bar-button
:isActive="isActive.blockquote()"
:onClick="commands.blockquote"
icon="quote-right"
/>
<menu-bar-button
:isActive="isActive.horizontal_rule()"
:onClick="commands.horizontal_rule"
icon="minus"
/>
</div>
</editor-menu-bar>
</template>
<script>
import { EditorMenuBar } from 'tiptap'
import MenuBarButton from './MenuBarButton'
export default {
components: {
EditorMenuBar,
MenuBarButton,
},
props: {
editor: Object,
toggleLinkInput: Function,
},
}
</script>

View File

@ -0,0 +1,16 @@
<template>
<ds-button size="small" :ghost="!isActive" @click.prevent="onClick" :icon="icon">
<span v-if="label">{{ label }}</span>
</ds-button>
</template>
<script>
export default {
props: {
isActive: Boolean,
icon: String,
label: String,
onClick: Function,
},
}
</script>

View File

@ -0,0 +1,96 @@
<template>
<ul v-show="showSuggestions" class="suggestion-list">
<li
v-for="(item, index) in filteredItems"
:key="item.id"
class="suggestion-list__item"
:class="{ 'is-selected': navigatedItemIndex === index }"
@click="selectItem(item)"
>
{{ createItemLabel(item) }}
</li>
<template v-if="isHashtag">
<li v-if="!query" class="suggestion-list__item hint">
{{ $t('editor.hashtag.addLetter') }}
</li>
<template v-else-if="!filteredItems.find(el => el.id === query)">
<li class="suggestion-list__item hint">{{ $t('editor.hashtag.addHashtag') }}</li>
<li class="suggestion-list__item" @click="selectItem({ id: query })">#{{ query }}</li>
</template>
</template>
<template v-else-if="isMention">
<li v-if="!hasResults" class="suggestion-list__item hint">
{{ $t('editor.mention.noUsersFound') }}
</li>
</template>
</ul>
</template>
<script>
import { HASHTAG, MENTION } from '../../constants/editor'
export default {
props: {
suggestionType: String,
filteredItems: Array,
query: String,
navigatedItemIndex: Number,
selectItem: Function,
},
computed: {
hasResults() {
return this.filteredItems.length > 0
},
isMention() {
return this.suggestionType === MENTION
},
isHashtag() {
return this.suggestionType === HASHTAG
},
showSuggestions() {
return this.query || this.hasResults
},
},
methods: {
createItemLabel(item) {
if (this.isMention) {
return `@${item.slug}`
} else {
return `#${item.id}`
}
},
},
}
</script>
<style lang="scss">
.suggestion-list {
list-style-type: none;
padding: 0.2rem;
border-radius: 5px;
border: 2px solid $color-primary;
font-size: 0.8rem;
font-weight: bold;
}
.suggestion-list__item {
border-radius: 5px;
padding: 0.2rem 0.5rem;
margin-bottom: 0.2rem;
cursor: pointer;
&:last-child {
margin-bottom: 0;
}
&.is-selected,
&:hover {
background-color: rgba($color-neutral-100, 0.3);
}
&.hint {
opacity: 0.7;
pointer-events: none;
}
}
</style>

View File

@ -0,0 +1,2 @@
export const HASHTAG = 'hashtag'
export const MENTION = 'mention'

View File

@ -0,0 +1,4 @@
export const ARROW_UP = 38
export const ARROW_DOWN = 40
export const RETURN = 13
export const SPACE = 32

View File

@ -51,5 +51,12 @@ export default i18n => {
} }
} }
`, `,
DeleteComment: gql`
mutation($id: ID!) {
DeleteComment(id: $id) {
id
}
}
`,
} }
} }

View File

@ -68,8 +68,8 @@
"jsonwebtoken": "~8.5.1", "jsonwebtoken": "~8.5.1",
"linkify-it": "~2.2.0", "linkify-it": "~2.2.0",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"nuxt": "~2.9.1", "nuxt": "~2.9.2",
"nuxt-dropzone": "^1.0.3", "nuxt-dropzone": "^1.0.4",
"nuxt-env": "~0.1.0", "nuxt-env": "~0.1.0",
"stack-utils": "^1.0.2", "stack-utils": "^1.0.2",
"string-hash": "^1.1.3", "string-hash": "^1.1.3",

View File

@ -1144,10 +1144,10 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
"@nuxt/babel-preset-app@2.9.1": "@nuxt/babel-preset-app@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/babel-preset-app/-/babel-preset-app-2.9.1.tgz#8394702e2829f9a576acc366b1335b02eaf5d1a1" resolved "https://registry.yarnpkg.com/@nuxt/babel-preset-app/-/babel-preset-app-2.9.2.tgz#e8d2ac841db845ef88ca2687093a95a480106e5d"
integrity sha512-lCY9lCXgiDEtnihxjDggzv4VE4+gHrxMxrnDmA66Fiks1KFLDVGN87PVc+Wo+hugi3rKHCTY0enP9h5Fkc0nFw== integrity sha512-s4423c5Pvl3aCmD8KoDdit1XZuZig0sCwop5KV3kn0/KfEru+jFWbQ3pTssCV8XTR9Am2BV0UIQ0hoCMdnvdfw==
dependencies: dependencies:
"@babel/core" "^7.5.5" "@babel/core" "^7.5.5"
"@babel/plugin-proposal-class-properties" "^7.5.5" "@babel/plugin-proposal-class-properties" "^7.5.5"
@ -1158,14 +1158,14 @@
"@vue/babel-preset-jsx" "^1.1.0" "@vue/babel-preset-jsx" "^1.1.0"
core-js "^2.6.5" core-js "^2.6.5"
"@nuxt/builder@2.9.1": "@nuxt/builder@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/builder/-/builder-2.9.1.tgz#e2196fcbd084122d04fc2e8cdd08d02efebd3a31" resolved "https://registry.yarnpkg.com/@nuxt/builder/-/builder-2.9.2.tgz#57c515efc446c02e4062ebdb6cd735ea456df4dd"
integrity sha512-99jch8WVqYcWDEO+uKDvCjvoiRVLc8ZI+Qbnm/cBJvZ0bB6hsD0a2H/kzyQpRYG7mhSP5TxnKPOSHVykQanXOQ== integrity sha512-egDjm2AnaKjeAlZ0yNAooP+Xd/fKIvhK66qNyd+ekvzutSkbSkKtB/udNxyHcBnjg8GOB4KayIXvBX0K1TS/vg==
dependencies: dependencies:
"@nuxt/devalue" "^1.2.4" "@nuxt/devalue" "^1.2.4"
"@nuxt/utils" "2.9.1" "@nuxt/utils" "2.9.2"
"@nuxt/vue-app" "2.9.1" "@nuxt/vue-app" "2.9.2"
chokidar "^3.0.2" chokidar "^3.0.2"
consola "^2.10.1" consola "^2.10.1"
fs-extra "^8.1.0" fs-extra "^8.1.0"
@ -1175,16 +1175,16 @@
lodash "^4.17.15" lodash "^4.17.15"
pify "^4.0.1" pify "^4.0.1"
semver "^6.3.0" semver "^6.3.0"
serialize-javascript "^1.7.0" serialize-javascript "^1.8.0"
upath "^1.1.2" upath "^1.1.2"
"@nuxt/cli@2.9.1": "@nuxt/cli@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/cli/-/cli-2.9.1.tgz#d9e0c18a566948f7d4d62132f38ef1648a0c253f" resolved "https://registry.yarnpkg.com/@nuxt/cli/-/cli-2.9.2.tgz#d56540f95b58afa7c7073c166d6f624b78024fca"
integrity sha512-EunBJdOfPRt3slurQZ/CfgHF1p+SR0MIUdWgH3pzbpZO5OxuhFI8Kcse5AWgH3ONneyNG9pwh+7bVz9eubaJcg== integrity sha512-9Pxavn/w/K4uUItXPNmKyT1aBoGlJPqTdpr3nlXRX00JSU1OKd2fTNL3RlaN+xXtlYh2XoZo2roGHAFX1CyKrw==
dependencies: dependencies:
"@nuxt/config" "2.9.1" "@nuxt/config" "2.9.2"
"@nuxt/utils" "2.9.1" "@nuxt/utils" "2.9.2"
boxen "^4.1.0" boxen "^4.1.0"
chalk "^2.4.2" chalk "^2.4.2"
consola "^2.10.1" consola "^2.10.1"
@ -1192,35 +1192,37 @@
execa "^2.0.4" execa "^2.0.4"
exit "^0.1.2" exit "^0.1.2"
fs-extra "^8.1.0" fs-extra "^8.1.0"
hable "^2.2.1"
minimist "^1.2.0" minimist "^1.2.0"
opener "1.5.1" opener "1.5.1"
pretty-bytes "^5.3.0" pretty-bytes "^5.3.0"
std-env "^2.2.1" std-env "^2.2.1"
wrap-ansi "^6.0.0" wrap-ansi "^6.0.0"
"@nuxt/config@2.9.1": "@nuxt/config@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/config/-/config-2.9.1.tgz#02d6484460a3ed0bd46e8e731490e4a20194d1f7" resolved "https://registry.yarnpkg.com/@nuxt/config/-/config-2.9.2.tgz#8976da395cc9f9971f48890ecaff9991d011578a"
integrity sha512-Zwtym2dmDDky4hqhRk3BVDfcZ+qicRbivlgJO00dOaVxIhn9KoYGj2+3gtva28gIit7F3qDx24S/yKX6jOQCfg== integrity sha512-FjBPZNE2vUh7UsJ4GdiEYcgr3umvAxSKU2xvbBQpBGk8mItPyt8k/1LmrRSvImkno4j1IBKp4VehSBZYEczJdQ==
dependencies: dependencies:
"@nuxt/utils" "2.9.1" "@nuxt/utils" "2.9.2"
consola "^2.10.1" consola "^2.10.1"
std-env "^2.2.1" std-env "^2.2.1"
"@nuxt/core@2.9.1": "@nuxt/core@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/core/-/core-2.9.1.tgz#42611ee8984358810b061403cf8300daa46a3446" resolved "https://registry.yarnpkg.com/@nuxt/core/-/core-2.9.2.tgz#1ab1d5c1928c37100a680241f23fe6ebe230d9f9"
integrity sha512-5nv1nk87SkrXMzchofVRsv6MSVhcf4QCk/rfn+meIB91pwJ/RqrMORGwR4vk+3JpZPnLMqrzi+CwnhhJodv3bw== integrity sha512-OtjLLutaMsYP6/EYXD96i/J79GSrjHlxfHbBaqHjIxnHdDnzZlsvA13EjULJ9mhumw3fvOPi12AEqqNpBHXqUg==
dependencies: dependencies:
"@nuxt/config" "2.9.1" "@nuxt/config" "2.9.2"
"@nuxt/devalue" "^1.2.4" "@nuxt/devalue" "^1.2.4"
"@nuxt/server" "2.9.1" "@nuxt/server" "2.9.2"
"@nuxt/utils" "2.9.1" "@nuxt/utils" "2.9.2"
"@nuxt/vue-renderer" "2.9.1" "@nuxt/vue-renderer" "2.9.2"
consola "^2.10.1" consola "^2.10.1"
debug "^4.1.1" debug "^4.1.1"
esm "^3.2.25" esm "^3.2.25"
fs-extra "^8.1.0" fs-extra "^8.1.0"
hable "^2.2.1"
hash-sum "^2.0.0" hash-sum "^2.0.0"
std-env "^2.2.1" std-env "^2.2.1"
@ -1241,12 +1243,12 @@
error-stack-parser "^2.0.0" error-stack-parser "^2.0.0"
string-width "^2.0.0" string-width "^2.0.0"
"@nuxt/generator@2.9.1": "@nuxt/generator@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/generator/-/generator-2.9.1.tgz#a46e95855e4c68fb890c01148676c6c91704c07c" resolved "https://registry.yarnpkg.com/@nuxt/generator/-/generator-2.9.2.tgz#5fd8e1af5217b3c7049ef89af4a8568b3d34a437"
integrity sha512-GRosDDdwhSnd58bBoUjcewyUfEPolVLECqh1fmqTih5i2EPZm7aV4k6wGkoVZAu/4GQYjlZPo7sc2uZy14uJ8A== integrity sha512-54bp94eel5vAxUQPKP8YU3uxPmaqSb0EwXXY+712LS2kZ2HELR/YpuATOH2wS3IUfpc0x9Zu6O/nPkjYo+635Q==
dependencies: dependencies:
"@nuxt/utils" "2.9.1" "@nuxt/utils" "2.9.2"
chalk "^2.4.2" chalk "^2.4.2"
consola "^2.10.1" consola "^2.10.1"
fs-extra "^8.1.0" fs-extra "^8.1.0"
@ -1262,22 +1264,22 @@
node-res "^5.0.1" node-res "^5.0.1"
serve-static "^1.14.1" serve-static "^1.14.1"
"@nuxt/opencollective@^0.2.2": "@nuxt/opencollective@^0.3.0":
version "0.2.2" version "0.3.0"
resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.2.2.tgz#17adc7d380457379cd14cbb64a435ea196cc4a6e" resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.3.0.tgz#11d8944dcf2d526e31660bb69570be03f8fb72b7"
integrity sha512-ie50SpS47L+0gLsW4yP23zI/PtjsDRglyozX2G09jeiUazC1AJlGPZo0JUs9iuCDUoIgsDEf66y7/bSfig0BpA== integrity sha512-Vf09BxCdj1iT2IRqVwX5snaY2WCTkvM0O4cWWSO1ThCFuc4if0Q/nNwAgCxRU0FeYHJ7DdyMUNSdswCLKlVqeg==
dependencies: dependencies:
chalk "^2.4.1" chalk "^2.4.2"
consola "^2.3.0" consola "^2.10.1"
node-fetch "^2.3.0" node-fetch "^2.6.0"
"@nuxt/server@2.9.1": "@nuxt/server@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/server/-/server-2.9.1.tgz#dc6ea866bc36d1466e30f0b91e404e7c75961b5e" resolved "https://registry.yarnpkg.com/@nuxt/server/-/server-2.9.2.tgz#ef6f45b57b2f873c48ddb3cb1c593f56052dc186"
integrity sha512-kIyZR/SlIjNIslReLDyGy4o+8NDNxFlFQM5zGbnOTSxOAIMEcyoUxoGeOc2wFr+QN5LFfpl+vruglUjRWGXhNQ== integrity sha512-If9Yu1pCah3d9l1AmyZ6hyfJ4+3RTekAdB9lMyHskIFGR4DCoTx2cd8oJ0VOv9CgQz90j/1Wi/SdeHy22Hy9Fg==
dependencies: dependencies:
"@nuxt/config" "2.9.1" "@nuxt/config" "2.9.2"
"@nuxt/utils" "2.9.1" "@nuxt/utils" "2.9.2"
"@nuxtjs/youch" "^4.2.3" "@nuxtjs/youch" "^4.2.3"
chalk "^2.4.2" chalk "^2.4.2"
compression "^1.7.4" compression "^1.7.4"
@ -1294,24 +1296,24 @@
serve-static "^1.14.1" serve-static "^1.14.1"
server-destroy "^1.0.1" server-destroy "^1.0.1"
"@nuxt/utils@2.9.1": "@nuxt/utils@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/utils/-/utils-2.9.1.tgz#5b2e0cdb9957971b6e20787c7582060c9ec1ba5c" resolved "https://registry.yarnpkg.com/@nuxt/utils/-/utils-2.9.2.tgz#b6ced2abe8ada3f8d5ec03dd1a5e8053c9b4a66c"
integrity sha512-7PWq0YM55+DRkwa2hLuFVKPkMhrFoWvehYtQhvhQWc0LvA+Hmv7hm6cABZsas1qsMunO4t3j5OK2xPxO0yLhDg== integrity sha512-qmXbRNNJtdT4cr1t66ayaUFx9rQ9aOiLPHM/J69/uw/TKiy/j3WgX1YHE6TRAfIpg0eb68nDzHGM40T3XJ+jsg==
dependencies: dependencies:
consola "^2.10.1" consola "^2.10.1"
fs-extra "^8.1.0" fs-extra "^8.1.0"
hash-sum "^2.0.0" hash-sum "^2.0.0"
proper-lockfile "^4.1.1" proper-lockfile "^4.1.1"
semver "^6.3.0" semver "^6.3.0"
serialize-javascript "^1.7.0" serialize-javascript "^1.8.0"
signal-exit "^3.0.2" signal-exit "^3.0.2"
ua-parser-js "^0.7.20" ua-parser-js "^0.7.20"
"@nuxt/vue-app@2.9.1": "@nuxt/vue-app@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/vue-app/-/vue-app-2.9.1.tgz#52433b20f9027949610981c4853604106ed80374" resolved "https://registry.yarnpkg.com/@nuxt/vue-app/-/vue-app-2.9.2.tgz#725b1f6c4ac955b990ce3db68f9ae19a8d578c5b"
integrity sha512-YiPii6wmf6R/LYOv+7Y5QGBBVwvwKVUDwR3AQ0HCh2FNJ/sz5vG2C+q2ADRZ8nMyqUMKhjLPgn9PTXFioySQ6w== integrity sha512-zLoCvA3+UVfdikfol7plPukP0GddU1LdgkV+1EDeVUm22PNgt/OdYN3z5kJIZEfZoLpfMbtF8NsBVWrehPuoFQ==
dependencies: dependencies:
node-fetch "^2.6.0" node-fetch "^2.6.0"
unfetch "^4.1.0" unfetch "^4.1.0"
@ -1323,13 +1325,13 @@
vue-template-compiler "^2.6.10" vue-template-compiler "^2.6.10"
vuex "^3.1.1" vuex "^3.1.1"
"@nuxt/vue-renderer@2.9.1": "@nuxt/vue-renderer@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/vue-renderer/-/vue-renderer-2.9.1.tgz#29e5334a3245f3cdab7cba29b2748c0e4cd75e6f" resolved "https://registry.yarnpkg.com/@nuxt/vue-renderer/-/vue-renderer-2.9.2.tgz#5118ba5caa894d94b272ad4665f88837ab2359ef"
integrity sha512-/V1LnjXEfLMaYFjzF1FtpHc2hjE66ppVnHnljBh56NEIwxBu9EGEGG1d3oydurnOtmikbpKgR5qnnHcKOQXnoA== integrity sha512-bLUnYEj2PHs07K7EAH+a3Nhg9ZK4WRsbG9q5eYNF3CD0O10CzNOR6/8qqqbFYj8hFrP76EOf0P/5CAJcWvRtPg==
dependencies: dependencies:
"@nuxt/devalue" "^1.2.4" "@nuxt/devalue" "^1.2.4"
"@nuxt/utils" "2.9.1" "@nuxt/utils" "2.9.2"
consola "^2.10.1" consola "^2.10.1"
fs-extra "^8.1.0" fs-extra "^8.1.0"
lru-cache "^5.1.1" lru-cache "^5.1.1"
@ -1337,15 +1339,15 @@
vue-meta "^2.2.1" vue-meta "^2.2.1"
vue-server-renderer "^2.6.10" vue-server-renderer "^2.6.10"
"@nuxt/webpack@2.9.1": "@nuxt/webpack@2.9.2":
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/@nuxt/webpack/-/webpack-2.9.1.tgz#21a090a99b1cb6d644f72ee90143a1ad0e3c0d91" resolved "https://registry.yarnpkg.com/@nuxt/webpack/-/webpack-2.9.2.tgz#4db33ddcb6805d5fed06a67515e542ca54ffa75d"
integrity sha512-ib3UHu+1/CVkHIQPZbcZ+LFWNWuiNuJtGjpIkaPgY563yutqAqI1Xwinr9bzmrk1yaBoT9YEg00U2cviVzAc4A== integrity sha512-M+j3Ceo6BcBSz4eIXqMP+Owcp2f78Dco+KGHJuUuCxWRNJjVdJAo1RHa2sMVDezdQgiDJQzgChwORU2mjN6rEw==
dependencies: dependencies:
"@babel/core" "^7.5.5" "@babel/core" "^7.5.5"
"@nuxt/babel-preset-app" "2.9.1" "@nuxt/babel-preset-app" "2.9.2"
"@nuxt/friendly-errors-webpack-plugin" "^2.5.0" "@nuxt/friendly-errors-webpack-plugin" "^2.5.0"
"@nuxt/utils" "2.9.1" "@nuxt/utils" "2.9.2"
babel-loader "^8.0.6" babel-loader "^8.0.6"
cache-loader "^4.1.0" cache-loader "^4.1.0"
caniuse-lite "^1.0.30000989" caniuse-lite "^1.0.30000989"
@ -1376,7 +1378,7 @@
time-fix-plugin "^2.0.6" time-fix-plugin "^2.0.6"
url-loader "^2.1.0" url-loader "^2.1.0"
vue-loader "^15.7.1" vue-loader "^15.7.1"
webpack "^4.39.2" webpack "^4.39.3"
webpack-bundle-analyzer "^3.4.1" webpack-bundle-analyzer "^3.4.1"
webpack-dev-middleware "^3.7.0" webpack-dev-middleware "^3.7.0"
webpack-hot-middleware "^2.25.0" webpack-hot-middleware "^2.25.0"
@ -5114,7 +5116,7 @@ connect@^3.7.0:
parseurl "~1.3.3" parseurl "~1.3.3"
utils-merge "1.0.1" utils-merge "1.0.1"
consola@^2.10.0, consola@^2.10.1, consola@^2.3.0, consola@^2.4.0, consola@^2.5.6, consola@^2.6.0, consola@^2.6.1, consola@^2.9.0: consola@^2.10.0, consola@^2.10.1, consola@^2.4.0, consola@^2.5.6, consola@^2.6.0, consola@^2.6.1, consola@^2.9.0:
version "2.10.1" version "2.10.1"
resolved "https://registry.yarnpkg.com/consola/-/consola-2.10.1.tgz#4693edba714677c878d520e4c7e4f69306b4b927" resolved "https://registry.yarnpkg.com/consola/-/consola-2.10.1.tgz#4693edba714677c878d520e4c7e4f69306b4b927"
integrity sha512-4sxpH6SGFYLADfUip4vuY65f/gEogrzJoniVhNUYkJHtng0l8ZjnDCqxxrSVRHOHwKxsy8Vm5ONZh1wOR3/l/w== integrity sha512-4sxpH6SGFYLADfUip4vuY65f/gEogrzJoniVhNUYkJHtng0l8ZjnDCqxxrSVRHOHwKxsy8Vm5ONZh1wOR3/l/w==
@ -7658,6 +7660,11 @@ gzip-size@^5.0.0:
duplexer "^0.1.1" duplexer "^0.1.1"
pify "^4.0.1" pify "^4.0.1"
hable@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/hable/-/hable-2.2.1.tgz#714ef141a7eda5bd8530d6e4e3b37c6807716290"
integrity sha512-CuGRGMNnCp8RJ70zeoTX37sX4ctoT8BpmkStI2TYQwBBtWzQQFXQ/jsBUCqd34grt3IJQ+hkUXAU84/IuErVLQ==
handlebars@^4.1.2: handlebars@^4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67"
@ -10382,7 +10389,7 @@ node-fetch@^1.0.1:
encoding "^0.1.11" encoding "^0.1.11"
is-stream "^1.0.1" is-stream "^1.0.1"
node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.3.0: node-fetch@^2.1.2, node-fetch@^2.2.0:
version "2.5.0" version "2.5.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.5.0.tgz#8028c49fc1191bba56a07adc6e2a954644a48501" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.5.0.tgz#8028c49fc1191bba56a07adc6e2a954644a48501"
integrity sha512-YuZKluhWGJwCcUu4RlZstdAxr8bFfOVHakc1mplwHkk8J+tqM1Y5yraYvIUpeX8aY7+crCwiELJq7Vl0o0LWXw== integrity sha512-YuZKluhWGJwCcUu4RlZstdAxr8bFfOVHakc1mplwHkk8J+tqM1Y5yraYvIUpeX8aY7+crCwiELJq7Vl0o0LWXw==
@ -10712,10 +10719,10 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
nuxt-dropzone@^1.0.3: nuxt-dropzone@^1.0.4:
version "1.0.3" version "1.0.4"
resolved "https://registry.yarnpkg.com/nuxt-dropzone/-/nuxt-dropzone-1.0.3.tgz#f808ad3bc30809d34d6cbbcb24cece6e73341107" resolved "https://registry.yarnpkg.com/nuxt-dropzone/-/nuxt-dropzone-1.0.4.tgz#ef10af35938f95bfe6a9ba3eb7b7de17db7cbb14"
integrity sha512-lElULoEkPJ1bJ7JzOyvg98/SSEAdvYHjdQ4V1k/XPe1Q/vmzMtOn2DxKwtzFKVWA5RqnB1P+EAjUMYan4mn0aw== integrity sha512-1QuthM3bDGBN2ugXE5HfcvBmekNy4YUYfMurTeuBrwIGId0JSF9HasspwndxsSNL42eGET83eezRcH4ekLGqeA==
dependencies: dependencies:
vue2-dropzone "3.6.0" vue2-dropzone "3.6.0"
@ -10724,18 +10731,18 @@ nuxt-env@~0.1.0:
resolved "https://registry.yarnpkg.com/nuxt-env/-/nuxt-env-0.1.0.tgz#8ac50b9ff45391ad3044ea932cbd05f06a585f87" resolved "https://registry.yarnpkg.com/nuxt-env/-/nuxt-env-0.1.0.tgz#8ac50b9ff45391ad3044ea932cbd05f06a585f87"
integrity sha512-7mTao3qG0zfN0hahk3O6SuDy0KEwYmNojammWQsMwhqMn3aUjX4nMYnWDa0pua+2/rwAY9oG53jQtLgJdG7f9w== integrity sha512-7mTao3qG0zfN0hahk3O6SuDy0KEwYmNojammWQsMwhqMn3aUjX4nMYnWDa0pua+2/rwAY9oG53jQtLgJdG7f9w==
nuxt@~2.9.1: nuxt@~2.9.2:
version "2.9.1" version "2.9.2"
resolved "https://registry.yarnpkg.com/nuxt/-/nuxt-2.9.1.tgz#6a9ce48d03b9e6f82919d4e66051b3d49b7aee36" resolved "https://registry.yarnpkg.com/nuxt/-/nuxt-2.9.2.tgz#3c190fe79dcb00550029d065bb9505caffd02bbb"
integrity sha512-riZ9ZUXCtUnRWcixJj3Mja6t5ujGlD/9/E71VDwW47AvyxhlYrSzitSUSs9sBwsC+6zzwP8cCM2k1fO/2oWyrg== integrity sha512-PQjHQfh567g9J+SdbiZPWUZ9FXKWDONE9kB6/H9O9reWcac+jwD/uwWzZrgt+W6AiphHmbfwyGGLwCLv5hrQBg==
dependencies: dependencies:
"@nuxt/builder" "2.9.1" "@nuxt/builder" "2.9.2"
"@nuxt/cli" "2.9.1" "@nuxt/cli" "2.9.2"
"@nuxt/core" "2.9.1" "@nuxt/core" "2.9.2"
"@nuxt/generator" "2.9.1" "@nuxt/generator" "2.9.2"
"@nuxt/loading-screen" "^1.0.1" "@nuxt/loading-screen" "^1.0.1"
"@nuxt/opencollective" "^0.2.2" "@nuxt/opencollective" "^0.3.0"
"@nuxt/webpack" "2.9.1" "@nuxt/webpack" "2.9.2"
nwsapi@^2.0.7: nwsapi@^2.0.7:
version "2.1.4" version "2.1.4"
@ -13458,6 +13465,11 @@ serialize-javascript@^1.3.0, serialize-javascript@^1.4.0, serialize-javascript@^
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65"
integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==
serialize-javascript@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.8.0.tgz#9515fc687232e2321aea1ca7a529476eb34bb480"
integrity sha512-3tHgtF4OzDmeKYj6V9nSyceRS0UJ3C7VqyD2Yj28vC/z2j6jG5FmFGahOKMD9CrglxTm3tETr87jEypaYV8DUg==
serve-favicon@^2.5.0: serve-favicon@^2.5.0:
version "2.5.0" version "2.5.0"
resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.5.0.tgz#935d240cdfe0f5805307fdfe967d88942a2cbcf0" resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.5.0.tgz#935d240cdfe0f5805307fdfe967d88942a2cbcf0"
@ -15473,10 +15485,10 @@ webpack@^4.38.0:
watchpack "^1.6.0" watchpack "^1.6.0"
webpack-sources "^1.4.1" webpack-sources "^1.4.1"
webpack@^4.39.2: webpack@^4.39.3:
version "4.39.2" version "4.39.3"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.39.2.tgz#c9aa5c1776d7c309d1b3911764f0288c8c2816aa" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.39.3.tgz#a02179d1032156b713b6ec2da7e0df9d037def50"
integrity sha512-AKgTfz3xPSsEibH00JfZ9sHXGUwIQ6eZ9tLN8+VLzachk1Cw2LVmy+4R7ZiwTa9cZZ15tzySjeMui/UnSCAZhA== integrity sha512-BXSI9M211JyCVc3JxHWDpze85CvjC842EvpRsVTc/d15YJGlox7GIDd38kJgWrb3ZluyvIjgenbLDMBQPDcxYQ==
dependencies: dependencies:
"@webassemblyjs/ast" "1.8.5" "@webassemblyjs/ast" "1.8.5"
"@webassemblyjs/helper-module-context" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5"

View File

@ -1847,10 +1847,10 @@ cucumber@^4.2.1:
util-arity "^1.0.2" util-arity "^1.0.2"
verror "^1.9.0" verror "^1.9.0"
cypress-cucumber-preprocessor@^1.15.0: cypress-cucumber-preprocessor@^1.15.1:
version "1.15.0" version "1.15.1"
resolved "https://registry.yarnpkg.com/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-1.15.0.tgz#bc2bbad5799dcc07798a0f8f1d374b99e0d3bbab" resolved "https://registry.yarnpkg.com/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-1.15.1.tgz#9a53d4931e9fcc502f0fd89c8373a4869f9a0e79"
integrity sha512-6exZ4cPruFcx55INZtxGnUwoGuzcAq+8T1k7NaCC2g36mdweltGjtjIGuHy4lk+VQaW6zmLV6zDtuxrEQsFC/w== integrity sha512-rZeZskdOXljFKSiSiSUg0oQ4+3/kY8g1y5mNS8POrFM8Ch3rldw6ZJy4soMfqHKitNyilaUl/pRsgjH6cFI95w==
dependencies: dependencies:
"@cypress/browserify-preprocessor" "^1.1.2" "@cypress/browserify-preprocessor" "^1.1.2"
chai "^4.1.2" chai "^4.1.2"