mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
fix conflicts with merge
This commit is contained in:
commit
f6e70bee25
176
CHANGELOG.md
176
CHANGELOG.md
@ -2,138 +2,62 @@
|
|||||||
|
|
||||||
## [Unreleased](https://github.com/Human-Connection/Human-Connection/tree/HEAD)
|
## [Unreleased](https://github.com/Human-Connection/Human-Connection/tree/HEAD)
|
||||||
|
|
||||||
[Full Changelog](https://github.com/Human-Connection/Human-Connection/compare/0.1.0...HEAD)
|
[Full Changelog](https://github.com/Human-Connection/Human-Connection/compare/0.1.4...HEAD)
|
||||||
|
|
||||||
**Fixed bugs:**
|
|
||||||
|
|
||||||
- 🐛 \[Bug\] Update maintenance page email [\#1731](https://github.com/Human-Connection/Human-Connection/issues/1731)
|
|
||||||
- 🐛 \[Bug\] Editing comments is not reactive again [\#1718](https://github.com/Human-Connection/Human-Connection/issues/1718)
|
|
||||||
- 🐛 \[Bug\] Comments with mentions in the end not displayed [\#1665](https://github.com/Human-Connection/Human-Connection/issues/1665)
|
|
||||||
- 🐛 \[Bug\] Delete the Sleep Icon [\#1659](https://github.com/Human-Connection/Human-Connection/issues/1659)
|
|
||||||
- 🐛 \[Bug\] Far to less Characters per Contribution \(2000\) [\#1639](https://github.com/Human-Connection/Human-Connection/issues/1639)
|
|
||||||
- 🐛 \[Bug\] Notifications do just update with page reload [\#1637](https://github.com/Human-Connection/Human-Connection/issues/1637)
|
|
||||||
- 🐛 \[Bug\] Can no users used all hashtags be correct? [\#1632](https://github.com/Human-Connection/Human-Connection/issues/1632)
|
|
||||||
- 🐛 \[Bug\] Create account has no info about email, no localisation, no HC logo [\#1631](https://github.com/Human-Connection/Human-Connection/issues/1631)
|
|
||||||
- 🐛 \[Bug\] Embeds are displayed when creating comments but get removed [\#1547](https://github.com/Human-Connection/Human-Connection/issues/1547)
|
|
||||||
- 🐛 \[Bug\] One cypress test fails but it does not fail the build [\#1312](https://github.com/Human-Connection/Human-Connection/issues/1312)
|
|
||||||
- 🐛 \[Bug\] TypeError: Cannot read property 'offsetTop' of null [\#1273](https://github.com/Human-Connection/Human-Connection/issues/1273)
|
|
||||||
|
|
||||||
**Closed issues:**
|
**Closed issues:**
|
||||||
|
|
||||||
- 🚀 \[Feature\] Extend Emoticons [\#1745](https://github.com/Human-Connection/Human-Connection/issues/1745)
|
- 🚀 \[Feature\] Register as a new User [\#1785](https://github.com/Human-Connection/Human-Connection/issues/1785)
|
||||||
- 🚀 \[Feature\] Change slug [\#1650](https://github.com/Human-Connection/Human-Connection/issues/1650)
|
|
||||||
- 🚀 \[Feature\] Make the slug more visible and usable [\#1486](https://github.com/Human-Connection/Human-Connection/issues/1486)
|
|
||||||
- 🚀 \[Feature\] Report with reason [\#1469](https://github.com/Human-Connection/Human-Connection/issues/1469)
|
|
||||||
- 🚀 \[Feature\] Make Invite an Registration E-Mails translatable and pretty [\#1186](https://github.com/Human-Connection/Human-Connection/issues/1186)
|
|
||||||
- 🚀 \[Feature\] @Username: Unique user identification if identical profile names exist [\#1069](https://github.com/Human-Connection/Human-Connection/issues/1069)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
**Merged pull requests:**
|
||||||
|
|
||||||
- Bump metascraper-logo from 5.7.5 to 5.7.6 in /backend [\#1783](https://github.com/Human-Connection/Human-Connection/pull/1783) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- Refactor embed settings page [\#1861](https://github.com/Human-Connection/Human-Connection/pull/1861) ([roschaefer](https://github.com/roschaefer))
|
||||||
- Bump metascraper-url from 5.7.5 to 5.7.6 in /backend [\#1782](https://github.com/Human-Connection/Human-Connection/pull/1782) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- Implement public registration [\#1814](https://github.com/Human-Connection/Human-Connection/pull/1814) ([roschaefer](https://github.com/roschaefer))
|
||||||
- Bump graphql-middleware from 3.0.5 to 4.0.1 in /backend [\#1781](https://github.com/Human-Connection/Human-Connection/pull/1781) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump eslint from 6.4.0 to 6.5.1 in /backend [\#1780](https://github.com/Human-Connection/Human-Connection/pull/1780) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
## [0.1.4](https://github.com/Human-Connection/Human-Connection/tree/0.1.4) (2019-10-10)
|
||||||
- Bump metascraper-audio from 5.7.5 to 5.7.6 in /backend [\#1779](https://github.com/Human-Connection/Human-Connection/pull/1779) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
[Full Changelog](https://github.com/Human-Connection/Human-Connection/compare/0.1.3...0.1.4)
|
||||||
- Bump metascraper-publisher from 5.7.4 to 5.7.6 in /backend [\#1778](https://github.com/Human-Connection/Human-Connection/pull/1778) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump metascraper-youtube from 5.7.5 to 5.7.6 in /backend [\#1777](https://github.com/Human-Connection/Human-Connection/pull/1777) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
**Fixed bugs:**
|
||||||
- Bump @babel/preset-env from 7.6.0 to 7.6.2 in /backend [\#1776](https://github.com/Human-Connection/Human-Connection/pull/1776) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump metascraper-soundcloud from 5.7.4 to 5.7.6 in /backend [\#1775](https://github.com/Human-Connection/Human-Connection/pull/1775) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- 🐛 \[Bug\] extend Title to 100 characters [\#1812](https://github.com/Human-Connection/Human-Connection/issues/1812)
|
||||||
- Bump metascraper-author from 5.7.4 to 5.7.6 in /backend [\#1774](https://github.com/Human-Connection/Human-Connection/pull/1774) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Fix failing test [\#1772](https://github.com/Human-Connection/Human-Connection/pull/1772) ([aonomike](https://github.com/aonomike))
|
**Closed issues:**
|
||||||
- Bump metascraper-date from 5.7.4 to 5.7.6 in /backend [\#1771](https://github.com/Human-Connection/Human-Connection/pull/1771) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump tiptap-extensions from 1.27.0 to 1.28.0 in /webapp [\#1770](https://github.com/Human-Connection/Human-Connection/pull/1770) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- 🚀 \[Feature\] Make Email of a User visible for Moderators [\#1704](https://github.com/Human-Connection/Human-Connection/issues/1704)
|
||||||
- Bump date-fns from 2.3.0 to 2.4.1 in /backend [\#1769](https://github.com/Human-Connection/Human-Connection/pull/1769) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- 🚀 \[Feature\] save embeds iframe permanently [\#1684](https://github.com/Human-Connection/Human-Connection/issues/1684)
|
||||||
- Bump date-fns from 2.4.0 to 2.4.1 in /webapp [\#1768](https://github.com/Human-Connection/Human-Connection/pull/1768) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump graphql-middleware-sentry from 3.2.0 to 3.2.1 in /backend [\#1767](https://github.com/Human-Connection/Human-Connection/pull/1767) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
**Merged pull requests:**
|
||||||
- Bump metascraper-lang from 5.7.4 to 5.7.6 in /backend [\#1766](https://github.com/Human-Connection/Human-Connection/pull/1766) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump tiptap from 1.25.0 to 1.26.0 in /webapp [\#1765](https://github.com/Human-Connection/Human-Connection/pull/1765) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- Add Hall of Fame to README [\#1859](https://github.com/Human-Connection/Human-Connection/pull/1859) ([roschaefer](https://github.com/roschaefer))
|
||||||
- Bump metascraper-video from 5.7.5 to 5.7.6 in /backend [\#1764](https://github.com/Human-Connection/Human-Connection/pull/1764) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump cypress-cucumber-preprocessor from 1.16.1 to 1.16.2 [\#1855](https://github.com/Human-Connection/Human-Connection/pull/1855) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump apollo-server from 2.9.3 to 2.9.4 in /backend [\#1762](https://github.com/Human-Connection/Human-Connection/pull/1762) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps\): bump nodemailer from 6.3.0 to 6.3.1 in /backend [\#1854](https://github.com/Human-Connection/Human-Connection/pull/1854) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump metascraper-image from 5.7.5 to 5.7.6 in /backend [\#1761](https://github.com/Human-Connection/Human-Connection/pull/1761) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- Save user setting to show embed code II [\#1852](https://github.com/Human-Connection/Human-Connection/pull/1852) ([ogerly](https://github.com/ogerly))
|
||||||
- Bump eslint-loader from 3.0.1 to 3.0.2 in /webapp [\#1760](https://github.com/Human-Connection/Human-Connection/pull/1760) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- Title character increased from 64 to 100 [\#1850](https://github.com/Human-Connection/Human-Connection/pull/1850) ([ogerly](https://github.com/ogerly))
|
||||||
- Bump metascraper-title from 5.7.5 to 5.7.6 in /backend [\#1759](https://github.com/Human-Connection/Human-Connection/pull/1759) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump @babel/core from 7.6.2 to 7.6.3 in /webapp [\#1848](https://github.com/Human-Connection/Human-Connection/pull/1848) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump nodemon from 1.19.2 to 1.19.3 in /backend [\#1758](https://github.com/Human-Connection/Human-Connection/pull/1758) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump @babel/cli from 7.6.2 to 7.6.3 in /backend [\#1847](https://github.com/Human-Connection/Human-Connection/pull/1847) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- fix email middleware transport config [\#1757](https://github.com/Human-Connection/Human-Connection/pull/1757) ([vbelolapotkov](https://github.com/vbelolapotkov))
|
- build\(deps-dev\): bump @babel/preset-env from 7.6.2 to 7.6.3 in /backend [\#1846](https://github.com/Human-Connection/Human-Connection/pull/1846) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- 1273 fix post page nav suggestions [\#1756](https://github.com/Human-Connection/Human-Connection/pull/1756) ([roschaefer](https://github.com/roschaefer))
|
- build\(deps-dev\): bump @babel/node from 7.6.2 to 7.6.3 in /backend [\#1843](https://github.com/Human-Connection/Human-Connection/pull/1843) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- docs: moves storybook into webapp/README.md [\#1755](https://github.com/Human-Connection/Human-Connection/pull/1755) ([roschaefer](https://github.com/roschaefer))
|
- build\(deps\): bump styleguide from `808b3c5` to `d46fc15` [\#1839](https://github.com/Human-Connection/Human-Connection/pull/1839) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump date-fns from 2.2.1 to 2.4.0 in /webapp [\#1752](https://github.com/Human-Connection/Human-Connection/pull/1752) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump @storybook/addon-actions from 5.2.1 to 5.2.3 in /webapp [\#1838](https://github.com/Human-Connection/Human-Connection/pull/1838) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- fix: Github's security vulnerability warning [\#1751](https://github.com/Human-Connection/Human-Connection/pull/1751) ([roschaefer](https://github.com/roschaefer))
|
- build\(deps\): bump node from 12.11.0-alpine to 12.11.1-alpine in /backend [\#1837](https://github.com/Human-Connection/Human-Connection/pull/1837) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- update neo4j docker-compose config [\#1750](https://github.com/Human-Connection/Human-Connection/pull/1750) ([vbelolapotkov](https://github.com/vbelolapotkov))
|
- build\(deps-dev\): bump @storybook/addon-a11y from 5.2.1 to 5.2.3 in /webapp [\#1836](https://github.com/Human-Connection/Human-Connection/pull/1836) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- 🍰 Try to fix VSCode format works against ESLint [\#1749](https://github.com/Human-Connection/Human-Connection/pull/1749) ([Tirokk](https://github.com/Tirokk))
|
- build\(deps\): bump node from 12.11.0-alpine to 12.11.1-alpine in /webapp [\#1835](https://github.com/Human-Connection/Human-Connection/pull/1835) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump neo4j from 3.5.9 to 3.5.11 in /neo4j [\#1739](https://github.com/Human-Connection/Human-Connection/pull/1739) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump @storybook/vue from 5.2.1 to 5.2.3 in /webapp [\#1834](https://github.com/Human-Connection/Human-Connection/pull/1834) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump graphql from 14.5.7 to 14.5.8 in /backend [\#1738](https://github.com/Human-Connection/Human-Connection/pull/1738) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump cucumber from 6.0.1 to 6.0.2 in /backend [\#1833](https://github.com/Human-Connection/Human-Connection/pull/1833) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump metascraper-youtube from 5.7.4 to 5.7.5 in /backend [\#1737](https://github.com/Human-Connection/Human-Connection/pull/1737) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- Fix typo in email template [\#1829](https://github.com/Human-Connection/Human-Connection/pull/1829) ([alina-beck](https://github.com/alina-beck))
|
||||||
- Update to 0.1.1 [\#1734](https://github.com/Human-Connection/Human-Connection/pull/1734) ([roschaefer](https://github.com/roschaefer))
|
- build\(deps-dev\): bump cucumber from 5.1.0 to 6.0.1 in /backend [\#1827](https://github.com/Human-Connection/Human-Connection/pull/1827) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Update maintenance page email to support@... [\#1732](https://github.com/Human-Connection/Human-Connection/pull/1732) ([mattwr18](https://github.com/mattwr18))
|
- build\(deps\): bump node from 12.10.0-alpine to 12.11.0-alpine in /backend [\#1826](https://github.com/Human-Connection/Human-Connection/pull/1826) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump @babel/register from 7.6.0 to 7.6.2 in /backend [\#1730](https://github.com/Human-Connection/Human-Connection/pull/1730) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps\): bump node from 12.10.0-alpine to 12.11.0-alpine in /webapp [\#1824](https://github.com/Human-Connection/Human-Connection/pull/1824) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump graphql from 14.5.7 to 14.5.8 in /webapp [\#1729](https://github.com/Human-Connection/Human-Connection/pull/1729) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump apollo-server-testing from 2.9.4 to 2.9.5 in /backend [\#1823](https://github.com/Human-Connection/Human-Connection/pull/1823) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump @babel/core from 7.6.0 to 7.6.2 in /backend [\#1728](https://github.com/Human-Connection/Human-Connection/pull/1728) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps\): bump tiptap-extensions from 1.28.0 to 1.28.3 in /webapp [\#1822](https://github.com/Human-Connection/Human-Connection/pull/1822) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump eslint-loader from 3.0.0 to 3.0.1 in /webapp [\#1727](https://github.com/Human-Connection/Human-Connection/pull/1727) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps\): bump tiptap from 1.26.0 to 1.26.3 in /webapp [\#1821](https://github.com/Human-Connection/Human-Connection/pull/1821) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump apollo-server-express from 2.9.3 to 2.9.4 in /backend [\#1726](https://github.com/Human-Connection/Human-Connection/pull/1726) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump eslint-config-prettier from 6.3.0 to 6.4.0 in /webapp [\#1819](https://github.com/Human-Connection/Human-Connection/pull/1819) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump @babel/node from 7.6.1 to 7.6.2 in /backend [\#1725](https://github.com/Human-Connection/Human-Connection/pull/1725) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump eslint-config-prettier from 6.3.0 to 6.4.0 in /backend [\#1818](https://github.com/Human-Connection/Human-Connection/pull/1818) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Fix bug UpdateComment, Fix styling on Comment [\#1719](https://github.com/Human-Connection/Human-Connection/pull/1719) ([mattwr18](https://github.com/mattwr18))
|
- build\(deps\): bump @hapi/joi from 16.1.5 to 16.1.7 in /backend [\#1817](https://github.com/Human-Connection/Human-Connection/pull/1817) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump apollo-server-testing from 2.9.3 to 2.9.4 in /backend [\#1717](https://github.com/Human-Connection/Human-Connection/pull/1717) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps-dev\): bump cypress-cucumber-preprocessor from 1.16.0 to 1.16.1 [\#1816](https://github.com/Human-Connection/Human-Connection/pull/1816) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- Bump metascraper-title from 5.7.4 to 5.7.5 in /backend [\#1715](https://github.com/Human-Connection/Human-Connection/pull/1715) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- Update to 0.1.3 [\#1813](https://github.com/Human-Connection/Human-Connection/pull/1813) ([mattwr18](https://github.com/mattwr18))
|
||||||
- Bump date-fns from 2.2.1 to 2.3.0 in /backend [\#1714](https://github.com/Human-Connection/Human-Connection/pull/1714) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- Display user email for administrators [\#1808](https://github.com/Human-Connection/Human-Connection/pull/1808) ([aonomike](https://github.com/aonomike))
|
||||||
- Bump @babel/cli from 7.6.0 to 7.6.2 in /backend [\#1713](https://github.com/Human-Connection/Human-Connection/pull/1713) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
- build\(deps\): bump nuxt from 2.9.2 to 2.10.0 in /webapp [\#1804](https://github.com/Human-Connection/Human-Connection/pull/1804) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
||||||
- \[WIP\]1706 refactor shout spec [\#1712](https://github.com/Human-Connection/Human-Connection/pull/1712) ([aonomike](https://github.com/aonomike))
|
- \[TEST\] Save user setting to show embed code [\#1686](https://github.com/Human-Connection/Human-Connection/pull/1686) ([ogerly](https://github.com/ogerly))
|
||||||
- Remove repetitive labels from emote button [\#1702](https://github.com/Human-Connection/Human-Connection/pull/1702) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- fix the bug with scrolling post comments into view [\#1701](https://github.com/Human-Connection/Human-Connection/pull/1701) ([vbelolapotkov](https://github.com/vbelolapotkov))
|
|
||||||
- Bump metascraper-description from 5.7.4 to 5.7.5 in /backend [\#1700](https://github.com/Human-Connection/Human-Connection/pull/1700) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump metascraper-logo from 5.7.4 to 5.7.5 in /backend [\#1698](https://github.com/Human-Connection/Human-Connection/pull/1698) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump metascraper-video from 5.7.4 to 5.7.5 in /backend [\#1697](https://github.com/Human-Connection/Human-Connection/pull/1697) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump @babel/core from 7.6.0 to 7.6.2 in /webapp [\#1696](https://github.com/Human-Connection/Human-Connection/pull/1696) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump metascraper-image from 5.7.4 to 5.7.5 in /backend [\#1695](https://github.com/Human-Connection/Human-Connection/pull/1695) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump @babel/preset-env from 7.6.0 to 7.6.2 in /webapp [\#1694](https://github.com/Human-Connection/Human-Connection/pull/1694) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump metascraper-audio from 5.7.4 to 5.7.5 in /backend [\#1693](https://github.com/Human-Connection/Human-Connection/pull/1693) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump metascraper-url from 5.7.4 to 5.7.5 in /backend [\#1692](https://github.com/Human-Connection/Human-Connection/pull/1692) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bugfix create user page - missing submit buttons [\#1690](https://github.com/Human-Connection/Human-Connection/pull/1690) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- Remove sleep icon from comments list [\#1689](https://github.com/Human-Connection/Human-Connection/pull/1689) ([alina-beck](https://github.com/alina-beck))
|
|
||||||
- Configure docker to work with storybook [\#1688](https://github.com/Human-Connection/Human-Connection/pull/1688) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- Add Comment story, add spacing above user info [\#1685](https://github.com/Human-Connection/Human-Connection/pull/1685) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- Fix create account page has no logo, localisation [\#1681](https://github.com/Human-Connection/Human-Connection/pull/1681) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- Fix intermittent backend specs [\#1679](https://github.com/Human-Connection/Human-Connection/pull/1679) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- Improve comments output [\#1678](https://github.com/Human-Connection/Human-Connection/pull/1678) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- Fix intermittent failing test [\#1677](https://github.com/Human-Connection/Human-Connection/pull/1677) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- Bump graphql from 14.5.6 to 14.5.7 in /webapp [\#1676](https://github.com/Human-Connection/Human-Connection/pull/1676) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump graphql from 14.5.6 to 14.5.7 in /backend [\#1675](https://github.com/Human-Connection/Human-Connection/pull/1675) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump cookie-universal-nuxt from 2.0.17 to 2.0.18 in /webapp [\#1674](https://github.com/Human-Connection/Human-Connection/pull/1674) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump @hapi/joi from 16.1.2 to 16.1.4 in /backend [\#1673](https://github.com/Human-Connection/Human-Connection/pull/1673) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump helmet from 3.21.0 to 3.21.1 in /backend [\#1672](https://github.com/Human-Connection/Human-Connection/pull/1672) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump cypress-file-upload from 3.3.3 to 3.3.4 [\#1671](https://github.com/Human-Connection/Human-Connection/pull/1671) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump codecov from 3.6.0 to 3.6.1 [\#1670](https://github.com/Human-Connection/Human-Connection/pull/1670) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Make Human Connection a Progressive Web App [\#1668](https://github.com/Human-Connection/Human-Connection/pull/1668) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- Remove contentExcerpt from comments [\#1667](https://github.com/Human-Connection/Human-Connection/pull/1667) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- Remove follow type enum [\#1660](https://github.com/Human-Connection/Human-Connection/pull/1660) ([vbelolapotkov](https://github.com/vbelolapotkov))
|
|
||||||
- 🍰 Notifications self update and refactoring [\#1658](https://github.com/Human-Connection/Human-Connection/pull/1658) ([Tirokk](https://github.com/Tirokk))
|
|
||||||
- Bump mustache from 3.0.3 to 3.1.0 in /backend [\#1655](https://github.com/Human-Connection/Human-Connection/pull/1655) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump @hapi/joi from 16.1.1 to 16.1.2 in /backend [\#1654](https://github.com/Human-Connection/Human-Connection/pull/1654) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump @nuxtjs/apollo from 4.0.0-rc13 to 4.0.0-rc13.1 in /webapp [\#1653](https://github.com/Human-Connection/Human-Connection/pull/1653) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump codecov from 3.5.0 to 3.6.0 [\#1652](https://github.com/Human-Connection/Human-Connection/pull/1652) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Change your own slug [\#1651](https://github.com/Human-Connection/Human-Connection/pull/1651) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- Fix bug where short comments scrub links [\#1649](https://github.com/Human-Connection/Human-Connection/pull/1649) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- Fix styling issue in comments list [\#1648](https://github.com/Human-Connection/Human-Connection/pull/1648) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- Provider list approval hard cut [\#1647](https://github.com/Human-Connection/Human-Connection/pull/1647) ([ogerly](https://github.com/ogerly))
|
|
||||||
- Point the changelog to Github [\#1646](https://github.com/Human-Connection/Human-Connection/pull/1646) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- Bump eslint-plugin-prettier from 3.1.0 to 3.1.1 in /webapp [\#1643](https://github.com/Human-Connection/Human-Connection/pull/1643) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump eslint-plugin-prettier from 3.1.0 to 3.1.1 in /backend [\#1642](https://github.com/Human-Connection/Human-Connection/pull/1642) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Fix \#1639 - No limits for post length [\#1641](https://github.com/Human-Connection/Human-Connection/pull/1641) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- 1486 make slug more usable [\#1640](https://github.com/Human-Connection/Human-Connection/pull/1640) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- Update de.json [\#1636](https://github.com/Human-Connection/Human-Connection/pull/1636) ([datenbrei](https://github.com/datenbrei))
|
|
||||||
- Exclude broken maintenance-worker docker image [\#1635](https://github.com/Human-Connection/Human-Connection/pull/1635) ([roschaefer](https://github.com/roschaefer))
|
|
||||||
- Fix bug where about must not be empty string [\#1630](https://github.com/Human-Connection/Human-Connection/pull/1630) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- Bump @storybook/addon-a11y from 5.2.0 to 5.2.1 in /webapp [\#1627](https://github.com/Human-Connection/Human-Connection/pull/1627) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump @storybook/addon-actions from 5.2.0 to 5.2.1 in /webapp [\#1625](https://github.com/Human-Connection/Human-Connection/pull/1625) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump @storybook/vue from 5.2.0 to 5.2.1 in /webapp [\#1624](https://github.com/Human-Connection/Human-Connection/pull/1624) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump cross-env from 5.2.1 to 6.0.0 in /backend [\#1623](https://github.com/Human-Connection/Human-Connection/pull/1623) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump @hapi/joi from 16.0.1 to 16.1.1 in /backend [\#1622](https://github.com/Human-Connection/Human-Connection/pull/1622) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Bump cross-env from 5.2.1 to 6.0.0 [\#1621](https://github.com/Human-Connection/Human-Connection/pull/1621) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- 1612 refactor moderator spec [\#1620](https://github.com/Human-Connection/Human-Connection/pull/1620) ([aonomike](https://github.com/aonomike))
|
|
||||||
- Fix disappearing embeds on comments [\#1618](https://github.com/Human-Connection/Human-Connection/pull/1618) ([mattwr18](https://github.com/mattwr18))
|
|
||||||
- links\_to\_imprint\_and\_privacy\_policy\_changed\_to\_human-connection.org [\#1615](https://github.com/Human-Connection/Human-Connection/pull/1615) ([ogerly](https://github.com/ogerly))
|
|
||||||
- Bump metascraper-author from 5.6.6 to 5.7.4 in /backend [\#1610](https://github.com/Human-Connection/Human-Connection/pull/1610) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
|
|
||||||
- Configure emails [\#1599](https://github.com/Human-Connection/Human-Connection/pull/1599) ([alina-beck](https://github.com/alina-beck))
|
|
||||||
- Improve follow/ufollow mutation [\#1596](https://github.com/Human-Connection/Human-Connection/pull/1596) ([vbelolapotkov](https://github.com/vbelolapotkov))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -50,6 +50,8 @@ Join our friendly open-source community on [Discord](https://discordapp.com/invi
|
|||||||
Just introduce yourself at `#introduce-yourself` and mention `@@Mentor` to get you onboard :neckbeard:
|
Just introduce yourself at `#introduce-yourself` and mention `@@Mentor` to get you onboard :neckbeard:
|
||||||
Check out the [contribution guideline](./CONTRIBUTING.md), too!
|
Check out the [contribution guideline](./CONTRIBUTING.md), too!
|
||||||
|
|
||||||
|
[](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/0)[](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/1)[](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/2)[](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/3)[](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/4)[](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/5)[](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/6)[](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/7)
|
||||||
|
|
||||||
|
|
||||||
## Attributions
|
## Attributions
|
||||||
|
|
||||||
|
|||||||
@ -17,3 +17,4 @@ PRIVATE_KEY_PASSPHRASE="a7dsf78sadg87ad87sfagsadg78"
|
|||||||
|
|
||||||
SENTRY_DSN_BACKEND=
|
SENTRY_DSN_BACKEND=
|
||||||
COMMIT=
|
COMMIT=
|
||||||
|
PUBLIC_REGISTRATION=false
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:12.10.0-alpine as base
|
FROM node:12.12.0-alpine as base
|
||||||
LABEL Description="Backend of the Social Network Human-Connection.org" Vendor="Human Connection gGmbH" Version="0.0.1" Maintainer="Human Connection gGmbH (developer@human-connection.org)"
|
LABEL Description="Backend of the Social Network Human-Connection.org" Vendor="Human Connection gGmbH" Version="0.0.1" Maintainer="Human Connection gGmbH (developer@human-connection.org)"
|
||||||
|
|
||||||
EXPOSE 4000
|
EXPOSE 4000
|
||||||
@ -24,4 +24,5 @@ FROM base as production
|
|||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
COPY --from=build-and-test /nitro-backend/dist ./dist
|
COPY --from=build-and-test /nitro-backend/dist ./dist
|
||||||
COPY ./public/img/ ./public/img/
|
COPY ./public/img/ ./public/img/
|
||||||
|
COPY ./public/providers.json ./public/providers.json
|
||||||
RUN yarn install --production=true --frozen-lockfile --non-interactive --no-cache
|
RUN yarn install --production=true --frozen-lockfile --non-interactive --no-cache
|
||||||
|
|||||||
@ -41,22 +41,22 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hapi/joi": "^16.1.4",
|
"@hapi/joi": "^16.1.7",
|
||||||
"@sentry/node": "^5.6.2",
|
"@sentry/node": "^5.7.0",
|
||||||
"apollo-cache-inmemory": "~1.6.3",
|
"apollo-cache-inmemory": "~1.6.3",
|
||||||
"apollo-client": "~2.6.4",
|
"apollo-client": "~2.6.4",
|
||||||
"apollo-link-context": "~1.0.19",
|
"apollo-link-context": "~1.0.19",
|
||||||
"apollo-link-http": "~1.5.16",
|
"apollo-link-http": "~1.5.16",
|
||||||
"apollo-server": "~2.9.4",
|
"apollo-server": "~2.9.6",
|
||||||
"apollo-server-express": "^2.9.4",
|
"apollo-server-express": "^2.9.6",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
"bcryptjs": "~2.4.3",
|
"bcryptjs": "~2.4.3",
|
||||||
"cheerio": "~1.0.0-rc.3",
|
"cheerio": "~1.0.0-rc.3",
|
||||||
"cors": "~2.8.5",
|
"cors": "~2.8.5",
|
||||||
"cross-env": "~6.0.2",
|
"cross-env": "~6.0.3",
|
||||||
"date-fns": "2.4.1",
|
"date-fns": "2.5.0",
|
||||||
"debug": "~4.1.1",
|
"debug": "~4.1.1",
|
||||||
"dotenv": "~8.1.0",
|
"dotenv": "~8.2.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"faker": "Marak/faker.js#master",
|
"faker": "Marak/faker.js#master",
|
||||||
"graphql": "^14.5.8",
|
"graphql": "^14.5.8",
|
||||||
@ -93,7 +93,7 @@
|
|||||||
"neo4j-graphql-js": "^2.7.2",
|
"neo4j-graphql-js": "^2.7.2",
|
||||||
"neode": "^0.3.3",
|
"neode": "^0.3.3",
|
||||||
"node-fetch": "~2.6.0",
|
"node-fetch": "~2.6.0",
|
||||||
"nodemailer": "^6.3.0",
|
"nodemailer": "^6.3.1",
|
||||||
"nodemailer-html-to-text": "^3.1.0",
|
"nodemailer-html-to-text": "^3.1.0",
|
||||||
"npm-run-all": "~4.1.5",
|
"npm-run-all": "~4.1.5",
|
||||||
"request": "~2.88.0",
|
"request": "~2.88.0",
|
||||||
@ -105,30 +105,30 @@
|
|||||||
"xregexp": "^4.2.4"
|
"xregexp": "^4.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "~7.6.2",
|
"@babel/cli": "~7.6.4",
|
||||||
"@babel/core": "~7.6.2",
|
"@babel/core": "~7.6.4",
|
||||||
"@babel/node": "~7.6.2",
|
"@babel/node": "~7.6.3",
|
||||||
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
|
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
|
||||||
"@babel/preset-env": "~7.6.2",
|
"@babel/preset-env": "~7.6.3",
|
||||||
"@babel/register": "~7.6.2",
|
"@babel/register": "~7.6.2",
|
||||||
"apollo-server-testing": "~2.9.4",
|
"apollo-server-testing": "~2.9.6",
|
||||||
"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": "~6.0.2",
|
||||||
"eslint": "~6.5.1",
|
"eslint": "~6.5.1",
|
||||||
"eslint-config-prettier": "~6.3.0",
|
"eslint-config-prettier": "~6.4.0",
|
||||||
"eslint-config-standard": "~14.1.0",
|
"eslint-config-standard": "~14.1.0",
|
||||||
"eslint-plugin-import": "~2.18.2",
|
"eslint-plugin-import": "~2.18.2",
|
||||||
"eslint-plugin-jest": "~22.17.0",
|
"eslint-plugin-jest": "~22.19.0",
|
||||||
"eslint-plugin-node": "~10.0.0",
|
"eslint-plugin-node": "~10.0.0",
|
||||||
"eslint-plugin-prettier": "~3.1.1",
|
"eslint-plugin-prettier": "~3.1.1",
|
||||||
"eslint-plugin-promise": "~4.2.1",
|
"eslint-plugin-promise": "~4.2.1",
|
||||||
"eslint-plugin-standard": "~4.0.1",
|
"eslint-plugin-standard": "~4.0.1",
|
||||||
"graphql-request": "~1.8.2",
|
"graphql-request": "~1.8.2",
|
||||||
"jest": "~24.9.0",
|
"jest": "~24.9.0",
|
||||||
"nodemon": "~1.19.3",
|
"nodemon": "~1.19.4",
|
||||||
"prettier": "~1.18.2",
|
"prettier": "~1.18.2",
|
||||||
"supertest": "~4.0.2"
|
"supertest": "~4.0.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,12 @@ const {
|
|||||||
GRAPHQL_URI = 'http://localhost:4000',
|
GRAPHQL_URI = 'http://localhost:4000',
|
||||||
} = process.env
|
} = process.env
|
||||||
|
|
||||||
export const requiredConfigs = { MAPBOX_TOKEN, JWT_SECRET, PRIVATE_KEY_PASSPHRASE }
|
export const requiredConfigs = {
|
||||||
|
MAPBOX_TOKEN,
|
||||||
|
JWT_SECRET,
|
||||||
|
PRIVATE_KEY_PASSPHRASE,
|
||||||
|
}
|
||||||
|
|
||||||
export const smtpConfigs = {
|
export const smtpConfigs = {
|
||||||
SMTP_HOST,
|
SMTP_HOST,
|
||||||
SMTP_PORT,
|
SMTP_PORT,
|
||||||
@ -30,7 +35,12 @@ export const smtpConfigs = {
|
|||||||
SMTP_PASSWORD,
|
SMTP_PASSWORD,
|
||||||
}
|
}
|
||||||
export const neo4jConfigs = { NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD }
|
export const neo4jConfigs = { NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD }
|
||||||
export const serverConfigs = { GRAPHQL_PORT, CLIENT_URI, GRAPHQL_URI }
|
export const serverConfigs = {
|
||||||
|
GRAPHQL_PORT,
|
||||||
|
CLIENT_URI,
|
||||||
|
GRAPHQL_URI,
|
||||||
|
PUBLIC_REGISTRATION: process.env.PUBLIC_REGISTRATION === 'true',
|
||||||
|
}
|
||||||
|
|
||||||
export const developmentConfigs = {
|
export const developmentConfigs = {
|
||||||
DEBUG: process.env.NODE_ENV !== 'production' && process.env.DEBUG,
|
DEBUG: process.env.NODE_ENV !== 'production' && process.env.DEBUG,
|
||||||
|
|||||||
@ -14,6 +14,7 @@ export default async (driver, authorizationHeader) => {
|
|||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
const query = `
|
const query = `
|
||||||
MATCH (user:User {id: $id, deleted: false, disabled: false })
|
MATCH (user:User {id: $id, deleted: false, disabled: false })
|
||||||
|
SET user.lastActiveAt = toString(datetime())
|
||||||
RETURN user {.id, .slug, .name, .avatar, .email, .role, .disabled, .actorId}
|
RETURN user {.id, .slug, .name, .avatar, .email, .role, .disabled, .actorId}
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import Factory from '../seed/factories/index'
|
import Factory from '../seed/factories/index'
|
||||||
import { getDriver } from '../bootstrap/neo4j'
|
import { getDriver, neode as getNeode } from '../bootstrap/neo4j'
|
||||||
import decode from './decode'
|
import decode from './decode'
|
||||||
|
|
||||||
const factory = Factory()
|
const factory = Factory()
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
|
const neode = getNeode()
|
||||||
|
|
||||||
// here is the decoded JWT token:
|
// here is the decoded JWT token:
|
||||||
// {
|
// {
|
||||||
@ -85,6 +86,33 @@ describe('decode', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('sets `lastActiveAt`', async () => {
|
||||||
|
let user = await neode.first('User', { id: 'u3' })
|
||||||
|
await expect(user.toJson()).resolves.not.toHaveProperty('lastActiveAt')
|
||||||
|
await decode(driver, authorizationHeader)
|
||||||
|
user = await neode.first('User', { id: 'u3' })
|
||||||
|
await expect(user.toJson()).resolves.toMatchObject({
|
||||||
|
lastActiveAt: expect.any(String),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('updates `lastActiveAt` for every authenticated request', async () => {
|
||||||
|
let user = await neode.first('User', { id: 'u3' })
|
||||||
|
await user.update({
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
lastActiveAt: '2019-10-03T23:33:08.598Z',
|
||||||
|
})
|
||||||
|
await expect(user.toJson()).resolves.toMatchObject({
|
||||||
|
lastActiveAt: '2019-10-03T23:33:08.598Z',
|
||||||
|
})
|
||||||
|
await decode(driver, authorizationHeader)
|
||||||
|
user = await neode.first('User', { id: 'u3' })
|
||||||
|
await expect(user.toJson()).resolves.toMatchObject({
|
||||||
|
// should be a different time by now ;)
|
||||||
|
lastActiveAt: expect.not.stringContaining('2019-10-03T23:33'),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('but user is deleted', () => {
|
describe('but user is deleted', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await user.update({ updatedAt: new Date().toISOString(), deleted: true })
|
await user.update({ updatedAt: new Date().toISOString(), deleted: true })
|
||||||
@ -92,6 +120,7 @@ describe('decode', () => {
|
|||||||
|
|
||||||
it('returns null', returnsNull)
|
it('returns null', returnsNull)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('but user is disabled', () => {
|
describe('but user is disabled', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await user.update({ updatedAt: new Date().toISOString(), disabled: true })
|
await user.update({ updatedAt: new Date().toISOString(), disabled: true })
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export const signupTemplate = ({ email, nonce }) => {
|
|||||||
subject,
|
subject,
|
||||||
html: mustache.render(
|
html: mustache.render(
|
||||||
templates.layout,
|
templates.layout,
|
||||||
{ actionUrl, supportUrl, subject },
|
{ actionUrl, nonce, supportUrl, subject },
|
||||||
{ content: templates.signup },
|
{ content: templates.signup },
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
<!-- Email Body German : BEGIN -->
|
<!-- Email Body German : BEGIN -->
|
||||||
<table class="email-german" align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
<table class="email-german" align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
||||||
style="margin: auto;">
|
style="margin: auto;">
|
||||||
<tr>
|
|
||||||
<td style="padding: 20px 0; text-align: center">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Hero Image, Flush : BEGIN -->
|
<!-- Hero Image, Flush : BEGIN -->
|
||||||
<tr>
|
<tr>
|
||||||
@ -61,7 +57,7 @@
|
|||||||
<td
|
<td
|
||||||
style="padding: 20px; padding-bottom: 0; font-family: Lato, sans-serif; font-size: 16px; line-height: 22px; color: #555555;">
|
style="padding: 20px; padding-bottom: 0; font-family: Lato, sans-serif; font-size: 16px; line-height: 22px; color: #555555;">
|
||||||
<p style="margin: 0;">Falls Du deine E-Mail Adresse doch nicht ändern möchtest, kannst du diese Nachricht
|
<p style="margin: 0;">Falls Du deine E-Mail Adresse doch nicht ändern möchtest, kannst du diese Nachricht
|
||||||
einfach ignorieren. Mlde Dich gerne <a href="{{{ supportUrl }}}" style="color: #17b53e;">bei
|
einfach ignorieren. Melde Dich gerne <a href="{{{ supportUrl }}}" style="color: #17b53e;">bei
|
||||||
unserem Support Team</a>, wenn du noch Fragen hast!</p>
|
unserem Support Team</a>, wenn du noch Fragen hast!</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -142,60 +142,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- LANGUAGE TOGGLE -->
|
|
||||||
<style>
|
|
||||||
.toggle+label {
|
|
||||||
display: inline-block;
|
|
||||||
height: 40px;
|
|
||||||
padding: 0 12px;
|
|
||||||
margin-top: 40px;
|
|
||||||
line-height: 38px;
|
|
||||||
font-family: Lato, sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
border: 1px solid #cbc7d1;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle+label:hover {
|
|
||||||
background-color: #bee876;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle:checked+label {
|
|
||||||
background-color: #19c243;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-english+label {
|
|
||||||
border-bottom-right-radius: 50px;
|
|
||||||
border-top-right-radius: 50px;
|
|
||||||
border-left: none;
|
|
||||||
margin-left: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-german+label {
|
|
||||||
border-bottom-left-radius: 50px;
|
|
||||||
border-top-left-radius: 50px;
|
|
||||||
border-right: none;
|
|
||||||
margin-right: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-german:checked~table.email-german {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-german:checked~table.email-english {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-english:checked~table.email-english {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-english:checked~table.email-german {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f5f4f6;">
|
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f5f4f6;">
|
||||||
@ -213,13 +159,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
|
||||||
<!-- LANGUAGE TOGGLE -->
|
<p style="color:#19c243; font-style: italic; font-family: Lato, sans-serif; font-size: 16px; padding-top: 20px;">English version below!</p>
|
||||||
<input type="radio" name="language" class="toggle toggle-german" style="display: none;" id="toggle-german"
|
|
||||||
checked="checked">
|
|
||||||
<label for="toggle-german">Deutsch</label>
|
|
||||||
<input type="radio" name="language" class="toggle toggle-english" style="display:none;" id="toggle-english">
|
|
||||||
<label for="toggle-english">English</label>
|
|
||||||
<p style="margin: 0;"></p>
|
|
||||||
|
|
||||||
{{> content}}
|
{{> content}}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
<!-- Email Body German : BEGIN -->
|
<!-- Email Body German : BEGIN -->
|
||||||
<table class="email-german" align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
<table class="email-german" align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
||||||
style="margin: auto;">
|
style="margin: auto;">
|
||||||
<tr>
|
|
||||||
<td style="padding: 20px 0; text-align: center">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Hero Image, Flush : BEGIN -->
|
<!-- Hero Image, Flush : BEGIN -->
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
<!-- Email Body German : BEGIN -->
|
<!-- Email Body German : BEGIN -->
|
||||||
<table class="email-german" align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
<table class="email-german" align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
||||||
style="margin: auto;">
|
style="margin: auto;">
|
||||||
<tr>
|
|
||||||
<td style="padding: 20px 0; text-align: center">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Hero Image, Flush : BEGIN -->
|
<!-- Hero Image, Flush : BEGIN -->
|
||||||
<tr>
|
<tr>
|
||||||
@ -64,7 +60,9 @@
|
|||||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 20px; font-family: Lato, sans-serif; font-size: 16px; line-height: 22px; color: #555555;">
|
<td style="padding: 20px; font-family: Lato, sans-serif; font-size: 16px; line-height: 22px; color: #555555;">
|
||||||
<p style="margin: 0;">Falls Du Dich nicht selbst bei <a href="https://human-connection.org"
|
<p style="margin: 0;">Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in Dein Browserfenster kopieren: <span style="color: #17b53e;">{{{ nonce }}}</span></p>
|
||||||
|
<p style="margin: 0;">Das funktioniert allerdings nur, wenn du Dich über unsere Website registriert hast.</p>
|
||||||
|
<p style="margin: 0; margin-top: 10px;">Falls Du Dich nicht selbst bei <a href="https://human-connection.org"
|
||||||
style="color: #17b53e;">Human Connection</a> angemeldet hast, schau doch mal vorbei!
|
style="color: #17b53e;">Human Connection</a> angemeldet hast, schau doch mal vorbei!
|
||||||
Wir sind ein gemeinnütziges Aktionsnetzwerk – von Menschen für Menschen.</p>
|
Wir sind ein gemeinnütziges Aktionsnetzwerk – von Menschen für Menschen.</p>
|
||||||
<p style="margin: 0; margin-top: 10px;">PS: Wenn Du keinen Account bei uns möchtest, kannst Du diese
|
<p style="margin: 0; margin-top: 10px;">PS: Wenn Du keinen Account bei uns möchtest, kannst Du diese
|
||||||
@ -173,7 +171,9 @@
|
|||||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 20px; font-family: Lato, sans-serif; font-size: 16px; line-height: 22px; color: #555555;">
|
<td style="padding: 20px; font-family: Lato, sans-serif; font-size: 16px; line-height: 22px; color: #555555;">
|
||||||
<p style="margin: 0;">If you didn't sign up for <a href="https://human-connection.org"
|
<p style="margin: 0;">If the above button doesn't work, you can also copy the following code into your browser window: <span style="color: #17b53e;">{{{ nonce }}}</span></p>
|
||||||
|
<p style="margin: 0;">However, this only works if you have registered through our website.</p>
|
||||||
|
<p style="margin: 0; margin-top: 10px;">If you didn't sign up for <a href="https://human-connection.org"
|
||||||
style="color: #17b53e;">Human Connection</a> we recommend you to check it out!
|
style="color: #17b53e;">Human Connection</a> we recommend you to check it out!
|
||||||
It's a social network from people for people who want to connect and change the world together.</p>
|
It's a social network from people for people who want to connect and change the world together.</p>
|
||||||
<p style="margin: 0; margin-top: 10px;">PS: If you ignore this e-mail we will not create an account
|
<p style="margin: 0; margin-top: 10px;">PS: If you ignore this e-mail we will not create an account
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
<!-- Email Body German : BEGIN -->
|
<!-- Email Body German : BEGIN -->
|
||||||
<table class="email-german" align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
<table class="email-german" align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
||||||
style="margin: auto;">
|
style="margin: auto;">
|
||||||
<tr>
|
|
||||||
<td style="padding: 20px 0; text-align: center">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- Hero Image, Flush : BEGIN -->
|
<!-- Hero Image, Flush : BEGIN -->
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@ -111,6 +111,8 @@ const noEmailFilter = rule({
|
|||||||
return !('email' in args)
|
return !('email' in args)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const publicRegistration = rule()(() => !!CONFIG.PUBLIC_REGISTRATION)
|
||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
const permissions = shield(
|
const permissions = shield(
|
||||||
{
|
{
|
||||||
@ -120,7 +122,7 @@ const permissions = shield(
|
|||||||
embed: allow,
|
embed: allow,
|
||||||
Category: allow,
|
Category: allow,
|
||||||
Tag: allow,
|
Tag: allow,
|
||||||
Report: isModerator,
|
reports: isModerator,
|
||||||
statistics: allow,
|
statistics: allow,
|
||||||
currentUser: allow,
|
currentUser: allow,
|
||||||
Post: or(onlyEnabledContent, isModerator),
|
Post: or(onlyEnabledContent, isModerator),
|
||||||
@ -137,7 +139,7 @@ const permissions = shield(
|
|||||||
'*': deny,
|
'*': deny,
|
||||||
login: allow,
|
login: allow,
|
||||||
SignupByInvitation: allow,
|
SignupByInvitation: allow,
|
||||||
Signup: isAdmin,
|
Signup: or(publicRegistration, isAdmin),
|
||||||
SignupVerification: allow,
|
SignupVerification: allow,
|
||||||
CreateInvitationCode: and(isAuthenticated, or(not(invitationLimitReached), isAdmin)),
|
CreateInvitationCode: and(isAuthenticated, or(not(invitationLimitReached), isAdmin)),
|
||||||
UpdateUser: onlyYourself,
|
UpdateUser: onlyYourself,
|
||||||
@ -174,7 +176,7 @@ const permissions = shield(
|
|||||||
VerifyEmailAddress: isAuthenticated,
|
VerifyEmailAddress: isAuthenticated,
|
||||||
},
|
},
|
||||||
User: {
|
User: {
|
||||||
email: isMyOwn,
|
email: or(isMyOwn, isAdmin),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,22 +1,63 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { createTestClient } from 'apollo-server-testing'
|
||||||
|
import createServer from '../server'
|
||||||
import Factory from '../seed/factories'
|
import Factory from '../seed/factories'
|
||||||
import { host, login } from '../jest/helpers'
|
import { gql } from '../jest/helpers'
|
||||||
|
import { getDriver, neode as getNeode } from '../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
const factory = Factory()
|
||||||
|
const instance = getNeode()
|
||||||
|
const driver = getDriver()
|
||||||
|
|
||||||
|
let query, authenticatedUser, owner, anotherRegularUser, administrator, variables, moderator
|
||||||
|
|
||||||
|
const userQuery = gql`
|
||||||
|
query($name: String) {
|
||||||
|
User(name: $name) {
|
||||||
|
email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
describe('authorization', () => {
|
describe('authorization', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await factory.cleanDatabase()
|
||||||
|
const { server } = createServer({
|
||||||
|
context: () => ({
|
||||||
|
driver,
|
||||||
|
instance,
|
||||||
|
user: authenticatedUser,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
query = createTestClient(server).query
|
||||||
|
})
|
||||||
|
|
||||||
describe('given two existing users', () => {
|
describe('given two existing users', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await factory.create('User', {
|
;[owner, anotherRegularUser, administrator, moderator] = await Promise.all([
|
||||||
email: 'owner@example.org',
|
factory.create('User', {
|
||||||
name: 'Owner',
|
email: 'owner@example.org',
|
||||||
password: 'iamtheowner',
|
name: 'Owner',
|
||||||
})
|
password: 'iamtheowner',
|
||||||
await factory.create('User', {
|
}),
|
||||||
email: 'someone@example.org',
|
factory.create('User', {
|
||||||
name: 'Someone else',
|
email: 'another.regular.user@example.org',
|
||||||
password: 'else',
|
name: 'Another Regular User',
|
||||||
})
|
password: 'else',
|
||||||
|
}),
|
||||||
|
factory.create('User', {
|
||||||
|
email: 'admin@example.org',
|
||||||
|
name: 'Admin',
|
||||||
|
password: 'admin',
|
||||||
|
role: 'admin',
|
||||||
|
}),
|
||||||
|
factory.create('User', {
|
||||||
|
email: 'moderator@example.org',
|
||||||
|
name: 'Moderator',
|
||||||
|
password: 'moderator',
|
||||||
|
role: 'moderator',
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
variables = {}
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@ -24,66 +65,77 @@ describe('authorization', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('access email address', () => {
|
describe('access email address', () => {
|
||||||
let headers = {}
|
describe('unauthenticated', () => {
|
||||||
let loginCredentials = null
|
|
||||||
const action = async () => {
|
|
||||||
if (loginCredentials) {
|
|
||||||
headers = await login(loginCredentials)
|
|
||||||
}
|
|
||||||
const graphQLClient = new GraphQLClient(host, { headers })
|
|
||||||
return graphQLClient.request('{User(name: "Owner") { email } }')
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('not logged in', () => {
|
|
||||||
it('rejects', async () => {
|
|
||||||
await expect(action()).rejects.toThrow('Not Authorised!')
|
|
||||||
})
|
|
||||||
|
|
||||||
it("does not expose the owner's email address", async () => {
|
|
||||||
let response = {}
|
|
||||||
try {
|
|
||||||
await action()
|
|
||||||
} catch (error) {
|
|
||||||
response = error.response.data
|
|
||||||
} finally {
|
|
||||||
expect(response).toEqual({ User: [null] })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('as owner', () => {
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
loginCredentials = {
|
authenticatedUser = null
|
||||||
email: 'owner@example.org',
|
|
||||||
password: 'iamtheowner',
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
it("throws an error and does not expose the owner's email address", async () => {
|
||||||
it("exposes the owner's email address", async () => {
|
await expect(
|
||||||
await expect(action()).resolves.toEqual({ User: [{ email: 'owner@example.org' }] })
|
query({ query: userQuery, variables: { name: 'Owner' } }),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
data: { User: [null] },
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('authenticated as another user', () => {
|
describe('authenticated', () => {
|
||||||
beforeEach(async () => {
|
describe('as the owner', () => {
|
||||||
loginCredentials = {
|
beforeEach(async () => {
|
||||||
email: 'someone@example.org',
|
authenticatedUser = await owner.toJson()
|
||||||
password: 'else',
|
})
|
||||||
}
|
|
||||||
|
it("exposes the owner's email address", async () => {
|
||||||
|
variables = { name: 'Owner' }
|
||||||
|
await expect(query({ query: userQuery, variables })).resolves.toMatchObject({
|
||||||
|
data: { User: [{ email: 'owner@example.org' }] },
|
||||||
|
errors: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rejects', async () => {
|
describe('as another regular user', () => {
|
||||||
await expect(action()).rejects.toThrow('Not Authorised!')
|
beforeEach(async () => {
|
||||||
|
authenticatedUser = await anotherRegularUser.toJson()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("throws an error and does not expose the owner's email address", async () => {
|
||||||
|
await expect(
|
||||||
|
query({ query: userQuery, variables: { name: 'Owner' } }),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
data: { User: [null] },
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("does not expose the owner's email address", async () => {
|
describe('as a moderator', () => {
|
||||||
let response
|
beforeEach(async () => {
|
||||||
try {
|
authenticatedUser = await moderator.toJson()
|
||||||
await action()
|
})
|
||||||
} catch (error) {
|
|
||||||
response = error.response.data
|
it("throws an error and does not expose the owner's email address", async () => {
|
||||||
}
|
await expect(
|
||||||
expect(response).toEqual({ User: [null] })
|
query({ query: userQuery, variables: { name: 'Owner' } }),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
data: { User: [null] },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('administrator', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
authenticatedUser = await administrator.toJson()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("exposes the owner's email address", async () => {
|
||||||
|
variables = { name: 'Owner' }
|
||||||
|
await expect(query({ query: userQuery, variables })).resolves.toMatchObject({
|
||||||
|
data: { User: [{ email: 'owner@example.org' }] },
|
||||||
|
errors: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -57,11 +57,37 @@ const validateUpdatePost = async (resolve, root, args, context, info) => {
|
|||||||
return validatePost(resolve, root, args, context, info)
|
return validatePost(resolve, root, args, context, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const validateReport = async (resolve, root, args, context, info) => {
|
||||||
|
const { resourceId } = args
|
||||||
|
const { user, driver } = context
|
||||||
|
if (resourceId === user.id) throw new Error('You cannot report yourself!')
|
||||||
|
const session = driver.session()
|
||||||
|
const reportQueryRes = await session.run(
|
||||||
|
`
|
||||||
|
MATCH (:User {id:$submitterId})-[:REPORTED]->(resource {id:$resourceId})
|
||||||
|
RETURN labels(resource)[0] as label
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
resourceId,
|
||||||
|
submitterId: user.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
const [existingReportedResource] = reportQueryRes.records.map(record => {
|
||||||
|
return {
|
||||||
|
label: record.get('label'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (existingReportedResource) throw new Error(`${existingReportedResource.label}`)
|
||||||
|
return resolve(root, args, context, info)
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Mutation: {
|
Mutation: {
|
||||||
CreateComment: validateCommentCreation,
|
CreateComment: validateCommentCreation,
|
||||||
UpdateComment: validateUpdateComment,
|
UpdateComment: validateUpdateComment,
|
||||||
CreatePost: validatePost,
|
CreatePost: validatePost,
|
||||||
UpdatePost: validateUpdatePost,
|
UpdatePost: validateUpdatePost,
|
||||||
|
report: validateReport,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,7 +85,7 @@ function clean(dirty) {
|
|||||||
return dirty
|
return dirty
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields = ['content', 'contentExcerpt']
|
const fields = ['content', 'contentExcerpt', 'reasonDescription']
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Mutation: async (resolve, root, args, context, info) => {
|
Mutation: async (resolve, root, args, context, info) => {
|
||||||
|
|||||||
@ -55,6 +55,7 @@ module.exports = {
|
|||||||
direction: 'in',
|
direction: 'in',
|
||||||
},
|
},
|
||||||
invitedBy: { type: 'relationship', relationship: 'INVITED', target: 'User', direction: 'in' },
|
invitedBy: { type: 'relationship', relationship: 'INVITED', target: 'User', direction: 'in' },
|
||||||
|
lastActiveAt: { type: 'string', isoDate: true },
|
||||||
createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() },
|
createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() },
|
||||||
updatedAt: {
|
updatedAt: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
@ -113,4 +114,8 @@ module.exports = {
|
|||||||
target: 'Location',
|
target: 'Location',
|
||||||
direction: 'out',
|
direction: 'out',
|
||||||
},
|
},
|
||||||
};
|
allowEmbedIframes: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ export default applyScalars(
|
|||||||
'Location',
|
'Location',
|
||||||
'SocialMedia',
|
'SocialMedia',
|
||||||
'NOTIFIED',
|
'NOTIFIED',
|
||||||
|
'REPORTED',
|
||||||
],
|
],
|
||||||
// add 'User' here as soon as possible
|
// add 'User' here as soon as possible
|
||||||
},
|
},
|
||||||
@ -35,7 +36,6 @@ export default applyScalars(
|
|||||||
'Notfication',
|
'Notfication',
|
||||||
'Post',
|
'Post',
|
||||||
'Comment',
|
'Comment',
|
||||||
'Report',
|
|
||||||
'Statistics',
|
'Statistics',
|
||||||
'LoggedInUser',
|
'LoggedInUser',
|
||||||
'Location',
|
'Location',
|
||||||
@ -43,6 +43,7 @@ export default applyScalars(
|
|||||||
'User',
|
'User',
|
||||||
'EMOTED',
|
'EMOTED',
|
||||||
'NOTIFIED',
|
'NOTIFIED',
|
||||||
|
'REPORTED',
|
||||||
],
|
],
|
||||||
// add 'User' here as soon as possible
|
// add 'User' here as soon as possible
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,7 +2,11 @@ import fs from 'fs'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import minimatch from 'minimatch'
|
import minimatch from 'minimatch'
|
||||||
|
|
||||||
let oEmbedProvidersFile = fs.readFileSync(path.join(__dirname, './providers.json'), 'utf8')
|
let oEmbedProvidersFile = fs.readFileSync(
|
||||||
|
path.join(__dirname, '../../../../public/providers.json'),
|
||||||
|
'utf8',
|
||||||
|
)
|
||||||
|
|
||||||
// some providers allow a format parameter
|
// some providers allow a format parameter
|
||||||
// we need JSON
|
// we need JSON
|
||||||
oEmbedProvidersFile = oEmbedProvidersFile.replace(/\{format\}/g, 'json')
|
oEmbedProvidersFile = oEmbedProvidersFile.replace(/\{format\}/g, 'json')
|
||||||
|
|||||||
@ -18,7 +18,6 @@ export default async function fileUpload(params, { file, url }, uploadCallback =
|
|||||||
const fileLocation = `/uploads/${Date.now()}-${slug(name)}`
|
const fileLocation = `/uploads/${Date.now()}-${slug(name)}`
|
||||||
await uploadCallback({ createReadStream, fileLocation })
|
await uploadCallback({ createReadStream, fileLocation })
|
||||||
delete params[file]
|
delete params[file]
|
||||||
|
|
||||||
params[url] = fileLocation
|
params[url] = fileLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,83 +1,125 @@
|
|||||||
import uuid from 'uuid/v4'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Mutation: {
|
Mutation: {
|
||||||
report: async (parent, { id, description }, { driver, req, user }, resolveInfo) => {
|
report: async (_parent, params, context, _resolveInfo) => {
|
||||||
const reportId = uuid()
|
let createdRelationshipWithNestedAttributes
|
||||||
|
const { resourceId, reasonCategory, reasonDescription } = params
|
||||||
|
const { driver, user } = context
|
||||||
const session = driver.session()
|
const session = driver.session()
|
||||||
const reportData = {
|
const writeTxResultPromise = session.writeTransaction(async txc => {
|
||||||
id: reportId,
|
const reportRelationshipTransactionResponse = await txc.run(
|
||||||
createdAt: new Date().toISOString(),
|
`
|
||||||
description: description,
|
MATCH (submitter:User {id: $submitterId})
|
||||||
}
|
MATCH (resource {id: $resourceId})
|
||||||
|
WHERE resource:User OR resource:Comment OR resource:Post
|
||||||
const reportQueryRes = await session.run(
|
CREATE (resource)<-[report:REPORTED {createdAt: $createdAt, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription}]-(submitter)
|
||||||
`
|
RETURN report, submitter, resource, labels(resource)[0] as type
|
||||||
match (u:User {id:$submitterId}) -[:REPORTED]->(report)-[:REPORTED]-> (resource {id: $resourceId})
|
`,
|
||||||
return labels(resource)[0] as label
|
{
|
||||||
`,
|
resourceId,
|
||||||
{
|
submitterId: user.id,
|
||||||
resourceId: id,
|
createdAt: new Date().toISOString(),
|
||||||
submitterId: user.id,
|
reasonCategory,
|
||||||
},
|
reasonDescription,
|
||||||
)
|
},
|
||||||
const [rep] = reportQueryRes.records.map(record => {
|
)
|
||||||
return {
|
return reportRelationshipTransactionResponse.records.map(record => ({
|
||||||
label: record.get('label'),
|
report: record.get('report'),
|
||||||
}
|
submitter: record.get('submitter'),
|
||||||
|
resource: record.get('resource').properties,
|
||||||
|
type: record.get('type'),
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
try {
|
||||||
if (rep) {
|
const txResult = await writeTxResultPromise
|
||||||
throw new Error(rep.label)
|
if (!txResult[0]) return null
|
||||||
}
|
const { report, submitter, resource, type } = txResult[0]
|
||||||
const res = await session.run(
|
createdRelationshipWithNestedAttributes = {
|
||||||
`
|
...report.properties,
|
||||||
MATCH (submitter:User {id: $userId})
|
post: null,
|
||||||
MATCH (resource {id: $resourceId})
|
comment: null,
|
||||||
WHERE resource:User OR resource:Comment OR resource:Post
|
user: null,
|
||||||
MERGE (report:Report {id: {reportData}.id })
|
submitter: submitter.properties,
|
||||||
MERGE (resource)<-[:REPORTED]-(report)
|
type,
|
||||||
MERGE (report)<-[:REPORTED]-(submitter)
|
|
||||||
RETURN report, submitter, resource, labels(resource)[0] as type
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
resourceId: id,
|
|
||||||
userId: user.id,
|
|
||||||
reportData,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
session.close()
|
|
||||||
|
|
||||||
const [dbResponse] = res.records.map(r => {
|
|
||||||
return {
|
|
||||||
report: r.get('report'),
|
|
||||||
submitter: r.get('submitter'),
|
|
||||||
resource: r.get('resource'),
|
|
||||||
type: r.get('type'),
|
|
||||||
}
|
}
|
||||||
})
|
switch (type) {
|
||||||
if (!dbResponse) return null
|
case 'Post':
|
||||||
const { report, submitter, resource, type } = dbResponse
|
createdRelationshipWithNestedAttributes.post = resource
|
||||||
|
break
|
||||||
const response = {
|
case 'Comment':
|
||||||
...report.properties,
|
createdRelationshipWithNestedAttributes.comment = resource
|
||||||
post: null,
|
break
|
||||||
comment: null,
|
case 'User':
|
||||||
user: null,
|
createdRelationshipWithNestedAttributes.user = resource
|
||||||
submitter: submitter.properties,
|
break
|
||||||
type,
|
}
|
||||||
|
} finally {
|
||||||
|
session.close()
|
||||||
}
|
}
|
||||||
switch (type) {
|
return createdRelationshipWithNestedAttributes
|
||||||
case 'Post':
|
},
|
||||||
response.post = resource.properties
|
},
|
||||||
|
Query: {
|
||||||
|
reports: async (_parent, params, context, _resolveInfo) => {
|
||||||
|
const { driver } = context
|
||||||
|
const session = driver.session()
|
||||||
|
let response
|
||||||
|
let orderByClause
|
||||||
|
switch (params.orderBy) {
|
||||||
|
case 'createdAt_asc':
|
||||||
|
orderByClause = 'ORDER BY report.createdAt ASC'
|
||||||
break
|
break
|
||||||
case 'Comment':
|
case 'createdAt_desc':
|
||||||
response.comment = resource.properties
|
orderByClause = 'ORDER BY report.createdAt DESC'
|
||||||
break
|
|
||||||
case 'User':
|
|
||||||
response.user = resource.properties
|
|
||||||
break
|
break
|
||||||
|
default:
|
||||||
|
orderByClause = ''
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const cypher = `
|
||||||
|
MATCH (submitter:User)-[report:REPORTED]->(resource)
|
||||||
|
WHERE resource:User OR resource:Comment OR resource:Post
|
||||||
|
RETURN report, submitter, resource, labels(resource)[0] as type
|
||||||
|
${orderByClause}
|
||||||
|
`
|
||||||
|
const result = await session.run(cypher, {})
|
||||||
|
const dbResponse = result.records.map(r => {
|
||||||
|
return {
|
||||||
|
report: r.get('report'),
|
||||||
|
submitter: r.get('submitter'),
|
||||||
|
resource: r.get('resource'),
|
||||||
|
type: r.get('type'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!dbResponse) return null
|
||||||
|
|
||||||
|
response = []
|
||||||
|
dbResponse.forEach(ele => {
|
||||||
|
const { report, submitter, resource, type } = ele
|
||||||
|
|
||||||
|
const responseEle = {
|
||||||
|
...report.properties,
|
||||||
|
post: null,
|
||||||
|
comment: null,
|
||||||
|
user: null,
|
||||||
|
submitter: submitter.properties,
|
||||||
|
type,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'Post':
|
||||||
|
responseEle.post = resource.properties
|
||||||
|
break
|
||||||
|
case 'Comment':
|
||||||
|
responseEle.comment = resource.properties
|
||||||
|
break
|
||||||
|
case 'User':
|
||||||
|
responseEle.user = resource.properties
|
||||||
|
break
|
||||||
|
}
|
||||||
|
response.push(responseEle)
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
session.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|||||||
@ -1,35 +1,73 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { host, login } from '../../jest/helpers'
|
import { host, login, gql } from '../../jest/helpers'
|
||||||
import { neode } from '../../bootstrap/neo4j'
|
import { getDriver, neode } from '../../bootstrap/neo4j'
|
||||||
|
import { createTestClient } from 'apollo-server-testing'
|
||||||
|
import createServer from '../.././server'
|
||||||
|
|
||||||
const factory = Factory()
|
const factory = Factory()
|
||||||
const instance = neode()
|
const instance = neode()
|
||||||
|
const driver = getDriver()
|
||||||
|
|
||||||
describe('report', () => {
|
describe('report mutation', () => {
|
||||||
let mutation
|
let reportMutation
|
||||||
let headers
|
let headers
|
||||||
let returnedObject
|
let client
|
||||||
let variables
|
let variables
|
||||||
let createPostVariables
|
let createPostVariables
|
||||||
let user
|
let user
|
||||||
const categoryIds = ['cat9']
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
|
const action = () => {
|
||||||
|
reportMutation = gql`
|
||||||
|
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
|
||||||
|
report(
|
||||||
|
resourceId: $resourceId
|
||||||
|
reasonCategory: $reasonCategory
|
||||||
|
reasonDescription: $reasonDescription
|
||||||
|
) {
|
||||||
|
createdAt
|
||||||
|
reasonCategory
|
||||||
|
reasonDescription
|
||||||
|
type
|
||||||
|
submitter {
|
||||||
|
email
|
||||||
|
}
|
||||||
|
user {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
comment {
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
client = new GraphQLClient(host, {
|
||||||
|
headers,
|
||||||
|
})
|
||||||
|
return client.request(reportMutation, variables)
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
returnedObject = '{ description }'
|
|
||||||
variables = {
|
variables = {
|
||||||
id: 'whatever',
|
resourceId: 'whatever',
|
||||||
|
reasonCategory: 'other',
|
||||||
|
reasonDescription: 'Violates code of conduct !!!',
|
||||||
}
|
}
|
||||||
headers = {}
|
headers = {}
|
||||||
user = await factory.create('User', {
|
user = await factory.create('User', {
|
||||||
|
id: 'u1',
|
||||||
|
role: 'user',
|
||||||
email: 'test@example.org',
|
email: 'test@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
id: 'u1',
|
|
||||||
})
|
})
|
||||||
await factory.create('User', {
|
await factory.create('User', {
|
||||||
id: 'u2',
|
id: 'u2',
|
||||||
name: 'abusive-user',
|
|
||||||
role: 'user',
|
role: 'user',
|
||||||
|
name: 'abusive-user',
|
||||||
email: 'abusive-user@example.org',
|
email: 'abusive-user@example.org',
|
||||||
})
|
})
|
||||||
await instance.create('Category', {
|
await instance.create('Category', {
|
||||||
@ -43,59 +81,57 @@ describe('report', () => {
|
|||||||
await factory.cleanDatabase()
|
await factory.cleanDatabase()
|
||||||
})
|
})
|
||||||
|
|
||||||
let client
|
|
||||||
const action = () => {
|
|
||||||
mutation = `
|
|
||||||
mutation($id: ID!) {
|
|
||||||
report(
|
|
||||||
id: $id,
|
|
||||||
description: "Violates code of conduct"
|
|
||||||
) ${returnedObject}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
client = new GraphQLClient(host, {
|
|
||||||
headers,
|
|
||||||
})
|
|
||||||
return client.request(mutation, variables)
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
await expect(action()).rejects.toThrow('Not Authorised')
|
await expect(action()).rejects.toThrow('Not Authorised')
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('authenticated', () => {
|
describe('authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
headers = await login({
|
headers = await login({
|
||||||
email: 'test@example.org',
|
email: 'test@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('invalid resource id', () => {
|
||||||
|
it('returns null', async () => {
|
||||||
|
await expect(action()).resolves.toEqual({
|
||||||
|
report: null,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('invalid resource id', () => {
|
describe('valid resource id', () => {
|
||||||
it('returns null', async () => {
|
describe('reported resource is a user', () => {
|
||||||
await expect(action()).resolves.toEqual({
|
|
||||||
report: null,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('valid resource id', () => {
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
variables = {
|
variables = {
|
||||||
id: 'u2',
|
...variables,
|
||||||
|
resourceId: 'u2',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
/*
|
|
||||||
it('creates a report', async () => {
|
it('returns type "User"', async () => {
|
||||||
await expect(action()).resolves.toEqual({
|
await expect(action()).resolves.toMatchObject({
|
||||||
type: null,
|
report: {
|
||||||
})
|
type: 'User',
|
||||||
})
|
},
|
||||||
*/
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns resource in user attribute', async () => {
|
||||||
|
await expect(action()).resolves.toMatchObject({
|
||||||
|
report: {
|
||||||
|
user: {
|
||||||
|
name: 'abusive-user',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('returns the submitter', async () => {
|
it('returns the submitter', async () => {
|
||||||
returnedObject = '{ submitter { email } }'
|
await expect(action()).resolves.toMatchObject({
|
||||||
await expect(action()).resolves.toEqual({
|
|
||||||
report: {
|
report: {
|
||||||
submitter: {
|
submitter: {
|
||||||
email: 'test@example.org',
|
email: 'test@example.org',
|
||||||
@ -104,138 +140,382 @@ describe('report', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('reported resource is a user', () => {
|
it('returns a date', async () => {
|
||||||
it('returns type "User"', async () => {
|
await expect(action()).resolves.toMatchObject({
|
||||||
returnedObject = '{ type }'
|
report: {
|
||||||
await expect(action()).resolves.toEqual({
|
createdAt: expect.any(String),
|
||||||
report: {
|
},
|
||||||
type: 'User',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns resource in user attribute', async () => {
|
|
||||||
returnedObject = '{ user { name } }'
|
|
||||||
await expect(action()).resolves.toEqual({
|
|
||||||
report: {
|
|
||||||
user: {
|
|
||||||
name: 'abusive-user',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('reported resource is a post', () => {
|
it('returns the reason category', async () => {
|
||||||
beforeEach(async () => {
|
variables = {
|
||||||
await factory.create('Post', {
|
...variables,
|
||||||
author: user,
|
reasonCategory: 'criminal_behavior_violation_german_law',
|
||||||
id: 'p23',
|
}
|
||||||
title: 'Matt and Robert having a pair-programming',
|
await expect(action()).resolves.toMatchObject({
|
||||||
categoryIds,
|
report: {
|
||||||
})
|
reasonCategory: 'criminal_behavior_violation_german_law',
|
||||||
variables = {
|
},
|
||||||
id: 'p23',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns type "Post"', async () => {
|
|
||||||
returnedObject = '{ type }'
|
|
||||||
await expect(action()).resolves.toEqual({
|
|
||||||
report: {
|
|
||||||
type: 'Post',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns resource in post attribute', async () => {
|
|
||||||
returnedObject = '{ post { title } }'
|
|
||||||
await expect(action()).resolves.toEqual({
|
|
||||||
report: {
|
|
||||||
post: {
|
|
||||||
title: 'Matt and Robert having a pair-programming',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns null in user attribute', async () => {
|
|
||||||
returnedObject = '{ user { name } }'
|
|
||||||
await expect(action()).resolves.toEqual({
|
|
||||||
report: {
|
|
||||||
user: null,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
/* An der Stelle würde ich den p23 noch mal prüfen, diesmal muss aber eine error meldung kommen.
|
it('gives an error if the reason category is not in enum "ReasonCategory"', async () => {
|
||||||
|
variables = {
|
||||||
|
...variables,
|
||||||
|
reasonCategory: 'my_category',
|
||||||
|
}
|
||||||
|
await expect(action()).rejects.toThrow(
|
||||||
|
'got invalid value "my_category"; Expected type ReasonCategory',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns the reason description', async () => {
|
||||||
|
variables = {
|
||||||
|
...variables,
|
||||||
|
reasonDescription: 'My reason!',
|
||||||
|
}
|
||||||
|
await expect(action()).resolves.toMatchObject({
|
||||||
|
report: {
|
||||||
|
reasonDescription: 'My reason!',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sanitize the reason description', async () => {
|
||||||
|
variables = {
|
||||||
|
...variables,
|
||||||
|
reasonDescription: 'My reason <sanitize></sanitize>!',
|
||||||
|
}
|
||||||
|
await expect(action()).resolves.toMatchObject({
|
||||||
|
report: {
|
||||||
|
reasonDescription: 'My reason !',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('reported resource is a post', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await factory.create('Post', {
|
||||||
|
author: user,
|
||||||
|
id: 'p23',
|
||||||
|
title: 'Matt and Robert having a pair-programming',
|
||||||
|
categoryIds,
|
||||||
|
})
|
||||||
|
variables = {
|
||||||
|
...variables,
|
||||||
|
resourceId: 'p23',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns type "Post"', async () => {
|
||||||
|
await expect(action()).resolves.toMatchObject({
|
||||||
|
report: {
|
||||||
|
type: 'Post',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns resource in post attribute', async () => {
|
||||||
|
await expect(action()).resolves.toMatchObject({
|
||||||
|
report: {
|
||||||
|
post: {
|
||||||
|
title: 'Matt and Robert having a pair-programming',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns null in user attribute', async () => {
|
||||||
|
await expect(action()).resolves.toMatchObject({
|
||||||
|
report: {
|
||||||
|
user: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/* An der Stelle würde ich den p23 noch mal prüfen, diesmal muss aber eine error meldung kommen.
|
||||||
At this point I would check the p23 again, but this time there must be an error message. */
|
At this point I would check the p23 again, but this time there must be an error message. */
|
||||||
|
|
||||||
describe('reported resource is a comment', () => {
|
describe('reported resource is a comment', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
createPostVariables = {
|
createPostVariables = {
|
||||||
id: 'p1',
|
id: 'p1',
|
||||||
title: 'post to comment on',
|
title: 'post to comment on',
|
||||||
content: 'please comment on me',
|
content: 'please comment on me',
|
||||||
categoryIds,
|
categoryIds,
|
||||||
}
|
}
|
||||||
await factory.create('Post', { ...createPostVariables, author: user })
|
await factory.create('Post', { ...createPostVariables, author: user })
|
||||||
await factory.create('Comment', {
|
await factory.create('Comment', {
|
||||||
author: user,
|
author: user,
|
||||||
postId: 'p1',
|
postId: 'p1',
|
||||||
id: 'c34',
|
id: 'c34',
|
||||||
content: 'Robert getting tired.',
|
content: 'Robert getting tired.',
|
||||||
})
|
|
||||||
variables = {
|
|
||||||
id: 'c34',
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
variables = {
|
||||||
|
...variables,
|
||||||
|
resourceId: 'c34',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('returns type "Comment"', async () => {
|
it('returns type "Comment"', async () => {
|
||||||
returnedObject = '{ type }'
|
await expect(action()).resolves.toMatchObject({
|
||||||
await expect(action()).resolves.toEqual({
|
report: {
|
||||||
report: {
|
type: 'Comment',
|
||||||
type: 'Comment',
|
},
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns resource in comment attribute', async () => {
|
|
||||||
returnedObject = '{ comment { content } }'
|
|
||||||
await expect(action()).resolves.toEqual({
|
|
||||||
report: {
|
|
||||||
comment: {
|
|
||||||
content: 'Robert getting tired.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
/* An der Stelle würde ich den c34 noch mal prüfen, diesmal muss aber eine error meldung kommen.
|
it('returns resource in comment attribute', async () => {
|
||||||
|
await expect(action()).resolves.toMatchObject({
|
||||||
|
report: {
|
||||||
|
comment: {
|
||||||
|
content: 'Robert getting tired.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/* An der Stelle würde ich den c34 noch mal prüfen, diesmal muss aber eine error meldung kommen.
|
||||||
At this point I would check the c34 again, but this time there must be an error message. */
|
At this point I would check the c34 again, but this time there must be an error message. */
|
||||||
|
|
||||||
describe('reported resource is a tag', () => {
|
describe('reported resource is a tag', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await factory.create('Tag', {
|
await factory.create('Tag', {
|
||||||
id: 't23',
|
id: 't23',
|
||||||
})
|
|
||||||
variables = {
|
|
||||||
id: 't23',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns null', async () => {
|
|
||||||
await expect(action()).resolves.toEqual({
|
|
||||||
report: null,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
variables = {
|
||||||
|
...variables,
|
||||||
|
resourceId: 't23',
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/* An der Stelle würde ich den t23 noch mal prüfen, diesmal muss aber eine error meldung kommen.
|
it('returns null', async () => {
|
||||||
At this point I would check the t23 again, but this time there must be an error message. */
|
await expect(action()).resolves.toMatchObject({
|
||||||
|
report: null,
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/* An der Stelle würde ich den t23 noch mal prüfen, diesmal muss aber eine error meldung kommen.
|
||||||
|
At this point I would check the t23 again, but this time there must be an error message. */
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('reports query', () => {
|
||||||
|
let query, mutate, authenticatedUser, moderator, user, author
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
|
const reportMutation = gql`
|
||||||
|
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
|
||||||
|
report(
|
||||||
|
resourceId: $resourceId
|
||||||
|
reasonCategory: $reasonCategory
|
||||||
|
reasonDescription: $reasonDescription
|
||||||
|
) {
|
||||||
|
type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const reportsQuery = gql`
|
||||||
|
query {
|
||||||
|
reports(orderBy: createdAt_desc) {
|
||||||
|
createdAt
|
||||||
|
reasonCategory
|
||||||
|
reasonDescription
|
||||||
|
submitter {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
type
|
||||||
|
user {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
comment {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await factory.cleanDatabase()
|
||||||
|
const { server } = createServer({
|
||||||
|
context: () => {
|
||||||
|
return {
|
||||||
|
driver,
|
||||||
|
user: authenticatedUser,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
query = createTestClient(server).query
|
||||||
|
mutate = createTestClient(server).mutate
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
authenticatedUser = null
|
||||||
|
|
||||||
|
moderator = await factory.create('User', {
|
||||||
|
id: 'mod1',
|
||||||
|
role: 'moderator',
|
||||||
|
email: 'moderator@example.org',
|
||||||
|
password: '1234',
|
||||||
|
})
|
||||||
|
user = await factory.create('User', {
|
||||||
|
id: 'user1',
|
||||||
|
role: 'user',
|
||||||
|
email: 'test@example.org',
|
||||||
|
password: '1234',
|
||||||
|
})
|
||||||
|
author = await factory.create('User', {
|
||||||
|
id: 'auth1',
|
||||||
|
role: 'user',
|
||||||
|
name: 'abusive-user',
|
||||||
|
email: 'abusive-user@example.org',
|
||||||
|
})
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
factory.create('Post', {
|
||||||
|
author,
|
||||||
|
id: 'p1',
|
||||||
|
categoryIds,
|
||||||
|
content: 'Interesting Knowledge',
|
||||||
|
}),
|
||||||
|
factory.create('Post', {
|
||||||
|
author: moderator,
|
||||||
|
id: 'p2',
|
||||||
|
categoryIds,
|
||||||
|
content: 'More things to do …',
|
||||||
|
}),
|
||||||
|
factory.create('Post', {
|
||||||
|
author: user,
|
||||||
|
id: 'p3',
|
||||||
|
categoryIds,
|
||||||
|
content: 'I am at school …',
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
await Promise.all([
|
||||||
|
factory.create('Comment', {
|
||||||
|
author: user,
|
||||||
|
id: 'c1',
|
||||||
|
postId: 'p1',
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
authenticatedUser = await user.toJson()
|
||||||
|
await Promise.all([
|
||||||
|
mutate({
|
||||||
|
mutation: reportMutation,
|
||||||
|
variables: {
|
||||||
|
resourceId: 'p1',
|
||||||
|
reasonCategory: 'other',
|
||||||
|
reasonDescription: 'This comment is bigoted',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
mutate({
|
||||||
|
mutation: reportMutation,
|
||||||
|
variables: {
|
||||||
|
resourceId: 'c1',
|
||||||
|
reasonCategory: 'discrimination_etc',
|
||||||
|
reasonDescription: 'This post is bigoted',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
mutate({
|
||||||
|
mutation: reportMutation,
|
||||||
|
variables: {
|
||||||
|
resourceId: 'auth1',
|
||||||
|
reasonCategory: 'doxing',
|
||||||
|
reasonDescription: 'This user is harassing me with bigoted remarks',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
authenticatedUser = null
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await factory.cleanDatabase()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('unauthenticated', () => {
|
||||||
|
it('throws authorization error', async () => {
|
||||||
|
authenticatedUser = null
|
||||||
|
expect(query({ query: reportsQuery })).resolves.toMatchObject({
|
||||||
|
data: { reports: null },
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('role "user" gets no reports', async () => {
|
||||||
|
authenticatedUser = await user.toJson()
|
||||||
|
expect(query({ query: reportsQuery })).resolves.toMatchObject({
|
||||||
|
data: { reports: null },
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('role "moderator" gets reports', async () => {
|
||||||
|
const expected = {
|
||||||
|
// to check 'orderBy: createdAt_desc' is not possible here, because 'createdAt' does not differ
|
||||||
|
reports: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
reasonCategory: 'doxing',
|
||||||
|
reasonDescription: 'This user is harassing me with bigoted remarks',
|
||||||
|
submitter: expect.objectContaining({
|
||||||
|
id: 'user1',
|
||||||
|
}),
|
||||||
|
type: 'User',
|
||||||
|
user: expect.objectContaining({
|
||||||
|
id: 'auth1',
|
||||||
|
}),
|
||||||
|
post: null,
|
||||||
|
comment: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
reasonCategory: 'other',
|
||||||
|
reasonDescription: 'This comment is bigoted',
|
||||||
|
submitter: expect.objectContaining({
|
||||||
|
id: 'user1',
|
||||||
|
}),
|
||||||
|
type: 'Post',
|
||||||
|
user: null,
|
||||||
|
post: expect.objectContaining({
|
||||||
|
id: 'p1',
|
||||||
|
}),
|
||||||
|
comment: null,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
createdAt: expect.any(String),
|
||||||
|
reasonCategory: 'discrimination_etc',
|
||||||
|
reasonDescription: 'This post is bigoted',
|
||||||
|
submitter: expect.objectContaining({
|
||||||
|
id: 'user1',
|
||||||
|
}),
|
||||||
|
type: 'Comment',
|
||||||
|
user: null,
|
||||||
|
post: null,
|
||||||
|
comment: expect.objectContaining({
|
||||||
|
id: 'c1',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticatedUser = await moderator.toJson()
|
||||||
|
const { data } = await query({ query: reportsQuery })
|
||||||
|
expect(data).toEqual(expected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,31 +1,49 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { createTestClient } from 'apollo-server-testing'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { host, login, gql } from '../../jest/helpers'
|
import { gql } from '../../jest/helpers'
|
||||||
|
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||||
|
import createServer from '../../server'
|
||||||
|
|
||||||
const factory = Factory()
|
const factory = Factory()
|
||||||
let user
|
const driver = getDriver()
|
||||||
let badge
|
const instance = getNeode()
|
||||||
|
|
||||||
|
let authenticatedUser, regularUser, administrator, moderator, badge, query, mutate
|
||||||
|
|
||||||
describe('rewards', () => {
|
describe('rewards', () => {
|
||||||
const variables = {
|
const variables = {
|
||||||
from: 'indiegogo_en_rhino',
|
from: 'indiegogo_en_rhino',
|
||||||
to: 'u1',
|
to: 'regular-user-id',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const { server } = createServer({
|
||||||
|
context: () => {
|
||||||
|
return {
|
||||||
|
driver,
|
||||||
|
neode: instance,
|
||||||
|
user: authenticatedUser,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
query = createTestClient(server).query
|
||||||
|
mutate = createTestClient(server).mutate
|
||||||
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = await factory.create('User', {
|
regularUser = await factory.create('User', {
|
||||||
id: 'u1',
|
id: 'regular-user-id',
|
||||||
role: 'user',
|
role: 'user',
|
||||||
email: 'user@example.org',
|
email: 'user@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
})
|
})
|
||||||
await factory.create('User', {
|
moderator = await factory.create('User', {
|
||||||
id: 'u2',
|
id: 'moderator-id',
|
||||||
role: 'moderator',
|
role: 'moderator',
|
||||||
email: 'moderator@example.org',
|
email: 'moderator@example.org',
|
||||||
})
|
})
|
||||||
await factory.create('User', {
|
administrator = await factory.create('User', {
|
||||||
id: 'u3',
|
id: 'admin-id',
|
||||||
role: 'admin',
|
role: 'admin',
|
||||||
email: 'admin@example.org',
|
email: 'admin@example.org',
|
||||||
})
|
})
|
||||||
@ -42,7 +60,7 @@ describe('rewards', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('reward', () => {
|
describe('reward', () => {
|
||||||
const mutation = gql`
|
const rewardMutation = gql`
|
||||||
mutation($from: ID!, $to: ID!) {
|
mutation($from: ID!, $to: ID!) {
|
||||||
reward(badgeKey: $from, userId: $to) {
|
reward(badgeKey: $from, userId: $to) {
|
||||||
id
|
id
|
||||||
@ -54,51 +72,61 @@ describe('rewards', () => {
|
|||||||
`
|
`
|
||||||
|
|
||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
let client
|
|
||||||
|
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
client = new GraphQLClient(host)
|
authenticatedUser = null
|
||||||
await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised')
|
await expect(mutate({ mutation: rewardMutation, variables })).resolves.toMatchObject({
|
||||||
|
data: { reward: null },
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('authenticated admin', () => {
|
describe('authenticated admin', () => {
|
||||||
let client
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const headers = await login({ email: 'admin@example.org', password: '1234' })
|
authenticatedUser = await administrator.toJson()
|
||||||
client = new GraphQLClient(host, { headers })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('badge for id does not exist', () => {
|
describe('badge for id does not exist', () => {
|
||||||
it('rejects with a telling error message', async () => {
|
it('rejects with an informative error message', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
client.request(mutation, {
|
mutate({
|
||||||
...variables,
|
mutation: rewardMutation,
|
||||||
from: 'bullshit',
|
variables: { to: 'regular-user-id', from: 'non-existent-badge-id' },
|
||||||
}),
|
}),
|
||||||
).rejects.toThrow("Couldn't find a badge with that id")
|
).resolves.toMatchObject({
|
||||||
|
data: { reward: null },
|
||||||
|
errors: [{ message: "Couldn't find a badge with that id" }],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('user for id does not exist', () => {
|
describe('non-existent user', () => {
|
||||||
it('rejects with a telling error message', async () => {
|
it('rejects with a telling error message', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
client.request(mutation, {
|
mutate({
|
||||||
...variables,
|
mutation: rewardMutation,
|
||||||
to: 'bullshit',
|
variables: { to: 'non-existent-user-id', from: 'indiegogo_en_rhino' },
|
||||||
}),
|
}),
|
||||||
).rejects.toThrow("Couldn't find a user with that id")
|
).resolves.toMatchObject({
|
||||||
|
data: { reward: null },
|
||||||
|
errors: [{ message: "Couldn't find a user with that id" }],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rewards a badge to user', async () => {
|
it('rewards a badge to user', async () => {
|
||||||
const expected = {
|
const expected = {
|
||||||
reward: {
|
data: {
|
||||||
id: 'u1',
|
reward: {
|
||||||
badges: [{ id: 'indiegogo_en_rhino' }],
|
id: 'regular-user-id',
|
||||||
|
badges: [{ id: 'indiegogo_en_rhino' }],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
}
|
}
|
||||||
await expect(client.request(mutation, variables)).resolves.toEqual(expected)
|
await expect(mutate({ mutation: rewardMutation, variables })).resolves.toMatchObject(
|
||||||
|
expected,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rewards a second different badge to same user', async () => {
|
it('rewards a second different badge to same user', async () => {
|
||||||
@ -108,42 +136,74 @@ describe('rewards', () => {
|
|||||||
})
|
})
|
||||||
const badges = [{ id: 'indiegogo_en_racoon' }, { id: 'indiegogo_en_rhino' }]
|
const badges = [{ id: 'indiegogo_en_racoon' }, { id: 'indiegogo_en_rhino' }]
|
||||||
const expected = {
|
const expected = {
|
||||||
reward: {
|
data: {
|
||||||
id: 'u1',
|
reward: {
|
||||||
badges: expect.arrayContaining(badges),
|
id: 'regular-user-id',
|
||||||
|
badges: expect.arrayContaining(badges),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
}
|
}
|
||||||
await client.request(mutation, variables)
|
await mutate({
|
||||||
|
mutation: rewardMutation,
|
||||||
|
variables: {
|
||||||
|
to: 'regular-user-id',
|
||||||
|
from: 'indiegogo_en_rhino',
|
||||||
|
},
|
||||||
|
})
|
||||||
await expect(
|
await expect(
|
||||||
client.request(mutation, {
|
mutate({
|
||||||
...variables,
|
mutation: rewardMutation,
|
||||||
from: 'indiegogo_en_racoon',
|
variables: {
|
||||||
|
to: 'regular-user-id',
|
||||||
|
from: 'indiegogo_en_racoon',
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toEqual(expected)
|
).resolves.toMatchObject(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rewards the same badge as well to another user', async () => {
|
it('rewards the same badge as well to another user', async () => {
|
||||||
const expected = {
|
const expected = {
|
||||||
reward: {
|
data: {
|
||||||
id: 'u2',
|
reward: {
|
||||||
badges: [{ id: 'indiegogo_en_rhino' }],
|
id: 'regular-user-2-id',
|
||||||
|
badges: [{ id: 'indiegogo_en_rhino' }],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
}
|
}
|
||||||
|
await factory.create('User', {
|
||||||
|
id: 'regular-user-2-id',
|
||||||
|
email: 'regular2@email.com',
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: rewardMutation,
|
||||||
|
variables,
|
||||||
|
})
|
||||||
await expect(
|
await expect(
|
||||||
client.request(mutation, {
|
mutate({
|
||||||
...variables,
|
mutation: rewardMutation,
|
||||||
to: 'u2',
|
variables: {
|
||||||
|
to: 'regular-user-2-id',
|
||||||
|
from: 'indiegogo_en_rhino',
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toEqual(expected)
|
).resolves.toMatchObject(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('creates no duplicate reward relationships', async () => {
|
it('creates no duplicate reward relationships', async () => {
|
||||||
await client.request(mutation, variables)
|
await mutate({
|
||||||
await client.request(mutation, variables)
|
mutation: rewardMutation,
|
||||||
|
variables,
|
||||||
|
})
|
||||||
|
await mutate({
|
||||||
|
mutation: rewardMutation,
|
||||||
|
variables,
|
||||||
|
})
|
||||||
|
|
||||||
const query = gql`
|
const userQuery = gql`
|
||||||
{
|
{
|
||||||
User(id: "u1") {
|
User(id: "regular-user-id") {
|
||||||
badgesCount
|
badgesCount
|
||||||
badges {
|
badges {
|
||||||
id
|
id
|
||||||
@ -151,22 +211,26 @@ describe('rewards', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const expected = { User: [{ badgesCount: 1, badges: [{ id: 'indiegogo_en_rhino' }] }] }
|
const expected = {
|
||||||
|
data: { User: [{ badgesCount: 1, badges: [{ id: 'indiegogo_en_rhino' }] }] },
|
||||||
|
errors: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
await expect(client.request(query)).resolves.toEqual(expected)
|
await expect(query({ query: userQuery })).resolves.toMatchObject(expected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('authenticated moderator', () => {
|
describe('authenticated moderator', () => {
|
||||||
let client
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const headers = await login({ email: 'moderator@example.org', password: '1234' })
|
authenticatedUser = moderator.toJson()
|
||||||
client = new GraphQLClient(host, { headers })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('rewards bage to user', () => {
|
describe('rewards badge to user', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised')
|
await expect(mutate({ mutation: rewardMutation, variables })).resolves.toMatchObject({
|
||||||
|
data: { reward: null },
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -174,11 +238,14 @@ describe('rewards', () => {
|
|||||||
|
|
||||||
describe('unreward', () => {
|
describe('unreward', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await user.relateTo(badge, 'rewarded')
|
await regularUser.relateTo(badge, 'rewarded')
|
||||||
})
|
})
|
||||||
const expected = { unreward: { id: 'u1', badges: [] } }
|
const expected = {
|
||||||
|
data: { unreward: { id: 'regular-user-id', badges: [] } },
|
||||||
|
errors: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
const mutation = gql`
|
const unrewardMutation = gql`
|
||||||
mutation($from: ID!, $to: ID!) {
|
mutation($from: ID!, $to: ID!) {
|
||||||
unreward(badgeKey: $from, userId: $to) {
|
unreward(badgeKey: $from, userId: $to) {
|
||||||
id
|
id
|
||||||
@ -191,9 +258,10 @@ describe('rewards', () => {
|
|||||||
|
|
||||||
describe('check test setup', () => {
|
describe('check test setup', () => {
|
||||||
it('user has one badge', async () => {
|
it('user has one badge', async () => {
|
||||||
const query = gql`
|
authenticatedUser = regularUser.toJson()
|
||||||
|
const userQuery = gql`
|
||||||
{
|
{
|
||||||
User(id: "u1") {
|
User(id: "regular-user-id") {
|
||||||
badgesCount
|
badgesCount
|
||||||
badges {
|
badges {
|
||||||
id
|
id
|
||||||
@ -201,48 +269,54 @@ describe('rewards', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const expected = { User: [{ badgesCount: 1, badges: [{ id: 'indiegogo_en_rhino' }] }] }
|
const expected = {
|
||||||
const client = new GraphQLClient(host)
|
data: { User: [{ badgesCount: 1, badges: [{ id: 'indiegogo_en_rhino' }] }] },
|
||||||
await expect(client.request(query)).resolves.toEqual(expected)
|
errors: undefined,
|
||||||
|
}
|
||||||
|
await expect(query({ query: userQuery })).resolves.toMatchObject(expected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
let client
|
|
||||||
|
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
client = new GraphQLClient(host)
|
authenticatedUser = null
|
||||||
await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised')
|
await expect(mutate({ mutation: unrewardMutation, variables })).resolves.toMatchObject({
|
||||||
|
data: { unreward: null },
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('authenticated admin', () => {
|
describe('authenticated admin', () => {
|
||||||
let client
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const headers = await login({ email: 'admin@example.org', password: '1234' })
|
authenticatedUser = await administrator.toJson()
|
||||||
client = new GraphQLClient(host, { headers })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('removes a badge from user', async () => {
|
it('removes a badge from user', async () => {
|
||||||
await expect(client.request(mutation, variables)).resolves.toEqual(expected)
|
await expect(mutate({ mutation: unrewardMutation, variables })).resolves.toMatchObject(
|
||||||
|
expected,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('does not crash when unrewarding multiple times', async () => {
|
it('does not crash when unrewarding multiple times', async () => {
|
||||||
await client.request(mutation, variables)
|
await mutate({ mutation: unrewardMutation, variables })
|
||||||
await expect(client.request(mutation, variables)).resolves.toEqual(expected)
|
await expect(mutate({ mutation: unrewardMutation, variables })).resolves.toMatchObject(
|
||||||
|
expected,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('authenticated moderator', () => {
|
describe('authenticated moderator', () => {
|
||||||
let client
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const headers = await login({ email: 'moderator@example.org', password: '1234' })
|
authenticatedUser = await moderator.toJson()
|
||||||
client = new GraphQLClient(host, { headers })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('removes bage from user', () => {
|
describe('removes bage from user', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised')
|
await expect(mutate({ mutation: unrewardMutation, variables })).resolves.toMatchObject({
|
||||||
|
data: { unreward: null },
|
||||||
|
errors: [{ message: 'Not Authorised!' }],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export default {
|
|||||||
countPosts: 'Post',
|
countPosts: 'Post',
|
||||||
countComments: 'Comment',
|
countComments: 'Comment',
|
||||||
countNotifications: 'NOTIFIED',
|
countNotifications: 'NOTIFIED',
|
||||||
countInvites: 'InvitationCode',
|
countEmails: 'EmailAddress',
|
||||||
countFollows: 'FOLLOWS',
|
countFollows: 'FOLLOWS',
|
||||||
countShouts: 'SHOUTED',
|
countShouts: 'SHOUTED',
|
||||||
}
|
}
|
||||||
@ -28,6 +28,11 @@ export default {
|
|||||||
const stat = statistics[mapping[key]]
|
const stat = statistics[mapping[key]]
|
||||||
response[key] = stat ? stat.toNumber() : 0
|
response[key] = stat ? stat.toNumber() : 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: invites count is calculated this way because invitation codes are not in use yet
|
||||||
|
*/
|
||||||
|
response.countInvites = response.countEmails - response.countUsers
|
||||||
} finally {
|
} finally {
|
||||||
session.close()
|
session.close()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -176,6 +176,7 @@ export default {
|
|||||||
'about',
|
'about',
|
||||||
'termsAndConditionsAgreedVersion',
|
'termsAndConditionsAgreedVersion',
|
||||||
'termsAndConditionsAgreedAt',
|
'termsAndConditionsAgreedAt',
|
||||||
|
'allowEmbedIframes',
|
||||||
],
|
],
|
||||||
boolean: {
|
boolean: {
|
||||||
followedByCurrentUser:
|
followedByCurrentUser:
|
||||||
|
|||||||
@ -86,6 +86,7 @@ describe('UpdateUser', () => {
|
|||||||
name: 'John Doe',
|
name: 'John Doe',
|
||||||
termsAndConditionsAgreedVersion: null,
|
termsAndConditionsAgreedVersion: null,
|
||||||
termsAndConditionsAgreedAt: null,
|
termsAndConditionsAgreedAt: null,
|
||||||
|
allowEmbedIframes: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
variables = {
|
variables = {
|
||||||
|
|||||||
@ -24,7 +24,6 @@ type Mutation {
|
|||||||
changePassword(oldPassword: String!, newPassword: String!): String!
|
changePassword(oldPassword: String!, newPassword: String!): String!
|
||||||
requestPasswordReset(email: String!): Boolean!
|
requestPasswordReset(email: String!): Boolean!
|
||||||
resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean!
|
resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean!
|
||||||
report(id: ID!, description: String): Report
|
|
||||||
disable(id: ID!): ID
|
disable(id: ID!): ID
|
||||||
enable(id: ID!): ID
|
enable(id: ID!): ID
|
||||||
# Shout the given Type and ID
|
# Shout the given Type and ID
|
||||||
@ -35,18 +34,6 @@ type Mutation {
|
|||||||
unfollowUser(id: ID!): User
|
unfollowUser(id: ID!): User
|
||||||
}
|
}
|
||||||
|
|
||||||
type Report {
|
|
||||||
id: ID!
|
|
||||||
submitter: User @relation(name: "REPORTED", direction: "IN")
|
|
||||||
description: String
|
|
||||||
type: String!
|
|
||||||
@cypher(statement: "MATCH (resource)<-[:REPORTED]-(this) RETURN labels(resource)[0]")
|
|
||||||
createdAt: String
|
|
||||||
comment: Comment @relation(name: "REPORTED", direction: "OUT")
|
|
||||||
post: Post @relation(name: "REPORTED", direction: "OUT")
|
|
||||||
user: User @relation(name: "REPORTED", direction: "OUT")
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Deletable {
|
enum Deletable {
|
||||||
Post
|
Post
|
||||||
Comment
|
Comment
|
||||||
|
|||||||
43
backend/src/schema/types/type/REPORTED.gql
Normal file
43
backend/src/schema/types/type/REPORTED.gql
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
type REPORTED {
|
||||||
|
createdAt: String
|
||||||
|
reasonCategory: ReasonCategory
|
||||||
|
reasonDescription: String
|
||||||
|
submitter: User
|
||||||
|
@cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN user")
|
||||||
|
# not yet supported
|
||||||
|
# resource: ReportResource
|
||||||
|
# @cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN resource")
|
||||||
|
type: String
|
||||||
|
@cypher(statement: "MATCH (resource)<-[:REPORTED]-(user:User) RETURN labels(resource)[0]")
|
||||||
|
user: User
|
||||||
|
post: Post
|
||||||
|
comment: Comment
|
||||||
|
}
|
||||||
|
|
||||||
|
# this list equals the strings of an array in file "webapp/constants/modals.js"
|
||||||
|
enum ReasonCategory {
|
||||||
|
other
|
||||||
|
discrimination_etc
|
||||||
|
pornographic_content_links
|
||||||
|
glorific_trivia_of_cruel_inhuman_acts
|
||||||
|
doxing
|
||||||
|
intentional_intimidation_stalking_persecution
|
||||||
|
advert_products_services_commercial
|
||||||
|
criminal_behavior_violation_german_law
|
||||||
|
}
|
||||||
|
|
||||||
|
# not yet supported
|
||||||
|
# union ReportResource = User | Post | Comment
|
||||||
|
|
||||||
|
enum ReportOrdering {
|
||||||
|
createdAt_asc
|
||||||
|
createdAt_desc
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
reports(orderBy: ReportOrdering): [REPORTED]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
report(resourceId: ID!, reasonCategory: ReasonCategory!, reasonDescription: String!): REPORTED
|
||||||
|
}
|
||||||
@ -27,6 +27,8 @@ type User {
|
|||||||
termsAndConditionsAgreedVersion: String
|
termsAndConditionsAgreedVersion: String
|
||||||
termsAndConditionsAgreedAt: String
|
termsAndConditionsAgreedAt: String
|
||||||
|
|
||||||
|
allowEmbedIframes: Boolean
|
||||||
|
|
||||||
friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
|
friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
|
||||||
friendsCount: Int! @cypher(statement: "MATCH (this)<-[: FRIENDS]->(r: User) RETURN COUNT(DISTINCT r)")
|
friendsCount: Int! @cypher(statement: "MATCH (this)<-[: FRIENDS]->(r: User) RETURN COUNT(DISTINCT r)")
|
||||||
|
|
||||||
@ -166,6 +168,7 @@ type Mutation {
|
|||||||
about: String
|
about: String
|
||||||
termsAndConditionsAgreedVersion: String
|
termsAndConditionsAgreedVersion: String
|
||||||
termsAndConditionsAgreedAt: String
|
termsAndConditionsAgreedAt: String
|
||||||
|
allowEmbedIframes: Boolean
|
||||||
): User
|
): User
|
||||||
|
|
||||||
DeleteUser(id: ID!, resource: [Deletable]): User
|
DeleteUser(id: ID!, resource: [Deletable]): User
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export default function create() {
|
|||||||
about: faker.lorem.paragraph(),
|
about: faker.lorem.paragraph(),
|
||||||
termsAndConditionsAgreedVersion: '0.0.1',
|
termsAndConditionsAgreedVersion: '0.0.1',
|
||||||
termsAndConditionsAgreedAt: '2019-08-01T10:47:19.212Z',
|
termsAndConditionsAgreedAt: '2019-08-01T10:47:19.212Z',
|
||||||
|
allowEmbedIframes: false,
|
||||||
}
|
}
|
||||||
defaults.slug = slugify(defaults.name, { lower: true })
|
defaults.slug = slugify(defaults.name, { lower: true })
|
||||||
args = {
|
args = {
|
||||||
|
|||||||
@ -24,10 +24,8 @@ import { gql } from '../jest/helpers'
|
|||||||
})
|
})
|
||||||
const { mutate } = createTestClient(server)
|
const { mutate } = createTestClient(server)
|
||||||
|
|
||||||
const f = Factory()
|
|
||||||
|
|
||||||
const [Hamburg, Berlin, Germany, Paris, France] = await Promise.all([
|
const [Hamburg, Berlin, Germany, Paris, France] = await Promise.all([
|
||||||
f.create('Location', {
|
factory.create('Location', {
|
||||||
id: 'region.5127278006398860',
|
id: 'region.5127278006398860',
|
||||||
name: 'Hamburg',
|
name: 'Hamburg',
|
||||||
type: 'region',
|
type: 'region',
|
||||||
@ -42,7 +40,7 @@ import { gql } from '../jest/helpers'
|
|||||||
nameNL: 'Hamburg',
|
nameNL: 'Hamburg',
|
||||||
namePL: 'Hamburg',
|
namePL: 'Hamburg',
|
||||||
}),
|
}),
|
||||||
f.create('Location', {
|
factory.create('Location', {
|
||||||
id: 'region.14880313158564380',
|
id: 'region.14880313158564380',
|
||||||
type: 'region',
|
type: 'region',
|
||||||
name: 'Berlin',
|
name: 'Berlin',
|
||||||
@ -57,7 +55,7 @@ import { gql } from '../jest/helpers'
|
|||||||
nameNL: 'Berlijn',
|
nameNL: 'Berlijn',
|
||||||
namePL: 'Berlin',
|
namePL: 'Berlin',
|
||||||
}),
|
}),
|
||||||
f.create('Location', {
|
factory.create('Location', {
|
||||||
id: 'country.10743216036480410',
|
id: 'country.10743216036480410',
|
||||||
name: 'Germany',
|
name: 'Germany',
|
||||||
type: 'country',
|
type: 'country',
|
||||||
@ -70,7 +68,7 @@ import { gql } from '../jest/helpers'
|
|||||||
nameIT: 'Germania',
|
nameIT: 'Germania',
|
||||||
nameEN: 'Germany',
|
nameEN: 'Germany',
|
||||||
}),
|
}),
|
||||||
f.create('Location', {
|
factory.create('Location', {
|
||||||
id: 'region.9397217726497330',
|
id: 'region.9397217726497330',
|
||||||
name: 'Paris',
|
name: 'Paris',
|
||||||
type: 'region',
|
type: 'region',
|
||||||
@ -85,7 +83,7 @@ import { gql } from '../jest/helpers'
|
|||||||
nameNL: 'Parijs',
|
nameNL: 'Parijs',
|
||||||
namePL: 'Paryż',
|
namePL: 'Paryż',
|
||||||
}),
|
}),
|
||||||
f.create('Location', {
|
factory.create('Location', {
|
||||||
id: 'country.9759535382641660',
|
id: 'country.9759535382641660',
|
||||||
name: 'France',
|
name: 'France',
|
||||||
type: 'country',
|
type: 'country',
|
||||||
@ -106,27 +104,27 @@ import { gql } from '../jest/helpers'
|
|||||||
])
|
])
|
||||||
|
|
||||||
const [racoon, rabbit, wolf, bear, turtle, rhino] = await Promise.all([
|
const [racoon, rabbit, wolf, bear, turtle, rhino] = await Promise.all([
|
||||||
f.create('Badge', {
|
factory.create('Badge', {
|
||||||
id: 'indiegogo_en_racoon',
|
id: 'indiegogo_en_racoon',
|
||||||
icon: '/img/badges/indiegogo_en_racoon.svg',
|
icon: '/img/badges/indiegogo_en_racoon.svg',
|
||||||
}),
|
}),
|
||||||
f.create('Badge', {
|
factory.create('Badge', {
|
||||||
id: 'indiegogo_en_rabbit',
|
id: 'indiegogo_en_rabbit',
|
||||||
icon: '/img/badges/indiegogo_en_rabbit.svg',
|
icon: '/img/badges/indiegogo_en_rabbit.svg',
|
||||||
}),
|
}),
|
||||||
f.create('Badge', {
|
factory.create('Badge', {
|
||||||
id: 'indiegogo_en_wolf',
|
id: 'indiegogo_en_wolf',
|
||||||
icon: '/img/badges/indiegogo_en_wolf.svg',
|
icon: '/img/badges/indiegogo_en_wolf.svg',
|
||||||
}),
|
}),
|
||||||
f.create('Badge', {
|
factory.create('Badge', {
|
||||||
id: 'indiegogo_en_bear',
|
id: 'indiegogo_en_bear',
|
||||||
icon: '/img/badges/indiegogo_en_bear.svg',
|
icon: '/img/badges/indiegogo_en_bear.svg',
|
||||||
}),
|
}),
|
||||||
f.create('Badge', {
|
factory.create('Badge', {
|
||||||
id: 'indiegogo_en_turtle',
|
id: 'indiegogo_en_turtle',
|
||||||
icon: '/img/badges/indiegogo_en_turtle.svg',
|
icon: '/img/badges/indiegogo_en_turtle.svg',
|
||||||
}),
|
}),
|
||||||
f.create('Badge', {
|
factory.create('Badge', {
|
||||||
id: 'indiegogo_en_rhino',
|
id: 'indiegogo_en_rhino',
|
||||||
icon: '/img/badges/indiegogo_en_rhino.svg',
|
icon: '/img/badges/indiegogo_en_rhino.svg',
|
||||||
}),
|
}),
|
||||||
@ -141,49 +139,49 @@ import { gql } from '../jest/helpers'
|
|||||||
louie,
|
louie,
|
||||||
dagobert,
|
dagobert,
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
f.create('User', {
|
factory.create('User', {
|
||||||
id: 'u1',
|
id: 'u1',
|
||||||
name: 'Peter Lustig',
|
name: 'Peter Lustig',
|
||||||
slug: 'peter-lustig',
|
slug: 'peter-lustig',
|
||||||
role: 'admin',
|
role: 'admin',
|
||||||
email: 'admin@example.org',
|
email: 'admin@example.org',
|
||||||
}),
|
}),
|
||||||
f.create('User', {
|
factory.create('User', {
|
||||||
id: 'u2',
|
id: 'u2',
|
||||||
name: 'Bob der Baumeister',
|
name: 'Bob der Baumeister',
|
||||||
slug: 'bob-der-baumeister',
|
slug: 'bob-der-baumeister',
|
||||||
role: 'moderator',
|
role: 'moderator',
|
||||||
email: 'moderator@example.org',
|
email: 'moderator@example.org',
|
||||||
}),
|
}),
|
||||||
f.create('User', {
|
factory.create('User', {
|
||||||
id: 'u3',
|
id: 'u3',
|
||||||
name: 'Jenny Rostock',
|
name: 'Jenny Rostock',
|
||||||
slug: 'jenny-rostock',
|
slug: 'jenny-rostock',
|
||||||
role: 'user',
|
role: 'user',
|
||||||
email: 'user@example.org',
|
email: 'user@example.org',
|
||||||
}),
|
}),
|
||||||
f.create('User', {
|
factory.create('User', {
|
||||||
id: 'u4',
|
id: 'u4',
|
||||||
name: 'Huey',
|
name: 'Huey',
|
||||||
slug: 'huey',
|
slug: 'huey',
|
||||||
role: 'user',
|
role: 'user',
|
||||||
email: 'huey@example.org',
|
email: 'huey@example.org',
|
||||||
}),
|
}),
|
||||||
f.create('User', {
|
factory.create('User', {
|
||||||
id: 'u5',
|
id: 'u5',
|
||||||
name: 'Dewey',
|
name: 'Dewey',
|
||||||
slug: 'dewey',
|
slug: 'dewey',
|
||||||
role: 'user',
|
role: 'user',
|
||||||
email: 'dewey@example.org',
|
email: 'dewey@example.org',
|
||||||
}),
|
}),
|
||||||
f.create('User', {
|
factory.create('User', {
|
||||||
id: 'u6',
|
id: 'u6',
|
||||||
name: 'Louie',
|
name: 'Louie',
|
||||||
slug: 'louie',
|
slug: 'louie',
|
||||||
role: 'user',
|
role: 'user',
|
||||||
email: 'louie@example.org',
|
email: 'louie@example.org',
|
||||||
}),
|
}),
|
||||||
f.create('User', {
|
factory.create('User', {
|
||||||
id: 'u7',
|
id: 'u7',
|
||||||
name: 'Dagobert',
|
name: 'Dagobert',
|
||||||
slug: 'dagobert',
|
slug: 'dagobert',
|
||||||
@ -226,97 +224,97 @@ import { gql } from '../jest/helpers'
|
|||||||
])
|
])
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat1',
|
id: 'cat1',
|
||||||
name: 'Just For Fun',
|
name: 'Just For Fun',
|
||||||
slug: 'just-for-fun',
|
slug: 'just-for-fun',
|
||||||
icon: 'smile',
|
icon: 'smile',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat2',
|
id: 'cat2',
|
||||||
name: 'Happiness & Values',
|
name: 'Happiness & Values',
|
||||||
slug: 'happiness-values',
|
slug: 'happiness-values',
|
||||||
icon: 'heart-o',
|
icon: 'heart-o',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat3',
|
id: 'cat3',
|
||||||
name: 'Health & Wellbeing',
|
name: 'Health & Wellbeing',
|
||||||
slug: 'health-wellbeing',
|
slug: 'health-wellbeing',
|
||||||
icon: 'medkit',
|
icon: 'medkit',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat4',
|
id: 'cat4',
|
||||||
name: 'Environment & Nature',
|
name: 'Environment & Nature',
|
||||||
slug: 'environment-nature',
|
slug: 'environment-nature',
|
||||||
icon: 'tree',
|
icon: 'tree',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat5',
|
id: 'cat5',
|
||||||
name: 'Animal Protection',
|
name: 'Animal Protection',
|
||||||
slug: 'animal-protection',
|
slug: 'animal-protection',
|
||||||
icon: 'paw',
|
icon: 'paw',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat6',
|
id: 'cat6',
|
||||||
name: 'Human Rights & Justice',
|
name: 'Human Rights & Justice',
|
||||||
slug: 'human-rights-justice',
|
slug: 'human-rights-justice',
|
||||||
icon: 'balance-scale',
|
icon: 'balance-scale',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat7',
|
id: 'cat7',
|
||||||
name: 'Education & Sciences',
|
name: 'Education & Sciences',
|
||||||
slug: 'education-sciences',
|
slug: 'education-sciences',
|
||||||
icon: 'graduation-cap',
|
icon: 'graduation-cap',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat8',
|
id: 'cat8',
|
||||||
name: 'Cooperation & Development',
|
name: 'Cooperation & Development',
|
||||||
slug: 'cooperation-development',
|
slug: 'cooperation-development',
|
||||||
icon: 'users',
|
icon: 'users',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat9',
|
id: 'cat9',
|
||||||
name: 'Democracy & Politics',
|
name: 'Democracy & Politics',
|
||||||
slug: 'democracy-politics',
|
slug: 'democracy-politics',
|
||||||
icon: 'university',
|
icon: 'university',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat10',
|
id: 'cat10',
|
||||||
name: 'Economy & Finances',
|
name: 'Economy & Finances',
|
||||||
slug: 'economy-finances',
|
slug: 'economy-finances',
|
||||||
icon: 'money',
|
icon: 'money',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat11',
|
id: 'cat11',
|
||||||
name: 'Energy & Technology',
|
name: 'Energy & Technology',
|
||||||
slug: 'energy-technology',
|
slug: 'energy-technology',
|
||||||
icon: 'flash',
|
icon: 'flash',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat12',
|
id: 'cat12',
|
||||||
name: 'IT, Internet & Data Privacy',
|
name: 'IT, Internet & Data Privacy',
|
||||||
slug: 'it-internet-data-privacy',
|
slug: 'it-internet-data-privacy',
|
||||||
icon: 'mouse-pointer',
|
icon: 'mouse-pointer',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat13',
|
id: 'cat13',
|
||||||
name: 'Art, Culture & Sport',
|
name: 'Art, Culture & Sport',
|
||||||
slug: 'art-culture-sport',
|
slug: 'art-culture-sport',
|
||||||
icon: 'paint-brush',
|
icon: 'paint-brush',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat14',
|
id: 'cat14',
|
||||||
name: 'Freedom of Speech',
|
name: 'Freedom of Speech',
|
||||||
slug: 'freedom-of-speech',
|
slug: 'freedom-of-speech',
|
||||||
icon: 'bullhorn',
|
icon: 'bullhorn',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat15',
|
id: 'cat15',
|
||||||
name: 'Consumption & Sustainability',
|
name: 'Consumption & Sustainability',
|
||||||
slug: 'consumption-sustainability',
|
slug: 'consumption-sustainability',
|
||||||
icon: 'shopping-cart',
|
icon: 'shopping-cart',
|
||||||
}),
|
}),
|
||||||
f.create('Category', {
|
factory.create('Category', {
|
||||||
id: 'cat16',
|
id: 'cat16',
|
||||||
name: 'Global Peace & Nonviolence',
|
name: 'Global Peace & Nonviolence',
|
||||||
slug: 'global-peace-nonviolence',
|
slug: 'global-peace-nonviolence',
|
||||||
@ -325,16 +323,16 @@ import { gql } from '../jest/helpers'
|
|||||||
])
|
])
|
||||||
|
|
||||||
const [environment, nature, democracy, freedom] = await Promise.all([
|
const [environment, nature, democracy, freedom] = await Promise.all([
|
||||||
f.create('Tag', {
|
factory.create('Tag', {
|
||||||
id: 'Environment',
|
id: 'Environment',
|
||||||
}),
|
}),
|
||||||
f.create('Tag', {
|
factory.create('Tag', {
|
||||||
id: 'Nature',
|
id: 'Nature',
|
||||||
}),
|
}),
|
||||||
f.create('Tag', {
|
factory.create('Tag', {
|
||||||
id: 'Democracy',
|
id: 'Democracy',
|
||||||
}),
|
}),
|
||||||
f.create('Tag', {
|
factory.create('Tag', {
|
||||||
id: 'Freedom',
|
id: 'Freedom',
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
@ -649,10 +647,15 @@ import { gql } from '../jest/helpers'
|
|||||||
])
|
])
|
||||||
authenticatedUser = null
|
authenticatedUser = null
|
||||||
|
|
||||||
|
// There is no error logged or the 'try' fails if this mutation is wrong. Why?
|
||||||
const reportMutation = gql`
|
const reportMutation = gql`
|
||||||
mutation($id: ID!, $description: String!) {
|
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
|
||||||
report(description: $description, id: $id) {
|
report(
|
||||||
id
|
resourceId: $resourceId
|
||||||
|
reasonCategory: $reasonCategory
|
||||||
|
reasonDescription: $reasonDescription
|
||||||
|
) {
|
||||||
|
type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -661,22 +664,25 @@ import { gql } from '../jest/helpers'
|
|||||||
mutate({
|
mutate({
|
||||||
mutation: reportMutation,
|
mutation: reportMutation,
|
||||||
variables: {
|
variables: {
|
||||||
description: 'This comment is bigoted',
|
resourceId: 'c1',
|
||||||
id: 'c1',
|
reasonCategory: 'other',
|
||||||
|
reasonDescription: 'This comment is bigoted',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: reportMutation,
|
mutation: reportMutation,
|
||||||
variables: {
|
variables: {
|
||||||
description: 'This post is bigoted',
|
resourceId: 'p1',
|
||||||
id: 'p1',
|
reasonCategory: 'discrimination_etc',
|
||||||
|
reasonDescription: 'This post is bigoted',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: reportMutation,
|
mutation: reportMutation,
|
||||||
variables: {
|
variables: {
|
||||||
description: 'This user is harassing me with bigoted remarks',
|
resourceId: 'u1',
|
||||||
id: 'u1',
|
reasonCategory: 'doxing',
|
||||||
|
reasonDescription: 'This user is harassing me with bigoted remarks',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
@ -684,7 +690,223 @@ import { gql } from '../jest/helpers'
|
|||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
[...Array(30).keys()].map(i => {
|
[...Array(30).keys()].map(i => {
|
||||||
return f.create('User')
|
return factory.create('User')
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(30).keys()].map(() => {
|
||||||
|
return factory.create('Post', {
|
||||||
|
author: jennyRostock,
|
||||||
|
image: faker.image.unsplash.objects(),
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(6).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: jennyRostock,
|
||||||
|
postId: 'p2',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(4).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: jennyRostock,
|
||||||
|
postId: 'p15',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(2).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: jennyRostock,
|
||||||
|
postId: 'p4',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(21).keys()].map(() => {
|
||||||
|
return factory.create('Post', {
|
||||||
|
author: peterLustig,
|
||||||
|
image: faker.image.unsplash.buildings(),
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(3).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: peterLustig,
|
||||||
|
postId: 'p4',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(5).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: peterLustig,
|
||||||
|
postId: 'p14',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(6).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: peterLustig,
|
||||||
|
postId: 'p0',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(11).keys()].map(() => {
|
||||||
|
return factory.create('Post', {
|
||||||
|
author: dewey,
|
||||||
|
image: faker.image.unsplash.food(),
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(7).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: dewey,
|
||||||
|
postId: 'p2',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(5).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: dewey,
|
||||||
|
postId: 'p6',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(2).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: dewey,
|
||||||
|
postId: 'p9',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(16).keys()].map(() => {
|
||||||
|
return factory.create('Post', {
|
||||||
|
author: louie,
|
||||||
|
image: faker.image.unsplash.technology(),
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(4).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: louie,
|
||||||
|
postId: 'p1',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(8).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: louie,
|
||||||
|
postId: 'p10',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(5).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: louie,
|
||||||
|
postId: 'p13',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(45).keys()].map(() => {
|
||||||
|
return factory.create('Post', {
|
||||||
|
author: bobDerBaumeister,
|
||||||
|
image: faker.image.unsplash.people(),
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(2).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: bobDerBaumeister,
|
||||||
|
postId: 'p2',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(3).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: bobDerBaumeister,
|
||||||
|
postId: 'p12',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(7).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: bobDerBaumeister,
|
||||||
|
postId: 'p13',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(8).keys()].map(() => {
|
||||||
|
return factory.create('Post', {
|
||||||
|
author: huey,
|
||||||
|
image: faker.image.unsplash.nature(),
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(6).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: huey,
|
||||||
|
postId: 'p0',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(8).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: huey,
|
||||||
|
postId: 'p13',
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[...Array(9).keys()].map(() => {
|
||||||
|
return factory.create('Comment', {
|
||||||
|
author: huey,
|
||||||
|
postId: 'p15',
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -14,10 +14,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.24.tgz#3ce939cb127fb8aaa3ffc1e90dff9b8af9f2e3dc"
|
resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.24.tgz#3ce939cb127fb8aaa3ffc1e90dff9b8af9f2e3dc"
|
||||||
integrity sha512-8GqG48m1XqyXh4mIZrtB5xOhUwSsh1WsrrsaZQOEYYql3YN9DEu9OOSg0ILzXHZo/h2Q74777YE4YzlArQzQEQ==
|
integrity sha512-8GqG48m1XqyXh4mIZrtB5xOhUwSsh1WsrrsaZQOEYYql3YN9DEu9OOSg0ILzXHZo/h2Q74777YE4YzlArQzQEQ==
|
||||||
|
|
||||||
"@babel/cli@~7.6.2":
|
"@babel/cli@~7.6.4":
|
||||||
version "7.6.2"
|
version "7.6.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.2.tgz#4ce8b5b4b2e4b4c1b7bd841cec62085e2dfc4465"
|
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.4.tgz#9b35a4e15fa7d8f487418aaa8229c8b0bc815f20"
|
||||||
integrity sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ==
|
integrity sha512-tqrDyvPryBM6xjIyKKUwr3s8CzmmYidwgdswd7Uc/Cv0ogZcuS1TYQTLx/eWKP3UbJ6JxZAiYlBZabXm/rtRsQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
commander "^2.8.1"
|
commander "^2.8.1"
|
||||||
convert-source-map "^1.1.0"
|
convert-source-map "^1.1.0"
|
||||||
@ -38,18 +38,18 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.0.0"
|
"@babel/highlight" "^7.0.0"
|
||||||
|
|
||||||
"@babel/core@^7.1.0", "@babel/core@~7.6.2":
|
"@babel/core@^7.1.0", "@babel/core@~7.6.4":
|
||||||
version "7.6.2"
|
version "7.6.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.2.tgz#069a776e8d5e9eefff76236bc8845566bd31dd91"
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.4.tgz#6ebd9fe00925f6c3e177bb726a188b5f578088ff"
|
||||||
integrity sha512-l8zto/fuoZIbncm+01p8zPSDZu/VuuJhAfA7d/AbzM09WR7iVhavvfNDYCNpo1VvLk6E6xgAoP9P+/EMJHuRkQ==
|
integrity sha512-Rm0HGw101GY8FTzpWSyRbki/jzq+/PkNQJ+nSulrdY6gFGOsNseCqD6KHRYe2E+EdzuBdr2pxCp6s4Uk6eJ+XQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.5.5"
|
"@babel/code-frame" "^7.5.5"
|
||||||
"@babel/generator" "^7.6.2"
|
"@babel/generator" "^7.6.4"
|
||||||
"@babel/helpers" "^7.6.2"
|
"@babel/helpers" "^7.6.2"
|
||||||
"@babel/parser" "^7.6.2"
|
"@babel/parser" "^7.6.4"
|
||||||
"@babel/template" "^7.6.0"
|
"@babel/template" "^7.6.0"
|
||||||
"@babel/traverse" "^7.6.2"
|
"@babel/traverse" "^7.6.3"
|
||||||
"@babel/types" "^7.6.0"
|
"@babel/types" "^7.6.3"
|
||||||
convert-source-map "^1.1.0"
|
convert-source-map "^1.1.0"
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
json5 "^2.1.0"
|
json5 "^2.1.0"
|
||||||
@ -58,12 +58,12 @@
|
|||||||
semver "^5.4.1"
|
semver "^5.4.1"
|
||||||
source-map "^0.5.0"
|
source-map "^0.5.0"
|
||||||
|
|
||||||
"@babel/generator@^7.4.0", "@babel/generator@^7.6.2":
|
"@babel/generator@^7.4.0", "@babel/generator@^7.6.3", "@babel/generator@^7.6.4":
|
||||||
version "7.6.2"
|
version "7.6.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03"
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.4.tgz#a4f8437287bf9671b07f483b76e3bb731bc97671"
|
||||||
integrity sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==
|
integrity sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.6.0"
|
"@babel/types" "^7.6.3"
|
||||||
jsesc "^2.5.1"
|
jsesc "^2.5.1"
|
||||||
lodash "^4.17.13"
|
lodash "^4.17.13"
|
||||||
source-map "^0.5.0"
|
source-map "^0.5.0"
|
||||||
@ -241,10 +241,10 @@
|
|||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
"@babel/node@~7.6.2":
|
"@babel/node@~7.6.3":
|
||||||
version "7.6.2"
|
version "7.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.6.2.tgz#a94479f95ee2008342f4847346c8bb8ff2770f44"
|
resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.6.3.tgz#f175ab6718dde55431cbd4d9dee95f65c38be527"
|
||||||
integrity sha512-59UxvVtRpVpL5i0KTcw41FqLNPT/Jc9k/48Rq00wfN49lAIQeRKGwZ6xX1FWlCfcIGP+5l4rfZajORvmYkhfGg==
|
integrity sha512-+nHje5AcE9TPlB/TRGYyOSQyTfhfU/WXniG6SkVf+V5+ibAjEqkH79lYdiEcytBTH4KeSf25IriySXs6TjaLjg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/register" "^7.6.2"
|
"@babel/register" "^7.6.2"
|
||||||
commander "^2.8.1"
|
commander "^2.8.1"
|
||||||
@ -254,10 +254,10 @@
|
|||||||
regenerator-runtime "^0.13.3"
|
regenerator-runtime "^0.13.3"
|
||||||
v8flags "^3.1.1"
|
v8flags "^3.1.1"
|
||||||
|
|
||||||
"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2":
|
"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.3", "@babel/parser@^7.6.4":
|
||||||
version "7.6.2"
|
version "7.6.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81"
|
||||||
integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==
|
integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==
|
||||||
|
|
||||||
"@babel/plugin-proposal-async-generator-functions@^7.2.0":
|
"@babel/plugin-proposal-async-generator-functions@^7.2.0":
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
@ -382,10 +382,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.0.0"
|
"@babel/helper-plugin-utils" "^7.0.0"
|
||||||
|
|
||||||
"@babel/plugin-transform-block-scoping@^7.6.2":
|
"@babel/plugin-transform-block-scoping@^7.6.3":
|
||||||
version "7.6.2"
|
version "7.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.2.tgz#96c33ab97a9ae500cc6f5b19e04a7e6553360a79"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz#6e854e51fbbaa84351b15d4ddafe342f3a5d542a"
|
||||||
integrity sha512-zZT8ivau9LOQQaOGC7bQLQOT4XPkPXgN2ERfUgk1X8ql+mVkLc4E8eKk+FO3o0154kxzqenWCorfmEXpEZcrSQ==
|
integrity sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.0.0"
|
"@babel/helper-plugin-utils" "^7.0.0"
|
||||||
lodash "^4.17.13"
|
lodash "^4.17.13"
|
||||||
@ -507,10 +507,10 @@
|
|||||||
"@babel/helper-module-transforms" "^7.1.0"
|
"@babel/helper-module-transforms" "^7.1.0"
|
||||||
"@babel/helper-plugin-utils" "^7.0.0"
|
"@babel/helper-plugin-utils" "^7.0.0"
|
||||||
|
|
||||||
"@babel/plugin-transform-named-capturing-groups-regex@^7.6.2":
|
"@babel/plugin-transform-named-capturing-groups-regex@^7.6.3":
|
||||||
version "7.6.2"
|
version "7.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.2.tgz#c1ca0bb84b94f385ca302c3932e870b0fb0e522b"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.3.tgz#aaa6e409dd4fb2e50b6e2a91f7e3a3149dbce0cf"
|
||||||
integrity sha512-xBdB+XOs+lgbZc2/4F5BVDVcDNS4tcSKQc96KmlqLEAwz6tpYPEvPdmDfvVG0Ssn8lAhronaRs6Z6KSexIpK5g==
|
integrity sha512-jTkk7/uE6H2s5w6VlMHeWuH+Pcy2lmdwFoeWCVnvIrDUnB5gQqTVI8WfmEAhF2CDEarGrknZcmSFg1+bkfCoSw==
|
||||||
dependencies:
|
dependencies:
|
||||||
regexpu-core "^4.6.0"
|
regexpu-core "^4.6.0"
|
||||||
|
|
||||||
@ -605,18 +605,10 @@
|
|||||||
"@babel/helper-regex" "^7.4.4"
|
"@babel/helper-regex" "^7.4.4"
|
||||||
regexpu-core "^4.6.0"
|
regexpu-core "^4.6.0"
|
||||||
|
|
||||||
"@babel/polyfill@^7.2.3":
|
"@babel/preset-env@~7.6.3":
|
||||||
version "7.6.0"
|
version "7.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.6.0.tgz#6d89203f8b6cd323e8d946e47774ea35dc0619cc"
|
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.3.tgz#9e1bf05a2e2d687036d24c40e4639dc46cef2271"
|
||||||
integrity sha512-q5BZJI0n/B10VaQQvln1IlDK3BTBJFbADx7tv+oXDPIDZuTo37H5Adb9jhlXm/fEN4Y7/64qD9mnrJJG7rmaTw==
|
integrity sha512-CWQkn7EVnwzlOdR5NOm2+pfgSNEZmvGjOhlCHBDq0J8/EStr+G+FvPEiz9B56dR6MoiUFjXhfE4hjLoAKKJtIQ==
|
||||||
dependencies:
|
|
||||||
core-js "^2.6.5"
|
|
||||||
regenerator-runtime "^0.13.2"
|
|
||||||
|
|
||||||
"@babel/preset-env@~7.6.2":
|
|
||||||
version "7.6.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.6.2.tgz#abbb3ed785c7fe4220d4c82a53621d71fc0c75d3"
|
|
||||||
integrity sha512-Ru7+mfzy9M1/YTEtlDS8CD45jd22ngb9tXnn64DvQK3ooyqSw9K4K9DUWmYknTTVk4TqygL9dqCrZgm1HMea/Q==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-module-imports" "^7.0.0"
|
"@babel/helper-module-imports" "^7.0.0"
|
||||||
"@babel/helper-plugin-utils" "^7.0.0"
|
"@babel/helper-plugin-utils" "^7.0.0"
|
||||||
@ -634,7 +626,7 @@
|
|||||||
"@babel/plugin-transform-arrow-functions" "^7.2.0"
|
"@babel/plugin-transform-arrow-functions" "^7.2.0"
|
||||||
"@babel/plugin-transform-async-to-generator" "^7.5.0"
|
"@babel/plugin-transform-async-to-generator" "^7.5.0"
|
||||||
"@babel/plugin-transform-block-scoped-functions" "^7.2.0"
|
"@babel/plugin-transform-block-scoped-functions" "^7.2.0"
|
||||||
"@babel/plugin-transform-block-scoping" "^7.6.2"
|
"@babel/plugin-transform-block-scoping" "^7.6.3"
|
||||||
"@babel/plugin-transform-classes" "^7.5.5"
|
"@babel/plugin-transform-classes" "^7.5.5"
|
||||||
"@babel/plugin-transform-computed-properties" "^7.2.0"
|
"@babel/plugin-transform-computed-properties" "^7.2.0"
|
||||||
"@babel/plugin-transform-destructuring" "^7.6.0"
|
"@babel/plugin-transform-destructuring" "^7.6.0"
|
||||||
@ -649,7 +641,7 @@
|
|||||||
"@babel/plugin-transform-modules-commonjs" "^7.6.0"
|
"@babel/plugin-transform-modules-commonjs" "^7.6.0"
|
||||||
"@babel/plugin-transform-modules-systemjs" "^7.5.0"
|
"@babel/plugin-transform-modules-systemjs" "^7.5.0"
|
||||||
"@babel/plugin-transform-modules-umd" "^7.2.0"
|
"@babel/plugin-transform-modules-umd" "^7.2.0"
|
||||||
"@babel/plugin-transform-named-capturing-groups-regex" "^7.6.2"
|
"@babel/plugin-transform-named-capturing-groups-regex" "^7.6.3"
|
||||||
"@babel/plugin-transform-new-target" "^7.4.4"
|
"@babel/plugin-transform-new-target" "^7.4.4"
|
||||||
"@babel/plugin-transform-object-super" "^7.5.5"
|
"@babel/plugin-transform-object-super" "^7.5.5"
|
||||||
"@babel/plugin-transform-parameters" "^7.4.4"
|
"@babel/plugin-transform-parameters" "^7.4.4"
|
||||||
@ -662,7 +654,7 @@
|
|||||||
"@babel/plugin-transform-template-literals" "^7.4.4"
|
"@babel/plugin-transform-template-literals" "^7.4.4"
|
||||||
"@babel/plugin-transform-typeof-symbol" "^7.2.0"
|
"@babel/plugin-transform-typeof-symbol" "^7.2.0"
|
||||||
"@babel/plugin-transform-unicode-regex" "^7.6.2"
|
"@babel/plugin-transform-unicode-regex" "^7.6.2"
|
||||||
"@babel/types" "^7.6.0"
|
"@babel/types" "^7.6.3"
|
||||||
browserslist "^4.6.0"
|
browserslist "^4.6.0"
|
||||||
core-js-compat "^3.1.1"
|
core-js-compat "^3.1.1"
|
||||||
invariant "^2.2.2"
|
invariant "^2.2.2"
|
||||||
@ -688,7 +680,7 @@
|
|||||||
core-js "^2.6.5"
|
core-js "^2.6.5"
|
||||||
regenerator-runtime "^0.13.2"
|
regenerator-runtime "^0.13.2"
|
||||||
|
|
||||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2":
|
"@babel/runtime@^7.0.0", "@babel/runtime@^7.5.5":
|
||||||
version "7.6.2"
|
version "7.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.2.tgz#c3d6e41b304ef10dcf13777a33e7694ec4a9a6dd"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.2.tgz#c3d6e41b304ef10dcf13777a33e7694ec4a9a6dd"
|
||||||
integrity sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==
|
integrity sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==
|
||||||
@ -704,25 +696,25 @@
|
|||||||
"@babel/parser" "^7.6.0"
|
"@babel/parser" "^7.6.0"
|
||||||
"@babel/types" "^7.6.0"
|
"@babel/types" "^7.6.0"
|
||||||
|
|
||||||
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2":
|
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2", "@babel/traverse@^7.6.3":
|
||||||
version "7.6.2"
|
version "7.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9"
|
||||||
integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==
|
integrity sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.5.5"
|
"@babel/code-frame" "^7.5.5"
|
||||||
"@babel/generator" "^7.6.2"
|
"@babel/generator" "^7.6.3"
|
||||||
"@babel/helper-function-name" "^7.1.0"
|
"@babel/helper-function-name" "^7.1.0"
|
||||||
"@babel/helper-split-export-declaration" "^7.4.4"
|
"@babel/helper-split-export-declaration" "^7.4.4"
|
||||||
"@babel/parser" "^7.6.2"
|
"@babel/parser" "^7.6.3"
|
||||||
"@babel/types" "^7.6.0"
|
"@babel/types" "^7.6.3"
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
lodash "^4.17.13"
|
lodash "^4.17.13"
|
||||||
|
|
||||||
"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0":
|
"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0", "@babel/types@^7.6.3":
|
||||||
version "7.6.1"
|
version "7.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.1.tgz#53abf3308add3ac2a2884d539151c57c4b3ac648"
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09"
|
||||||
integrity sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==
|
integrity sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==
|
||||||
dependencies:
|
dependencies:
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
lodash "^4.17.13"
|
lodash "^4.17.13"
|
||||||
@ -766,10 +758,10 @@
|
|||||||
"@hapi/hoek" "8.x.x"
|
"@hapi/hoek" "8.x.x"
|
||||||
"@hapi/topo" "3.x.x"
|
"@hapi/topo" "3.x.x"
|
||||||
|
|
||||||
"@hapi/joi@^16.1.4":
|
"@hapi/joi@^16.1.7":
|
||||||
version "16.1.4"
|
version "16.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-16.1.4.tgz#b039fe474a0ab838c1a90620c53a208fcef75d99"
|
resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-16.1.7.tgz#360857223a87bb1f5f67691537964c1b4908ed93"
|
||||||
integrity sha512-m7ctezhxjob+dSpXnCNlgAj6rrEpdSsaWu3GWL3g1AybQCU36mlAo9IwGFJwIxD+oHgdO6mYyviYlaejX+qN6g==
|
integrity sha512-anaIgnZhNooG3LJLrTFzgGALTiO97zRA1UkvQHm9KxxoSiIzCozB3RCNCpDnfhTJD72QlrHA8nwGmNgpFFCIeg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@hapi/address" "^2.1.2"
|
"@hapi/address" "^2.1.2"
|
||||||
"@hapi/formula" "^1.2.0"
|
"@hapi/formula" "^1.2.0"
|
||||||
@ -1050,60 +1042,60 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||||
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
||||||
|
|
||||||
"@sentry/core@5.6.2":
|
"@sentry/core@5.7.0":
|
||||||
version "5.6.2"
|
version "5.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.6.2.tgz#8c5477654a83ebe41a72e86a79215deb5025e418"
|
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.7.0.tgz#c2aa5341e703ec7cf2acc69e51971a0b1f7d102a"
|
||||||
integrity sha512-grbjvNmyxP5WSPR6UobN2q+Nss7Hvz+BClBT8QTr7VTEG5q89TwNddn6Ej3bGkaUVbct/GpVlI3XflWYDsnU6Q==
|
integrity sha512-gQel0d7LBSWJGHc7gfZllYAu+RRGD9GcYGmkRfemurmDyDGQDf/sfjiBi8f9QxUc2iFTHnvIR5nMTyf0U3yl3Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/hub" "5.6.1"
|
"@sentry/hub" "5.7.0"
|
||||||
"@sentry/minimal" "5.6.1"
|
"@sentry/minimal" "5.7.0"
|
||||||
"@sentry/types" "5.6.1"
|
"@sentry/types" "5.7.0"
|
||||||
"@sentry/utils" "5.6.1"
|
"@sentry/utils" "5.7.0"
|
||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
|
|
||||||
"@sentry/hub@5.6.1":
|
"@sentry/hub@5.7.0":
|
||||||
version "5.6.1"
|
version "5.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.6.1.tgz#9f355c0abcc92327fbd10b9b939608aa4967bece"
|
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.7.0.tgz#f7c356202a9db1daae82ce7f48ebf1139e4e9d02"
|
||||||
integrity sha512-m+OhkIV5yTAL3R1+XfCwzUQka0UF/xG4py8sEfPXyYIcoOJ2ZTX+1kQJLy8QQJ4RzOBwZA+DzRKP0cgzPJ3+oQ==
|
integrity sha512-qNdYheJ6j4P9Sk0eqIINpJohImmu/+trCwFb4F8BGLQth5iGMVQD6D0YUrgjf4ZaQwfhw9tv4W6VEfF5tyASoA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/types" "5.6.1"
|
"@sentry/types" "5.7.0"
|
||||||
"@sentry/utils" "5.6.1"
|
"@sentry/utils" "5.7.0"
|
||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
|
|
||||||
"@sentry/minimal@5.6.1":
|
"@sentry/minimal@5.7.0":
|
||||||
version "5.6.1"
|
version "5.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.6.1.tgz#09d92b26de0b24555cd50c3c33ba4c3e566009a1"
|
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.7.0.tgz#832d26bcd862c6ea628d48ad199ac7f966a2d907"
|
||||||
integrity sha512-ercCKuBWHog6aS6SsJRuKhJwNdJ2oRQVWT2UAx1zqvsbHT9mSa8ZRjdPHYOtqY3DoXKk/pLUFW/fkmAnpdMqRw==
|
integrity sha512-0sizE2prS9nmfLyVUKmVzFFFqRNr9iorSCCejwnlRe3crqKqjf84tuRSzm6NkZjIyYj9djuuo9l9XN12NLQ/4A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/hub" "5.6.1"
|
"@sentry/hub" "5.7.0"
|
||||||
"@sentry/types" "5.6.1"
|
"@sentry/types" "5.7.0"
|
||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
|
|
||||||
"@sentry/node@^5.6.2":
|
"@sentry/node@^5.7.0":
|
||||||
version "5.6.2"
|
version "5.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.6.2.tgz#4b62f056031da65cad78220d48c546b8bfbfaed7"
|
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.7.0.tgz#153777f06b2fcd346edbff9adbb6b231c7e5fa0a"
|
||||||
integrity sha512-A9CELco6SjF4zt8iS1pO3KdUVI2WVhtTGhSH6X04OVf2en1fimPR+Vs8YVY/04udwd7o+3mI6byT+rS9+/Qzow==
|
integrity sha512-iqQbGAJDBlpQkp1rl9RkDCIfnukr4cOtHPgJPmLY19m/KXIHD2cdKhvbqoCvIPBTIAeSGQIvDT9jD5zT46eoqQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/core" "5.6.2"
|
"@sentry/core" "5.7.0"
|
||||||
"@sentry/hub" "5.6.1"
|
"@sentry/hub" "5.7.0"
|
||||||
"@sentry/types" "5.6.1"
|
"@sentry/types" "5.7.0"
|
||||||
"@sentry/utils" "5.6.1"
|
"@sentry/utils" "5.7.0"
|
||||||
cookie "0.3.1"
|
cookie "^0.3.1"
|
||||||
https-proxy-agent "2.2.1"
|
https-proxy-agent "^3.0.0"
|
||||||
lru_map "0.3.3"
|
lru_map "^0.3.3"
|
||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
|
|
||||||
"@sentry/types@5.6.1":
|
"@sentry/types@5.7.0":
|
||||||
version "5.6.1"
|
version "5.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.6.1.tgz#5915e1ee4b7a678da3ac260c356b1cb91139a299"
|
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.7.0.tgz#e8677e57b40c2c63cad42c02add12b238e647c10"
|
||||||
integrity sha512-Kub8TETefHpdhvtnDj3kKfhCj0u/xn3Zi2zIC7PB11NJHvvPXENx97tciz4roJGp7cLRCJsFqCg4tHXniqDSnQ==
|
integrity sha512-bFRVortg713dE2yJXNFgNe6sNBVVSkpoELLkGPatdVQi0dYc6OggIIX4UZZvkynFx72GwYqO1NOrtUcJY2gmMg==
|
||||||
|
|
||||||
"@sentry/utils@5.6.1":
|
"@sentry/utils@5.7.0":
|
||||||
version "5.6.1"
|
version "5.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.6.1.tgz#69d9e151e50415bc91f2428e3bcca8beb9bc2815"
|
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.7.0.tgz#a6850aa4f5476fa26517cd5c6248f871d8d9939b"
|
||||||
integrity sha512-rfgha+UsHW816GqlSRPlniKqAZylOmQWML2JsujoUP03nPu80zdN43DK9Poy/d9OxBxv0gd5K2n+bFdM2kqLQQ==
|
integrity sha512-XmwQpLqea9mj8x1N7P/l4JvnEb0Rn5Py5OtBgl0ctk090W+GB1uM8rl9mkMf6698o1s1Z8T/tI/QY0yFA5uZXg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/types" "5.6.1"
|
"@sentry/types" "5.7.0"
|
||||||
tslib "^1.9.3"
|
tslib "^1.9.3"
|
||||||
|
|
||||||
"@sindresorhus/is@^0.14.0":
|
"@sindresorhus/is@^0.14.0":
|
||||||
@ -1452,7 +1444,7 @@ acorn@^7.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a"
|
||||||
integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==
|
integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==
|
||||||
|
|
||||||
agent-base@^4.1.0:
|
agent-base@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||||
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
||||||
@ -1531,13 +1523,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.4:
|
apollo-cache-control@^0.8.5:
|
||||||
version "0.8.4"
|
version "0.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.8.4.tgz#a3650d5e4173953e2a3af995bea62147f1ffe4d7"
|
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.8.5.tgz#d4b34691f6ca1cefac9d82b99a94a0815a85a5a8"
|
||||||
integrity sha512-IZ1d3AXZtkZhLYo0kWqTbZ6nqLFaeUvLdMESs+9orMadBZ7mvzcAfBwrhKyCWPGeAAZ/jKv8FtYHybpchHgFAg==
|
integrity sha512-2yQ1vKgJQ54SGkoQS/ZLZrDX3La6cluAYYdruFYJMJtL4zQrSdeOCy11CQliCMYEd6eKNyE70Rpln51QswW2Og==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-server-env "^2.4.3"
|
apollo-server-env "^2.4.3"
|
||||||
graphql-extensions "^0.10.3"
|
graphql-extensions "^0.10.4"
|
||||||
|
|
||||||
apollo-cache-inmemory@~1.6.3:
|
apollo-cache-inmemory@~1.6.3:
|
||||||
version "1.6.3"
|
version "1.6.3"
|
||||||
@ -1580,27 +1572,27 @@ apollo-datasource@^0.6.3:
|
|||||||
apollo-server-caching "^0.5.0"
|
apollo-server-caching "^0.5.0"
|
||||||
apollo-server-env "^2.4.3"
|
apollo-server-env "^2.4.3"
|
||||||
|
|
||||||
apollo-engine-reporting-protobuf@^0.4.0:
|
apollo-engine-reporting-protobuf@^0.4.1:
|
||||||
version "0.4.0"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.4.0.tgz#e34c192d86493b33a73181fd6be75721559111ec"
|
resolved "https://registry.yarnpkg.com/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.4.1.tgz#c0a35bcf28487f87dcbc452b03277f575192f5d2"
|
||||||
integrity sha512-cXHZSienkis8v4RhqB3YG3DkaksqLpcxApRLTpRMs7IXNozgV7CUPYGFyFBEra1ZFgUyHXx4G9MpelV+n2cCfA==
|
integrity sha512-d7vFFZ2oUrvGaN0Hpet8joe2ZG0X0lIGilN+SwgVP38dJnOuadjsaYMyrD9JudGQJg0bJA5wVQfYzcCVy0slrw==
|
||||||
dependencies:
|
dependencies:
|
||||||
protobufjs "^6.8.6"
|
protobufjs "^6.8.6"
|
||||||
|
|
||||||
apollo-engine-reporting@^1.4.6:
|
apollo-engine-reporting@^1.4.7:
|
||||||
version "1.4.6"
|
version "1.4.7"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.4.6.tgz#83af6689c4ab82d1c62c3f5dde7651975508114f"
|
resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.4.7.tgz#6ca69ebdc1c17200969e2e4e07a0be64d748c27e"
|
||||||
integrity sha512-acfb7oFnru/8YQdY4x6+7WJbZfzdVETI8Cl+9ImgUrvUnE8P+f2SsGTKXTC1RuUvve4c56PAvaPgE+z8X1a1Mw==
|
integrity sha512-qsKDz9VkoctFhojM3Nj3nvRBO98t8TS2uTgtiIjUGs3Hln2poKMP6fIQ37Nm2Q2B3JJst76HQtpPwXmRJd1ZUg==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-engine-reporting-protobuf "^0.4.0"
|
apollo-engine-reporting-protobuf "^0.4.1"
|
||||||
apollo-graphql "^0.3.3"
|
apollo-graphql "^0.3.4"
|
||||||
apollo-server-caching "^0.5.0"
|
apollo-server-caching "^0.5.0"
|
||||||
apollo-server-env "^2.4.3"
|
apollo-server-env "^2.4.3"
|
||||||
apollo-server-types "^0.2.4"
|
apollo-server-types "^0.2.5"
|
||||||
async-retry "^1.2.1"
|
async-retry "^1.2.1"
|
||||||
graphql-extensions "^0.10.3"
|
graphql-extensions "^0.10.4"
|
||||||
|
|
||||||
apollo-env@0.5.1:
|
apollo-env@0.5.1, apollo-env@^0.5.1:
|
||||||
version "0.5.1"
|
version "0.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.5.1.tgz#b9b0195c16feadf0fe9fd5563edb0b9b7d9e97d3"
|
resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.5.1.tgz#b9b0195c16feadf0fe9fd5563edb0b9b7d9e97d3"
|
||||||
integrity sha512-fndST2xojgSdH02k5hxk1cbqA9Ti8RX4YzzBoAB4oIe1Puhq7+YlhXGXfXB5Y4XN0al8dLg+5nAkyjNAR2qZTw==
|
integrity sha512-fndST2xojgSdH02k5hxk1cbqA9Ti8RX4YzzBoAB4oIe1Puhq7+YlhXGXfXB5Y4XN0al8dLg+5nAkyjNAR2qZTw==
|
||||||
@ -1617,12 +1609,12 @@ apollo-errors@^1.9.0:
|
|||||||
assert "^1.4.1"
|
assert "^1.4.1"
|
||||||
extendable-error "^0.1.5"
|
extendable-error "^0.1.5"
|
||||||
|
|
||||||
apollo-graphql@^0.3.3:
|
apollo-graphql@^0.3.4:
|
||||||
version "0.3.3"
|
version "0.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-graphql/-/apollo-graphql-0.3.3.tgz#ce1df194f6e547ad3ce1e35b42f9c211766e1658"
|
resolved "https://registry.yarnpkg.com/apollo-graphql/-/apollo-graphql-0.3.4.tgz#c1f68591a4775945441d049eff9323542ab0401f"
|
||||||
integrity sha512-t3CO/xIDVsCG2qOvx2MEbuu4b/6LzQjcBBwiVnxclmmFyAxYCIe7rpPlnLHSq7HyOMlCWDMozjoeWfdqYSaLqQ==
|
integrity sha512-w+Az1qxePH4oQ8jvbhQBl5iEVvqcqynmU++x/M7MM5xqN1C7m1kyIzpN17gybXlTJXY4Oxej2WNURC2/hwpfYw==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-env "0.5.1"
|
apollo-env "^0.5.1"
|
||||||
lodash.sortby "^4.7.0"
|
lodash.sortby "^4.7.0"
|
||||||
|
|
||||||
apollo-link-context@~1.0.19:
|
apollo-link-context@~1.0.19:
|
||||||
@ -1668,26 +1660,26 @@ apollo-server-caching@^0.5.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lru-cache "^5.0.0"
|
lru-cache "^5.0.0"
|
||||||
|
|
||||||
apollo-server-core@^2.9.4:
|
apollo-server-core@^2.9.6:
|
||||||
version "2.9.4"
|
version "2.9.6"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.4.tgz#0404455884951804d23ea64e45514c73afd34e5e"
|
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.6.tgz#b6dc087200633f47ca4f08244d3e606b4d616320"
|
||||||
integrity sha512-6mzipnn9woJxgo/JQFWTlY13svS7HCr0ZsN035eRmKOsXzROfB9ugXcTuc6MP94ICM7TlB/DtJOP+bLX53mijw==
|
integrity sha512-2tHAWQxP7HrETI/BZvg2fem6YlahF9HUp4Y6SSL95WP3uNMOJBlN12yM1y+O2u5K5e4jwdPNaLjoL2A/26XrLw==
|
||||||
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.4"
|
apollo-cache-control "^0.8.5"
|
||||||
apollo-datasource "^0.6.3"
|
apollo-datasource "^0.6.3"
|
||||||
apollo-engine-reporting "^1.4.6"
|
apollo-engine-reporting "^1.4.7"
|
||||||
apollo-server-caching "^0.5.0"
|
apollo-server-caching "^0.5.0"
|
||||||
apollo-server-env "^2.4.3"
|
apollo-server-env "^2.4.3"
|
||||||
apollo-server-errors "^2.3.3"
|
apollo-server-errors "^2.3.3"
|
||||||
apollo-server-plugin-base "^0.6.4"
|
apollo-server-plugin-base "^0.6.5"
|
||||||
apollo-server-types "^0.2.4"
|
apollo-server-types "^0.2.5"
|
||||||
apollo-tracing "^0.8.4"
|
apollo-tracing "^0.8.5"
|
||||||
fast-json-stable-stringify "^2.0.0"
|
fast-json-stable-stringify "^2.0.0"
|
||||||
graphql-extensions "^0.10.3"
|
graphql-extensions "^0.10.4"
|
||||||
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"
|
||||||
@ -1708,10 +1700,10 @@ apollo-server-errors@^2.3.3:
|
|||||||
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.3.tgz#83763b00352c10dc68fbb0d41744ade66de549ff"
|
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.3.tgz#83763b00352c10dc68fbb0d41744ade66de549ff"
|
||||||
integrity sha512-MO4oJ129vuCcbqwr5ZwgxqGGiLz3hCyowz0bstUF7MR+vNGe4oe3DWajC9lv4CxrhcqUHQOeOPViOdIo1IxE3g==
|
integrity sha512-MO4oJ129vuCcbqwr5ZwgxqGGiLz3hCyowz0bstUF7MR+vNGe4oe3DWajC9lv4CxrhcqUHQOeOPViOdIo1IxE3g==
|
||||||
|
|
||||||
apollo-server-express@^2.9.4:
|
apollo-server-express@^2.9.6:
|
||||||
version "2.9.4"
|
version "2.9.6"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.9.4.tgz#ae7ca0b70a644ba9fa5e3ac395d1e2d9a4b23522"
|
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.9.6.tgz#eec2ec43b829b059278e14994d06bd23e43266f9"
|
||||||
integrity sha512-diX9n81E0tIJ0Sy2bHvDGPM9QsFBsZ76Nx/dszinY00ViyWG0yIAYEYWeRbsoKTeNDWWTvlMrh/3Eu2oaCIEhQ==
|
integrity sha512-j80azBeXvLvyZsbqCnus7GH+w8vk+2IOnYzROZu/f0D2roDZtsu1XZkn+aplDJZXMcEXtqB6t4qNpyvV4zY0XQ==
|
||||||
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"
|
||||||
@ -1719,8 +1711,8 @@ apollo-server-express@^2.9.4:
|
|||||||
"@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.4"
|
apollo-server-core "^2.9.6"
|
||||||
apollo-server-types "^0.2.4"
|
apollo-server-types "^0.2.5"
|
||||||
body-parser "^1.18.3"
|
body-parser "^1.18.3"
|
||||||
cors "^2.8.4"
|
cors "^2.8.4"
|
||||||
express "^4.17.1"
|
express "^4.17.1"
|
||||||
@ -1730,47 +1722,47 @@ apollo-server-express@^2.9.4:
|
|||||||
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.4:
|
apollo-server-plugin-base@^0.6.5:
|
||||||
version "0.6.4"
|
version "0.6.5"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.6.4.tgz#63ea4fd0bbb6c4510bc8d0d2ad0a0684c8d0da8c"
|
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.6.5.tgz#eebe27734c51bf6a45b6a9ec8738750b132ffde7"
|
||||||
integrity sha512-4rY+cBAIpQomGWYBtk8hHkLQWHrh5hgIBPQqmhXh00YFdcY+Ob1/cU2/2iqTcIzhtcaezsc8OZ63au6ahSBQqg==
|
integrity sha512-z2ve7HEPWmZI3EzL0iiY9qyt1i0hitT+afN5PzssCw594LB6DfUQWsI14UW+W+gcw8hvl8VQUpXByfUntAx5vw==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-server-types "^0.2.4"
|
apollo-server-types "^0.2.5"
|
||||||
|
|
||||||
apollo-server-testing@~2.9.4:
|
apollo-server-testing@~2.9.6:
|
||||||
version "2.9.4"
|
version "2.9.6"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.9.4.tgz#421783573bdc5cef70dfe574b5193db38a33b5fb"
|
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.9.6.tgz#1cae51c93a8865b85e877e2c9927964cf32625e6"
|
||||||
integrity sha512-qvnA9cXRKqizfYPHBli4LeSKYXwFVsQkGF3eHgofN/RbTqnEBqW7I5L14qDYAjGZg9/Z4alJf69hFE8KPHbT0Q==
|
integrity sha512-pbURQD5VjNFk4GMVVxyCds9rY4/NIqjvjE4tyf1k89RHwMdk+zuVggt/DGudteorZtqAqtsOIHWojMBU4s2klA==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-server-core "^2.9.4"
|
apollo-server-core "^2.9.6"
|
||||||
|
|
||||||
apollo-server-types@^0.2.4:
|
apollo-server-types@^0.2.5:
|
||||||
version "0.2.4"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.2.4.tgz#28864900ffc7f9711a859297c143a833fdb6aa43"
|
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.2.5.tgz#2d63924706ffc1a59480cbbc93e9fe86655a57a5"
|
||||||
integrity sha512-G4FvBVgGQcTW6ZBS2+hvcDQkSfdOIKV+cHADduXA275v+5zl42g+bCaGd/hCCKTDRjmQvObLiMxH/BJ6pDMQgA==
|
integrity sha512-6iJQsPh59FWu4K7ABrVmpnQVgeK8Ockx8BcawBh+saFYWTlVczwcLyGSZPeV1tPSKwFwKZutyEslrYSafcarXQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-engine-reporting-protobuf "^0.4.0"
|
apollo-engine-reporting-protobuf "^0.4.1"
|
||||||
apollo-server-caching "^0.5.0"
|
apollo-server-caching "^0.5.0"
|
||||||
apollo-server-env "^2.4.3"
|
apollo-server-env "^2.4.3"
|
||||||
|
|
||||||
apollo-server@~2.9.4:
|
apollo-server@~2.9.6:
|
||||||
version "2.9.4"
|
version "2.9.6"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.9.4.tgz#564a0d0ec6dbefc86dbabe15bd23a83e48f58314"
|
resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.9.6.tgz#11b6f1128ddb674d2651bb289e0c0fc28aa18653"
|
||||||
integrity sha512-huAgQizkmzUkREixsSJHNM4ZnJ08plkwK70dm36mX9j+yYbc0h9J5b5o4E2Fb9U5PMR8kEVto1dz2rOJ0XPApA==
|
integrity sha512-sDvrGpMQsTGQ9FTkFm3xracrSUi8nFoh3svlD98pe6qb75UDDrXAZgxwQCSOwZ3BkaJ7UkdndfhnruhFstTeMw==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-server-core "^2.9.4"
|
apollo-server-core "^2.9.6"
|
||||||
apollo-server-express "^2.9.4"
|
apollo-server-express "^2.9.6"
|
||||||
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.4:
|
apollo-tracing@^0.8.5:
|
||||||
version "0.8.4"
|
version "0.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.8.4.tgz#0117820c3f0ad3aa6daf7bf13ddbb923cbefa6de"
|
resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.8.5.tgz#f07c4584d95bcf750e44bfe9845e073b03774941"
|
||||||
integrity sha512-DjbFW0IvHicSlTVG+vK+1WINfBMRCdPPHJSW/j65JMir9Oe56WGeqL8qz8hptdUUmLYEb+azvcyyGsJsiR3zpQ==
|
integrity sha512-lZn10/GRBZUlMxVYLghLMFsGcLN0jTYDd98qZfBtxw+wEWUx+PKkZdljDT+XNoOm/kDvEutFGmi5tSLhArIzWQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-server-env "^2.4.3"
|
apollo-server-env "^2.4.3"
|
||||||
graphql-extensions "^0.10.3"
|
graphql-extensions "^0.10.4"
|
||||||
|
|
||||||
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"
|
||||||
@ -1880,12 +1872,12 @@ assert@^1.4.1:
|
|||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
util "0.10.3"
|
util "0.10.3"
|
||||||
|
|
||||||
assertion-error-formatter@^2.0.1:
|
assertion-error-formatter@^3.0.0:
|
||||||
version "2.0.1"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/assertion-error-formatter/-/assertion-error-formatter-2.0.1.tgz#6bbdffaec8e2fa9e2b0eb158bfe353132d7c0a9b"
|
resolved "https://registry.yarnpkg.com/assertion-error-formatter/-/assertion-error-formatter-3.0.0.tgz#be9c8825dee6a8a6c72183d915912d9b57d5d265"
|
||||||
integrity sha512-cjC3jUCh9spkroKue5PDSKH5RFQ/KNuZJhk3GwHYmB/8qqETxLOmMdLH+ohi/VukNzxDlMvIe7zScvLoOdhb6Q==
|
integrity sha512-6YyAVLrEze0kQ7CmJfUgrLHb+Y7XghmL2Ie7ijVa2Y9ynP3LV+VDiwFk62Dn0qtqbmY0BT0ss6p1xxpiF2PYbQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
diff "^3.0.0"
|
diff "^4.0.1"
|
||||||
pad-right "^0.2.2"
|
pad-right "^0.2.2"
|
||||||
repeat-string "^1.6.1"
|
repeat-string "^1.6.1"
|
||||||
|
|
||||||
@ -2073,7 +2065,7 @@ bcryptjs@~2.4.3:
|
|||||||
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
|
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
|
||||||
integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=
|
integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=
|
||||||
|
|
||||||
becke-ch--regex--s0-0-v1--base--pl--lib@^1.2.0:
|
becke-ch--regex--s0-0-v1--base--pl--lib@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz#429ceebbfa5f7e936e78d73fbdc7da7162b20e20"
|
resolved "https://registry.yarnpkg.com/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz#429ceebbfa5f7e936e78d73fbdc7da7162b20e20"
|
||||||
integrity sha1-Qpzuu/pffpNueNc/vcfacWKyDiA=
|
integrity sha1-Qpzuu/pffpNueNc/vcfacWKyDiA=
|
||||||
@ -2328,7 +2320,7 @@ cheerio@~1.0.0-rc.2, cheerio@~1.0.0-rc.3:
|
|||||||
lodash "^4.15.0"
|
lodash "^4.15.0"
|
||||||
parse5 "^3.0.1"
|
parse5 "^3.0.1"
|
||||||
|
|
||||||
chokidar@^2.1.5, chokidar@^2.1.8:
|
chokidar@^2.1.8:
|
||||||
version "2.1.8"
|
version "2.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
|
||||||
integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
|
integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
|
||||||
@ -2487,11 +2479,16 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
|
|||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream "~1.0.0"
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
commander@^2.8.1, commander@^2.9.0, commander@~2.20.0:
|
commander@^2.8.1, commander@~2.20.0:
|
||||||
version "2.20.0"
|
version "2.20.0"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
|
||||||
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
|
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
|
||||||
|
|
||||||
|
commander@^3.0.1:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e"
|
||||||
|
integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==
|
||||||
|
|
||||||
commondir@^1.0.1:
|
commondir@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||||
@ -2568,16 +2565,16 @@ cookie-signature@1.0.6:
|
|||||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||||
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
|
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
|
||||||
|
|
||||||
cookie@0.3.1:
|
|
||||||
version "0.3.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
|
|
||||||
integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
|
|
||||||
|
|
||||||
cookie@0.4.0:
|
cookie@0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
|
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
|
||||||
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
|
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
|
||||||
|
|
||||||
|
cookie@^0.3.1:
|
||||||
|
version "0.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
|
||||||
|
integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
|
||||||
|
|
||||||
cookiejar@^2.1.0:
|
cookiejar@^2.1.0:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
|
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
|
||||||
@ -2626,12 +2623,11 @@ create-error-class@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
capture-stack-trace "^1.0.0"
|
capture-stack-trace "^1.0.0"
|
||||||
|
|
||||||
cross-env@~6.0.2:
|
cross-env@~6.0.3:
|
||||||
version "6.0.2"
|
version "6.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-6.0.2.tgz#2ec3c4b9b90cc074fed375415fc229cb7d6ce612"
|
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-6.0.3.tgz#4256b71e49b3a40637a0ce70768a6ef5c72ae941"
|
||||||
integrity sha512-lA44HlqWCzrv7/l2pY3sfLDvMhXXhx8oztvD6rg34PdCIcP0yk77UwOL2nacsZXlrzPUMtbfagVbK6Itx8pwng==
|
integrity sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.6.2"
|
|
||||||
cross-spawn "^7.0.0"
|
cross-spawn "^7.0.0"
|
||||||
|
|
||||||
cross-fetch@2.2.2:
|
cross-fetch@2.2.2:
|
||||||
@ -2711,49 +2707,48 @@ cssstyle@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
cssom "0.3.x"
|
cssom "0.3.x"
|
||||||
|
|
||||||
cucumber-expressions@^6.0.0:
|
cucumber-expressions@^8.0.1:
|
||||||
version "6.6.2"
|
version "8.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/cucumber-expressions/-/cucumber-expressions-6.6.2.tgz#d89640eccc72a78380b6c210eae36a64e7462b81"
|
resolved "https://registry.yarnpkg.com/cucumber-expressions/-/cucumber-expressions-8.0.1.tgz#47eb87dcb626e90a4672986da1130f3c470b9e3d"
|
||||||
integrity sha512-WcFSVBiWNLJbIcAAC3t/ACU46vaOKfe1UIF5H3qveoq+Y4XQm9j3YwHurQNufRKBBg8nCnpU7Ttsx7egjS3hwA==
|
integrity sha512-g+A+tUEafNofe6ErwvOkqaMvDj9NuOr0GouGotpw4r5yK2d4144o9/6sQpXBr2YXbRy5ItmER/2bzAyDAzhPyQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
becke-ch--regex--s0-0-v1--base--pl--lib "^1.2.0"
|
becke-ch--regex--s0-0-v1--base--pl--lib "^1.4.0"
|
||||||
|
xregexp "^4.2.4"
|
||||||
|
|
||||||
cucumber-tag-expressions@^1.1.1:
|
cucumber-tag-expressions@^2.0.2:
|
||||||
version "1.1.1"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/cucumber-tag-expressions/-/cucumber-tag-expressions-1.1.1.tgz#7f5c7b70009bc2b666591bfe64854578bedee85a"
|
resolved "https://registry.yarnpkg.com/cucumber-tag-expressions/-/cucumber-tag-expressions-2.0.2.tgz#aac27aae3690818ec15235bd056282dad8a2d2b8"
|
||||||
integrity sha1-f1x7cACbwrZmWRv+ZIVFeL7e6Fo=
|
integrity sha512-DohmT4X641KX/sb96bdb7J2kXNcQBPrYmf3Oc5kiHCLfzFMWx/o2kB4JvjvQPZnYuA9lRt6pqtArM5gvUn4uzw==
|
||||||
|
|
||||||
cucumber@~5.1.0:
|
cucumber@~6.0.2:
|
||||||
version "5.1.0"
|
version "6.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/cucumber/-/cucumber-5.1.0.tgz#7b166812c255bec7eac4b0df7007a40d089c895d"
|
resolved "https://registry.yarnpkg.com/cucumber/-/cucumber-6.0.2.tgz#3c4fbf1f76e60ddee79ab58f137a62c897a4d7f0"
|
||||||
integrity sha512-zrl2VYTBRgvxucwV2GKAvLqcfA1Naeax8plPvWgPEzl3SCJiuPPv3WxBHIRHtPYcEdbHDR6oqLpZP4bJ8UIdmA==
|
integrity sha512-yEwPYGvgS2KG6ODdUXQwWcxjyr/l31dmpGJsZSkJIXNLNNmieKVefTpf8zLj6+0V2TCPwkmUZt4+OIXv97duEw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/polyfill" "^7.2.3"
|
assertion-error-formatter "^3.0.0"
|
||||||
assertion-error-formatter "^2.0.1"
|
|
||||||
bluebird "^3.4.1"
|
bluebird "^3.4.1"
|
||||||
cli-table3 "^0.5.1"
|
cli-table3 "^0.5.1"
|
||||||
colors "^1.1.2"
|
colors "^1.1.2"
|
||||||
commander "^2.9.0"
|
commander "^3.0.1"
|
||||||
cross-spawn "^6.0.5"
|
cucumber-expressions "^8.0.1"
|
||||||
cucumber-expressions "^6.0.0"
|
cucumber-tag-expressions "^2.0.2"
|
||||||
cucumber-tag-expressions "^1.1.1"
|
|
||||||
duration "^0.2.1"
|
duration "^0.2.1"
|
||||||
escape-string-regexp "^1.0.5"
|
escape-string-regexp "^2.0.0"
|
||||||
figures "2.0.0"
|
figures "^3.0.0"
|
||||||
gherkin "^5.0.0"
|
gherkin "5.0.0"
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
indent-string "^3.1.0"
|
indent-string "^4.0.0"
|
||||||
is-generator "^1.0.2"
|
is-generator "^1.0.2"
|
||||||
is-stream "^1.1.0"
|
is-stream "^2.0.0"
|
||||||
knuth-shuffle-seeded "^1.0.6"
|
knuth-shuffle-seeded "^1.0.6"
|
||||||
lodash "^4.17.10"
|
lodash "^4.17.14"
|
||||||
mz "^2.4.0"
|
mz "^2.4.0"
|
||||||
progress "^2.0.0"
|
progress "^2.0.0"
|
||||||
resolve "^1.3.3"
|
resolve "^1.3.3"
|
||||||
serialize-error "^3.0.0"
|
serialize-error "^4.1.0"
|
||||||
stack-chain "^2.0.0"
|
stack-chain "^2.0.0"
|
||||||
stacktrace-js "^2.0.0"
|
stacktrace-js "^2.0.0"
|
||||||
string-argv "0.1.1"
|
string-argv "^0.3.0"
|
||||||
title-case "^2.1.1"
|
title-case "^2.1.1"
|
||||||
util-arity "^1.0.2"
|
util-arity "^1.0.2"
|
||||||
verror "^1.9.0"
|
verror "^1.9.0"
|
||||||
@ -2787,10 +2782,10 @@ data-urls@^1.0.0:
|
|||||||
whatwg-mimetype "^2.2.0"
|
whatwg-mimetype "^2.2.0"
|
||||||
whatwg-url "^7.0.0"
|
whatwg-url "^7.0.0"
|
||||||
|
|
||||||
date-fns@2.4.1:
|
date-fns@2.5.0:
|
||||||
version "2.4.1"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.4.1.tgz#b53f9bb65ae6bd9239437035710e01cf383b625e"
|
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.5.0.tgz#b939f17c2902ce81cffe449702ba22c0781b38ec"
|
||||||
integrity sha512-2RhmH/sjDSCYW2F3ZQxOUx/I7PvzXpi89aQL2d3OAxSTwLx6NilATeUbe0menFE3Lu5lFkOFci36ivimwYHHxw==
|
integrity sha512-I6Tkis01//nRcmvMQw/MRE1HAtcuA5Ie6jGPb8bJZJub7494LGOObqkV3ParnsSVviAjk5C8mNKDqYVBzCopWg==
|
||||||
|
|
||||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
@ -2938,10 +2933,10 @@ diff-sequences@^24.9.0:
|
|||||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
|
||||||
integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
|
integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
|
||||||
|
|
||||||
diff@^3.0.0:
|
diff@^4.0.1:
|
||||||
version "3.5.0"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff"
|
||||||
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==
|
||||||
|
|
||||||
dns-prefetch-control@0.2.0:
|
dns-prefetch-control@0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
@ -3036,10 +3031,10 @@ dotenv@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d"
|
||||||
integrity sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=
|
integrity sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=
|
||||||
|
|
||||||
dotenv@~8.1.0:
|
dotenv@~8.2.0:
|
||||||
version "8.1.0"
|
version "8.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.1.0.tgz#d811e178652bfb8a1e593c6dd704ec7e90d85ea2"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
|
||||||
integrity sha512-GUE3gqcDCaMltj2++g6bRQ5rBJWtkWTmqmD0fo1RnnMuUqHNCt2oTPeDnS9n6fKYvlhn7AeBkb38lymBtWBQdA==
|
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
|
||||||
|
|
||||||
duplexer3@^0.1.4:
|
duplexer3@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
@ -3194,6 +3189,11 @@ escape-string-regexp@^1.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||||
|
|
||||||
|
escape-string-regexp@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
|
||||||
|
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
|
||||||
|
|
||||||
escodegen@^1.9.1:
|
escodegen@^1.9.1:
|
||||||
version "1.12.0"
|
version "1.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541"
|
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541"
|
||||||
@ -3206,10 +3206,10 @@ escodegen@^1.9.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
source-map "~0.6.1"
|
source-map "~0.6.1"
|
||||||
|
|
||||||
eslint-config-prettier@~6.3.0:
|
eslint-config-prettier@~6.4.0:
|
||||||
version "6.3.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.3.0.tgz#e73b48e59dc49d950843f3eb96d519e2248286a3"
|
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.4.0.tgz#0a04f147e31d33c6c161b2dd0971418ac52d0477"
|
||||||
integrity sha512-EWaGjlDAZRzVFveh2Jsglcere2KK5CJBhkNSa1xs3KfMUGdRiT7lG089eqPdvlzWHpAqaekubOsOMu8W8Yk71A==
|
integrity sha512-YrKucoFdc7SEko5Sxe4r6ixqXPDP1tunGw91POeZTTRKItf/AMFYt/YLEQtZMkR2LVpAVhcAcZgcWpm1oGPW7w==
|
||||||
dependencies:
|
dependencies:
|
||||||
get-stdin "^6.0.0"
|
get-stdin "^6.0.0"
|
||||||
|
|
||||||
@ -3259,10 +3259,10 @@ eslint-plugin-import@~2.18.2:
|
|||||||
read-pkg-up "^2.0.0"
|
read-pkg-up "^2.0.0"
|
||||||
resolve "^1.11.0"
|
resolve "^1.11.0"
|
||||||
|
|
||||||
eslint-plugin-jest@~22.17.0:
|
eslint-plugin-jest@~22.19.0:
|
||||||
version "22.17.0"
|
version "22.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.17.0.tgz#dc170ec8369cd1bff9c5dd8589344e3f73c88cf6"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.19.0.tgz#0cf90946a8c927d40a2c64458c89bb635d0f2a0b"
|
||||||
integrity sha512-WT4DP4RoGBhIQjv+5D0FM20fAdAUstfYAf/mkufLNTojsfgzc5/IYW22cIg/Q4QBavAZsROQlqppiWDpFZDS8Q==
|
integrity sha512-4zUc3rh36ds0SXdl2LywT4YWA3zRe8sfLhz8bPp8qQPIKvynTTkNGwmSCMpl5d9QiZE2JxSinGF+WD8yU+O0Lg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/experimental-utils" "^1.13.0"
|
"@typescript-eslint/experimental-utils" "^1.13.0"
|
||||||
|
|
||||||
@ -3628,13 +3628,6 @@ feature-policy@0.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/feature-policy/-/feature-policy-0.3.0.tgz#7430e8e54a40da01156ca30aaec1a381ce536069"
|
resolved "https://registry.yarnpkg.com/feature-policy/-/feature-policy-0.3.0.tgz#7430e8e54a40da01156ca30aaec1a381ce536069"
|
||||||
integrity sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==
|
integrity sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==
|
||||||
|
|
||||||
figures@2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
|
|
||||||
integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
|
|
||||||
dependencies:
|
|
||||||
escape-string-regexp "^1.0.5"
|
|
||||||
|
|
||||||
figures@^3.0.0:
|
figures@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9"
|
resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9"
|
||||||
@ -3893,10 +3886,10 @@ getpass@^0.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
gherkin@^5.0.0:
|
gherkin@5.0.0:
|
||||||
version "5.1.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/gherkin/-/gherkin-5.1.0.tgz#684bbb03add24eaf7bdf544f58033eb28fb3c6d5"
|
resolved "https://registry.yarnpkg.com/gherkin/-/gherkin-5.0.0.tgz#96def41198ec3908258b511af74f655a2764d2a1"
|
||||||
integrity sha1-aEu7A63STq9731RPWAM+so+zxtU=
|
integrity sha1-lt70EZjsOQgli1Ea909lWidk0qE=
|
||||||
|
|
||||||
glob-parent@^3.1.0:
|
glob-parent@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
@ -3995,14 +3988,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.3:
|
graphql-extensions@^0.10.4:
|
||||||
version "0.10.3"
|
version "0.10.4"
|
||||||
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.10.3.tgz#9e37f3bd26309c40b03a0be0e63e02b3f99d52ea"
|
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.10.4.tgz#af851b0d44ea6838cf54de9df3cfc6a8e575e571"
|
||||||
integrity sha512-kwU0gUe+Qdfr8iZYT91qrPSwQNgPhB/ClF1m1LEPdxlptk5FhFmjpxAcbMZ8q7j0kjfnbp2IeV1OhRDCEPqz2w==
|
integrity sha512-lE6MroluEYocbR/ICwccv39w+Pz4cBPadJ11z1rJkbZv5wstISEganbDOwl9qN21rcZGiWzh7QUNxUiFUXXEDw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@apollographql/apollo-tools" "^0.4.0"
|
"@apollographql/apollo-tools" "^0.4.0"
|
||||||
apollo-server-env "^2.4.3"
|
apollo-server-env "^2.4.3"
|
||||||
apollo-server-types "^0.2.4"
|
apollo-server-types "^0.2.5"
|
||||||
|
|
||||||
graphql-import@0.7.1:
|
graphql-import@0.7.1:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
@ -4339,12 +4332,12 @@ http-signature@~1.2.0:
|
|||||||
jsprim "^1.2.2"
|
jsprim "^1.2.2"
|
||||||
sshpk "^1.7.0"
|
sshpk "^1.7.0"
|
||||||
|
|
||||||
https-proxy-agent@2.2.1:
|
https-proxy-agent@^3.0.0:
|
||||||
version "2.2.1"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
|
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-3.0.0.tgz#0106efa5d63d6d6f3ab87c999fa4877a3fd1ff97"
|
||||||
integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==
|
integrity sha512-y4jAxNEihqvBI5F3SaO2rtsjIOnnNA8sEbuiP+UhJZJHeM2NRm6c09ax2tgqme+SgUUvjao2fJXF4h3D6Cb2HQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base "^4.1.0"
|
agent-base "^4.3.0"
|
||||||
debug "^3.1.0"
|
debug "^3.1.0"
|
||||||
|
|
||||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
|
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
|
||||||
@ -4412,11 +4405,16 @@ imurmurhash@^0.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||||
|
|
||||||
indent-string@^3.1.0, indent-string@^3.2.0:
|
indent-string@^3.2.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
|
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
|
||||||
integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
|
integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
|
||||||
|
|
||||||
|
indent-string@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||||
|
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
|
||||||
|
|
||||||
inflight@^1.0.4:
|
inflight@^1.0.4:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||||
@ -4772,6 +4770,11 @@ is-stream@^1.0.0, is-stream@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
|
||||||
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
|
||||||
|
|
||||||
|
is-stream@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
|
||||||
|
integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
|
||||||
|
|
||||||
is-symbol@^1.0.2:
|
is-symbol@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
|
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
|
||||||
@ -5591,7 +5594,7 @@ lodash.unescape@4.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
|
resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c"
|
||||||
integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=
|
integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=
|
||||||
|
|
||||||
lodash@4.17.15, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.11, lodash@~4.17.14, lodash@~4.17.15:
|
lodash@4.17.15, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.11, lodash@~4.17.14, lodash@~4.17.15:
|
||||||
version "4.17.15"
|
version "4.17.15"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||||
@ -5638,7 +5641,7 @@ lru-cache@^5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
yallist "^3.0.2"
|
yallist "^3.0.2"
|
||||||
|
|
||||||
lru_map@0.3.3:
|
lru_map@^0.3.3:
|
||||||
version "0.3.3"
|
version "0.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
|
resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
|
||||||
integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=
|
integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=
|
||||||
@ -6179,23 +6182,23 @@ nodemailer-html-to-text@^3.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
html-to-text "^5.1.1"
|
html-to-text "^5.1.1"
|
||||||
|
|
||||||
nodemailer@^6.3.0:
|
nodemailer@^6.3.1:
|
||||||
version "6.3.0"
|
version "6.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.3.0.tgz#a89b0c62d3937bdcdeecbf55687bd7911b627e12"
|
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.3.1.tgz#2784beebac6b9f014c424c54dbdcc5c4d1221346"
|
||||||
integrity sha512-TEHBNBPHv7Ie/0o3HXnb7xrPSSQmH1dXwQKRaMKDBGt/ZN54lvDVujP6hKkO/vjkIYL9rK8kHSG11+G42Nhxuw==
|
integrity sha512-j0BsSyaMlyadEDEypK/F+xlne2K5m6wzPYMXS/yxKI0s7jmT1kBx6GEKRVbZmyYfKOsjkeC/TiMVDJBI/w5gMQ==
|
||||||
|
|
||||||
nodemon@~1.19.3:
|
nodemon@~1.19.4:
|
||||||
version "1.19.3"
|
version "1.19.4"
|
||||||
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.3.tgz#db71b3e62aef2a8e1283a9fa00164237356102c0"
|
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.4.tgz#56db5c607408e0fdf8920d2b444819af1aae0971"
|
||||||
integrity sha512-TBNKRmJykEbxpTniZBusqRrUTHIEqa2fpecbTQDQj1Gxjth7kKAPP296ztR0o5gPUWsiYbuEbt73/+XMYab1+w==
|
integrity sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar "^2.1.5"
|
chokidar "^2.1.8"
|
||||||
debug "^3.1.0"
|
debug "^3.2.6"
|
||||||
ignore-by-default "^1.0.1"
|
ignore-by-default "^1.0.1"
|
||||||
minimatch "^3.0.4"
|
minimatch "^3.0.4"
|
||||||
pstree.remy "^1.1.6"
|
pstree.remy "^1.1.7"
|
||||||
semver "^5.5.0"
|
semver "^5.7.1"
|
||||||
supports-color "^5.2.0"
|
supports-color "^5.5.0"
|
||||||
touch "^3.1.0"
|
touch "^3.1.0"
|
||||||
undefsafe "^2.0.2"
|
undefsafe "^2.0.2"
|
||||||
update-notifier "^2.5.0"
|
update-notifier "^2.5.0"
|
||||||
@ -6892,7 +6895,7 @@ psl@^1.1.24, psl@^1.1.28:
|
|||||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.3.0.tgz#e1ebf6a3b5564fa8376f3da2275da76d875ca1bd"
|
resolved "https://registry.yarnpkg.com/psl/-/psl-1.3.0.tgz#e1ebf6a3b5564fa8376f3da2275da76d875ca1bd"
|
||||||
integrity sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==
|
integrity sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==
|
||||||
|
|
||||||
pstree.remy@^1.1.6:
|
pstree.remy@^1.1.7:
|
||||||
version "1.1.7"
|
version "1.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.7.tgz#c76963a28047ed61542dc361aa26ee55a7fa15f3"
|
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.7.tgz#c76963a28047ed61542dc361aa26ee55a7fa15f3"
|
||||||
integrity sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==
|
integrity sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==
|
||||||
@ -7404,7 +7407,7 @@ semver-diff@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
semver "^5.0.3"
|
semver "^5.0.3"
|
||||||
|
|
||||||
"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0:
|
"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
@ -7438,10 +7441,12 @@ send@0.17.1:
|
|||||||
range-parser "~1.2.1"
|
range-parser "~1.2.1"
|
||||||
statuses "~1.5.0"
|
statuses "~1.5.0"
|
||||||
|
|
||||||
serialize-error@^3.0.0:
|
serialize-error@^4.1.0:
|
||||||
version "3.0.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-3.0.0.tgz#80100282b09be33c611536f50033481cb9cc87cf"
|
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-4.1.0.tgz#63e1e33ede20bcd89d9f0528ea4c15fbf0f2b78a"
|
||||||
integrity sha512-+y3nkkG/go1Vdw+2f/+XUXM1DXX1XcxTl99FfiD/OEPUNw4uo0i6FKABfTAN5ZcgGtjTRZcEbxcE/jtXbEY19A==
|
integrity sha512-5j9GgyGsP9vV9Uj1S0lDCvlsd+gc2LEPVK7HHHte7IyPwOD4lVQFeaX143gx3U5AnoCi+wbcb3mvaxVysjpxEw==
|
||||||
|
dependencies:
|
||||||
|
type-fest "^0.3.0"
|
||||||
|
|
||||||
serve-static@1.14.1:
|
serve-static@1.14.1:
|
||||||
version "1.14.1"
|
version "1.14.1"
|
||||||
@ -7731,10 +7736,10 @@ streamsearch@0.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
||||||
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
||||||
|
|
||||||
string-argv@0.1.1:
|
string-argv@^0.3.0:
|
||||||
version "0.1.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.1.1.tgz#66bd5ae3823708eaa1916fa5412703150d4ddfaf"
|
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
|
||||||
integrity sha512-El1Va5ehZ0XTj3Ekw4WFidXvTmt9SrC0+eigdojgtJMVtPkF0qbBe9fyNSl9eQf+kUHnTSQxdQYzuHfZy8V+DQ==
|
integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==
|
||||||
|
|
||||||
string-length@^2.0.0:
|
string-length@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -7885,7 +7890,7 @@ supports-color@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^2.0.0"
|
has-flag "^2.0.0"
|
||||||
|
|
||||||
supports-color@^5.2.0, supports-color@^5.3.0:
|
supports-color@^5.3.0, supports-color@^5.5.0:
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||||
|
|||||||
@ -107,6 +107,11 @@ Then(`I can't see the moderation menu item`, () => {
|
|||||||
When(/^I confirm the reporting dialog .*:$/, message => {
|
When(/^I confirm the reporting dialog .*:$/, message => {
|
||||||
cy.contains(message) // wait for element to become visible
|
cy.contains(message) // wait for element to become visible
|
||||||
cy.get('.ds-modal').within(() => {
|
cy.get('.ds-modal').within(() => {
|
||||||
|
cy.get('.ds-radio-option-label')
|
||||||
|
.first()
|
||||||
|
.click({
|
||||||
|
force: true
|
||||||
|
})
|
||||||
cy.get('button')
|
cy.get('button')
|
||||||
.contains('Report')
|
.contains('Report')
|
||||||
.click()
|
.click()
|
||||||
@ -114,21 +119,22 @@ When(/^I confirm the reporting dialog .*:$/, message => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Given('somebody reported the following posts:', table => {
|
Given('somebody reported the following posts:', table => {
|
||||||
table.hashes().forEach(({ id }) => {
|
table.hashes().forEach(({ submitterEmail, resourceId, reasonCategory, reasonDescription }) => {
|
||||||
const submitter = {
|
const submitter = {
|
||||||
email: `submitter${id}@example.org`,
|
email: submitterEmail,
|
||||||
password: '1234'
|
password: '1234'
|
||||||
}
|
}
|
||||||
cy.factory()
|
cy.factory()
|
||||||
.create('User', submitter)
|
.create('User', submitter)
|
||||||
.authenticateAs(submitter)
|
.authenticateAs(submitter)
|
||||||
.mutate(`mutation($id: ID!, $description: String!) {
|
.mutate(`mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
|
||||||
report(description: $description, id: $id) {
|
report(resourceId: $resourceId, reasonCategory: $reasonCategory, reasonDescription: $reasonDescription) {
|
||||||
id
|
type
|
||||||
}
|
}
|
||||||
}`, {
|
}`, {
|
||||||
id,
|
resourceId,
|
||||||
description: 'Offensive content'
|
reasonCategory,
|
||||||
|
reasonDescription
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -50,8 +50,8 @@ Feature: Report and Moderate
|
|||||||
|
|
||||||
Scenario: Review reported content
|
Scenario: Review reported content
|
||||||
Given somebody reported the following posts:
|
Given somebody reported the following posts:
|
||||||
| id |
|
| submitterEmail | resourceId | reasonCategory | reasonDescription |
|
||||||
| p1 |
|
| p1.submitter@example.org | p1 | discrimination_etc | Offensive content |
|
||||||
And I am logged in with a "moderator" role
|
And I am logged in with a "moderator" role
|
||||||
When I click on the avatar menu in the top right corner
|
When I click on the avatar menu in the top right corner
|
||||||
And I click on "Moderation"
|
And I click on "Moderation"
|
||||||
@ -60,8 +60,8 @@ Feature: Report and Moderate
|
|||||||
|
|
||||||
Scenario: Review reported posts of a user who's blocked a moderator
|
Scenario: Review reported posts of a user who's blocked a moderator
|
||||||
Given somebody reported the following posts:
|
Given somebody reported the following posts:
|
||||||
| id |
|
| submitterEmail | resourceId | reasonCategory | reasonDescription |
|
||||||
| p2 |
|
| p2.submitter@example.org | p2 | other | Offensive content |
|
||||||
And my user account has the role "moderator"
|
And my user account has the role "moderator"
|
||||||
And there is an annoying user who has blocked me
|
And there is an annoying user who has blocked me
|
||||||
And I am logged in
|
And I am logged in
|
||||||
|
|||||||
57
deployment/volumes/neo4j-online-backup/README.md
Normal file
57
deployment/volumes/neo4j-online-backup/README.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# Backup (online)
|
||||||
|
|
||||||
|
## Online backups are only avaible with a Neo4j Enterprise and a license, see https://neo4j.com/licensing/ for the different licenses available
|
||||||
|
|
||||||
|
This tutorial explains how to carry out an online backup of your Neo4J
|
||||||
|
database in a kubernetes cluster.
|
||||||
|
|
||||||
|
One of the benefits of doing an online backup is that the Neo4j database does not need to be stopped, so there is no downtime. Read [the docs](https://neo4j.com/docs/operations-manual/current/backup/performing/)
|
||||||
|
|
||||||
|
To use Neo4j Enterprise you must add this line to your configmap, if using, or your deployment `nitro-neo4j` env.
|
||||||
|
|
||||||
|
```
|
||||||
|
NEO4J_ACCEPT_LICENSE_AGREEMENT: "yes"
|
||||||
|
```
|
||||||
|
## Create a Backup in Kubernetes
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Backup the database with one command, this will get the nitro-neo4j pod, ssh into it, and run the backup command
|
||||||
|
kubectl -n=human-connection exec -it $(kubectl -n=human-connection get pods | grep nitro-neo4j | awk '{ print $1 }') -- neo4j-admin backup --backup-dir=/var/lib/neo4j --name=neo4j-backup
|
||||||
|
# Download the file from the pod to your computer.
|
||||||
|
kubectl cp human-connection/$(kubectl -n=human-connection get pods | grep nitro-neo4j | awk '{ print $1 }'):/var/lib/neo4j/neo4j-backup ./neo4j-backup/
|
||||||
|
```
|
||||||
|
|
||||||
|
You should now have a backup of the database locally. If you want, you can simulate disaster recovery by sshing into the nitro-neo4j pod, deleting all data and restoring from backup
|
||||||
|
|
||||||
|
## Disaster where database data is gone somehow
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubectl -n=human-connection exec -it $(kubectl -n=human-connection get pods | grep nitro-neo4j |awk '{ print $1 }') bash
|
||||||
|
# Enter cypher-shell
|
||||||
|
cypher-shell
|
||||||
|
# Delete all data
|
||||||
|
> MATCH (n) DETACH DELETE (n);
|
||||||
|
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
## Restore a backup in Kubernetes
|
||||||
|
|
||||||
|
Restoration must be done while the database is not running, see [our docs](https://docs.human-connection.org/human-connection/deployment/volumes/neo4j-offline-backup#stop-and-restart-neo-4-j-database-in-kubernetes) for how to stop the database, but keep the container running
|
||||||
|
|
||||||
|
After, you have stopped the database, and have the pod running, you can restore the database by running these commands:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubectl --namespace=human-connection get pods
|
||||||
|
# Copy the ID of the pod running Neo4J.
|
||||||
|
# Then upload your local backup to the pod. Note that once the pod gets deleted
|
||||||
|
# e.g. if you change the deployment, the backup file is gone with it.
|
||||||
|
kubectl cp ./neo4j-backup/ human-connection/<POD-ID>:/root/
|
||||||
|
kubectl --namespace=human-connection exec -it <POD-ID> bash
|
||||||
|
# Once you're in the pod restore the backup and overwrite the default database
|
||||||
|
# called `graph.db` with `--force`.
|
||||||
|
# This will delete all existing data in database `graph.db`!
|
||||||
|
neo4j-admin restore --from=/root/neo4j-backup --force
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
Revert your changes to deployment `nitro-neo4j` which will restart the database.
|
||||||
@ -15,6 +15,7 @@ services:
|
|||||||
- ./webapp:/nitro-web
|
- ./webapp:/nitro-web
|
||||||
environment:
|
environment:
|
||||||
- NUXT_BUILD=/tmp/nuxt # avoid file permission issues when `rm -rf .nuxt/`
|
- NUXT_BUILD=/tmp/nuxt # avoid file permission issues when `rm -rf .nuxt/`
|
||||||
|
- PUBLIC_REGISTRATION=true
|
||||||
command: yarn run dev
|
command: yarn run dev
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
@ -28,6 +29,7 @@ services:
|
|||||||
- SMTP_PORT=25
|
- SMTP_PORT=25
|
||||||
- SMTP_IGNORE_TLS=true
|
- SMTP_IGNORE_TLS=true
|
||||||
- "DEBUG=${DEBUG}"
|
- "DEBUG=${DEBUG}"
|
||||||
|
- PUBLIC_REGISTRATION=true
|
||||||
maintenance:
|
maintenance:
|
||||||
image: humanconnection/maintenance:latest
|
image: humanconnection/maintenance:latest
|
||||||
build:
|
build:
|
||||||
|
|||||||
@ -57,6 +57,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- NEO4J_AUTH=none
|
- NEO4J_AUTH=none
|
||||||
- NEO4J_dbms_security_procedures_unrestricted=algo.*,apoc.*
|
- NEO4J_dbms_security_procedures_unrestricted=algo.*,apoc.*
|
||||||
|
- NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
|
||||||
ports:
|
ports:
|
||||||
- 7687:7687
|
- 7687:7687
|
||||||
- 7474:7474
|
- 7474:7474
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM neo4j:3.5.11
|
FROM neo4j:3.5.11-enterprise
|
||||||
LABEL Description="Neo4J database of the Social Network Human-Connection.org with preinstalled database constraints and indices" Vendor="Human Connection gGmbH" Version="0.0.1" Maintainer="Human Connection gGmbH (developer@human-connection.org)"
|
LABEL Description="Neo4J database of the Social Network Human-Connection.org with preinstalled database constraints and indices" Vendor="Human Connection gGmbH" Version="0.0.1" Maintainer="Human Connection gGmbH (developer@human-connection.org)"
|
||||||
|
|
||||||
ARG BUILD_COMMIT
|
ARG BUILD_COMMIT
|
||||||
|
|||||||
26
neo4j/change_report_node_to_relationship.sh
Executable file
26
neo4j/change_report_node_to_relationship.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
ENV_FILE=$(dirname "$0")/.env
|
||||||
|
[[ -f "$ENV_FILE" ]] && source "$ENV_FILE"
|
||||||
|
|
||||||
|
if [ -z "$NEO4J_USERNAME" ] || [ -z "$NEO4J_PASSWORD" ]; then
|
||||||
|
echo "Please set NEO4J_USERNAME and NEO4J_PASSWORD environment variables."
|
||||||
|
echo "Database manipulation is not possible without connecting to the database."
|
||||||
|
echo "E.g. you could \`cp .env.template .env\` unless you run the script in a docker container"
|
||||||
|
fi
|
||||||
|
|
||||||
|
until echo 'RETURN "Connection successful" as info;' | cypher-shell
|
||||||
|
do
|
||||||
|
echo "Connecting to neo4j failed, trying again..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "
|
||||||
|
MATCH (submitter:User)-[:REPORTED]->(report:Report)-[:REPORTED]->(resource)
|
||||||
|
DETACH DELETE report
|
||||||
|
CREATE (submitter)-[reported:REPORTED]->(resource)
|
||||||
|
SET reported.createdAt = toString(datetime())
|
||||||
|
SET reported.reasonCategory = 'other'
|
||||||
|
SET reported.reasonDescription = '!!! Created automatically to ensure database consistency! Creation date is when the database manipulation happened.'
|
||||||
|
RETURN reported;
|
||||||
|
" | cypher-shell
|
||||||
12
package.json
12
package.json
@ -21,17 +21,21 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"codecov": "^3.6.1",
|
"codecov": "^3.6.1",
|
||||||
"cross-env": "^6.0.2",
|
"cross-env": "^6.0.3",
|
||||||
"cypress": "^3.4.1",
|
"cypress": "^3.4.1",
|
||||||
"cypress-cucumber-preprocessor": "^1.16.0",
|
"cypress-cucumber-preprocessor": "^1.16.2",
|
||||||
"cypress-file-upload": "^3.3.4",
|
"cypress-file-upload": "^3.3.4",
|
||||||
"cypress-plugin-retries": "^1.3.0",
|
"cypress-plugin-retries": "^1.3.0",
|
||||||
"dotenv": "^8.1.0",
|
"date-fns": "^2.5.0",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
"faker": "Marak/faker.js#master",
|
"faker": "Marak/faker.js#master",
|
||||||
"graphql-request": "^1.8.2",
|
"graphql-request": "^1.8.2",
|
||||||
"neo4j-driver": "^1.7.6",
|
"neo4j-driver": "^1.7.6",
|
||||||
"neode": "^0.3.3",
|
"neode": "^0.3.6",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"slug": "^1.1.0"
|
"slug": "^1.1.0"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"set-value": "^2.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
MAPBOX_TOKEN="pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.KZ8KK9l70omjXbEkkbHGsQ"
|
MAPBOX_TOKEN="pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.KZ8KK9l70omjXbEkkbHGsQ"
|
||||||
SENTRY_DSN_WEBAPP=
|
SENTRY_DSN_WEBAPP=
|
||||||
COMMIT=
|
COMMIT=
|
||||||
|
PUBLIC_REGISTRATION=false
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:12.10.0-alpine as base
|
FROM node:12.12.0-alpine as base
|
||||||
LABEL Description="Web Frontend of the Social Network Human-Connection.org" Vendor="Human-Connection gGmbH" Version="0.0.1" Maintainer="Human-Connection gGmbH (developer@human-connection.org)"
|
LABEL Description="Web Frontend of the Social Network Human-Connection.org" Vendor="Human-Connection gGmbH" Version="0.0.1" Maintainer="Human-Connection gGmbH (developer@human-connection.org)"
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:12.10.0-alpine as build
|
FROM node:12.12.0-alpine as build
|
||||||
LABEL Description="Web Frontend of the Social Network Human-Connection.org" Vendor="Human-Connection gGmbH" Version="0.0.1" Maintainer="Human-Connection gGmbH (developer@human-connection.org)"
|
LABEL Description="Web Frontend of the Social Network Human-Connection.org" Vendor="Human-Connection gGmbH" Version="0.0.1" Maintainer="Human-Connection gGmbH (developer@human-connection.org)"
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|||||||
@ -10,10 +10,15 @@
|
|||||||
</ds-card>
|
</ds-card>
|
||||||
</div>
|
</div>
|
||||||
<div v-else :class="{ comment: true, 'disabled-content': comment.deleted || comment.disabled }">
|
<div v-else :class="{ comment: true, 'disabled-content': comment.deleted || comment.disabled }">
|
||||||
<ds-card :id="anchor">
|
<ds-card :id="anchor" :class="{ 'comment--target': isTarget }">
|
||||||
<ds-space margin-bottom="small" margin-top="small">
|
<ds-space margin-bottom="small" margin-top="small">
|
||||||
<hc-user :user="author" :date-time="comment.createdAt" />
|
<hc-user :user="author" :date-time="comment.createdAt">
|
||||||
<!-- Content Menu (can open Modals) -->
|
<template v-slot:dateTime>
|
||||||
|
<ds-text v-if="comment.createdAt !== comment.updatedAt">
|
||||||
|
({{ $t('comment.edited') }})
|
||||||
|
</ds-text>
|
||||||
|
</template>
|
||||||
|
</hc-user>
|
||||||
<client-only>
|
<client-only>
|
||||||
<content-menu
|
<content-menu
|
||||||
v-show="!openEditCommentMenu"
|
v-show="!openEditCommentMenu"
|
||||||
@ -38,35 +43,15 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<content-viewer
|
<content-viewer :content="commentContent" class="comment-content" />
|
||||||
v-if="$filters.removeHtml(comment.content).length < 180"
|
<button
|
||||||
:content="comment.content"
|
v-if="isLongComment"
|
||||||
class="padding-left"
|
type="button"
|
||||||
/>
|
class="collapse-button"
|
||||||
<div v-else class="show-more-or-less-div">
|
@click="isCollapsed = !isCollapsed"
|
||||||
<content-viewer
|
>
|
||||||
v-if="isCollapsed"
|
{{ isCollapsed ? $t('comment.show.more') : $t('comment.show.less') }}
|
||||||
:content="$filters.truncate(comment.content, 180)"
|
</button>
|
||||||
class="padding-left text-align-left"
|
|
||||||
/>
|
|
||||||
<span class="show-more-or-less">
|
|
||||||
<a v-if="isCollapsed" class="padding-left" @click="isCollapsed = !isCollapsed">
|
|
||||||
{{ $t('comment.show.more') }}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<content-viewer
|
|
||||||
v-if="!isCollapsed"
|
|
||||||
:content="comment.content"
|
|
||||||
class="padding-left text-align-left"
|
|
||||||
/>
|
|
||||||
<div class="show-more-or-less-div">
|
|
||||||
<span class="show-more-or-less">
|
|
||||||
<a v-if="!isCollapsed" class="padding-left" @click="isCollapsed = !isCollapsed">
|
|
||||||
{{ $t('comment.show.less') }}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<ds-space margin-bottom="small" />
|
<ds-space margin-bottom="small" />
|
||||||
</ds-card>
|
</ds-card>
|
||||||
@ -75,6 +60,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { COMMENT_MAX_UNTRUNCATED_LENGTH, COMMENT_TRUNCATE_TO_LENGTH } from '~/constants/comment'
|
||||||
import HcUser from '~/components/User/User'
|
import HcUser from '~/components/User/User'
|
||||||
import ContentMenu from '~/components/ContentMenu'
|
import ContentMenu from '~/components/ContentMenu'
|
||||||
import ContentViewer from '~/components/Editor/ContentViewer'
|
import ContentViewer from '~/components/Editor/ContentViewer'
|
||||||
@ -84,9 +70,14 @@ import scrollToAnchor from '~/mixins/scrollToAnchor.js'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [scrollToAnchor],
|
mixins: [scrollToAnchor],
|
||||||
data: function() {
|
data() {
|
||||||
|
const anchor = `commentId-${this.comment.id}`
|
||||||
|
const isTarget = this.routeHash === `#${anchor}`
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isCollapsed: true,
|
anchor,
|
||||||
|
isTarget,
|
||||||
|
isCollapsed: !isTarget,
|
||||||
openEditCommentMenu: false,
|
openEditCommentMenu: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -97,13 +88,9 @@ export default {
|
|||||||
HcCommentForm,
|
HcCommentForm,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
post: { type: Object, default: () => {} },
|
routeHash: { type: String, default: () => '' },
|
||||||
comment: {
|
post: { type: Object, default: () => ({}) },
|
||||||
type: Object,
|
comment: { type: Object, default: () => ({}) },
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dateTime: { type: [Date, String], default: null },
|
dateTime: { type: [Date, String], default: null },
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -111,8 +98,15 @@ export default {
|
|||||||
user: 'auth/user',
|
user: 'auth/user',
|
||||||
isModerator: 'auth/isModerator',
|
isModerator: 'auth/isModerator',
|
||||||
}),
|
}),
|
||||||
anchor() {
|
isLongComment() {
|
||||||
return `commentId-${this.comment.id}`
|
return this.$filters.removeHtml(this.comment.content).length > COMMENT_MAX_UNTRUNCATED_LENGTH
|
||||||
|
},
|
||||||
|
commentContent() {
|
||||||
|
if (this.isLongComment && this.isCollapsed) {
|
||||||
|
return this.$filters.truncate(this.comment.content, COMMENT_TRUNCATE_TO_LENGTH)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.comment.content
|
||||||
},
|
},
|
||||||
displaysComment() {
|
displaysComment() {
|
||||||
return !this.unavailable || this.isModerator
|
return !this.unavailable || this.isModerator
|
||||||
@ -177,26 +171,37 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.collapse-button {
|
||||||
|
// TODO: move this to css resets
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
float: right;
|
||||||
|
padding: 0 16px 16px 16px;
|
||||||
|
color: $color-primary;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-content {
|
||||||
|
padding-left: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
.float-right {
|
.float-right {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.padding-left {
|
@keyframes highlight {
|
||||||
padding-left: 40px;
|
0% {
|
||||||
|
border: 1px solid $color-primary;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-align-left {
|
.comment--target {
|
||||||
text-align: left;
|
animation: highlight 4s ease;
|
||||||
}
|
|
||||||
|
|
||||||
div.show-more-or-less-div {
|
|
||||||
text-align: right;
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.show-more-or-less {
|
|
||||||
display: block;
|
|
||||||
margin: 0px 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
:key="comment.id"
|
:key="comment.id"
|
||||||
:comment="comment"
|
:comment="comment"
|
||||||
:post="post"
|
:post="post"
|
||||||
|
:routeHash="routeHash"
|
||||||
@deleteComment="updateCommentList"
|
@deleteComment="updateCommentList"
|
||||||
@updateComment="updateCommentList"
|
@updateComment="updateCommentList"
|
||||||
/>
|
/>
|
||||||
@ -38,6 +39,7 @@ export default {
|
|||||||
Comment,
|
Comment,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
routeHash: { type: String, default: () => '' },
|
||||||
post: { type: Object, default: () => {} },
|
post: { type: Object, default: () => {} },
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@ -32,7 +32,7 @@ describe('ContributionForm.vue', () => {
|
|||||||
const postTitle = 'this is a title for a post'
|
const postTitle = 'this is a title for a post'
|
||||||
const postTitleTooShort = 'xx'
|
const postTitleTooShort = 'xx'
|
||||||
let postTitleTooLong = ''
|
let postTitleTooLong = ''
|
||||||
for (let i = 0; i < 65; i++) {
|
for (let i = 0; i < 101; i++) {
|
||||||
postTitleTooLong += 'x'
|
postTitleTooLong += 'x'
|
||||||
}
|
}
|
||||||
const postContent = 'this is a post'
|
const postContent = 'this is a post'
|
||||||
|
|||||||
@ -10,9 +10,17 @@
|
|||||||
</hc-teaser-image>
|
</hc-teaser-image>
|
||||||
<ds-card>
|
<ds-card>
|
||||||
<ds-space />
|
<ds-space />
|
||||||
<hc-user :user="currentUser" :trunc="35" />
|
<client-only>
|
||||||
|
<hc-user :user="currentUser" :trunc="35" />
|
||||||
|
</client-only>
|
||||||
<ds-space />
|
<ds-space />
|
||||||
<ds-input model="title" class="post-title" placeholder="Title" name="title" autofocus />
|
<ds-input
|
||||||
|
model="title"
|
||||||
|
class="post-title"
|
||||||
|
:placeholder="$t('contribution.title')"
|
||||||
|
name="title"
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
<small class="smallTag">{{ form.title.length }}/{{ formSchema.title.max }}</small>
|
<small class="smallTag">{{ form.title.length }}/{{ formSchema.title.max }}</small>
|
||||||
<client-only>
|
<client-only>
|
||||||
<hc-editor
|
<hc-editor
|
||||||
@ -104,7 +112,7 @@ export default {
|
|||||||
categoryIds: [],
|
categoryIds: [],
|
||||||
},
|
},
|
||||||
formSchema: {
|
formSchema: {
|
||||||
title: { required: true, min: 3, max: 64 },
|
title: { required: true, min: 3, max: 100 },
|
||||||
content: [{ required: true }],
|
content: [{ required: true }],
|
||||||
},
|
},
|
||||||
id: null,
|
id: null,
|
||||||
@ -262,7 +270,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
.smallTag {
|
.smallTag {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<editor-content :editor="editor" />
|
<editor-content :editor="editor" :key="content" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -31,6 +31,9 @@ export default {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
beforeUpdate() {
|
||||||
|
this.editor.setContent(this.content)
|
||||||
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.editor.destroy()
|
this.editor.destroy()
|
||||||
},
|
},
|
||||||
|
|||||||
@ -5,8 +5,12 @@ import helpers from '~/storybook/helpers'
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
|
||||||
const embed = {
|
const embed = {
|
||||||
|
image: 'https://i.ytimg.com/vi/ptCcgLM-p8k/maxresdefault_live.jpg',
|
||||||
|
title: 'Video Titel',
|
||||||
|
// html: null,
|
||||||
|
description: 'Video Description',
|
||||||
html:
|
html:
|
||||||
'<iframe width="480" height="270" src="https://www.youtube.com/embed/qkdXAtO40Fo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>',
|
'<iframe width="auto" height="250" src="https://www.youtube.com/embed/qkdXAtO40Fo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>',
|
||||||
}
|
}
|
||||||
|
|
||||||
const plugins = [
|
const plugins = [
|
||||||
@ -114,15 +118,12 @@ storiesOf('Editor', module)
|
|||||||
}),
|
}),
|
||||||
template: `<hc-editor :users="users" :value="content" />`,
|
template: `<hc-editor :users="users" :value="content" />`,
|
||||||
}))
|
}))
|
||||||
.add('Embeds', () => ({
|
.add('Embeds with iframe', () => ({
|
||||||
components: { HcEditor },
|
components: { HcEditor },
|
||||||
store: helpers.store,
|
store: helpers.store,
|
||||||
data: () => ({
|
data: () => ({
|
||||||
users,
|
users,
|
||||||
content: `
|
content: `
|
||||||
<p>
|
|
||||||
The following link should render a youtube video in addition to the link.
|
|
||||||
</p>
|
|
||||||
<a class="embed" href="https://www.youtube.com/watch?v=qkdXAtO40Fo">
|
<a class="embed" href="https://www.youtube.com/watch?v=qkdXAtO40Fo">
|
||||||
<em>https://www.youtube.com/watch?v=qkdXAtO40Fo</em>
|
<em>https://www.youtube.com/watch?v=qkdXAtO40Fo</em>
|
||||||
</a>
|
</a>
|
||||||
@ -130,3 +131,16 @@ storiesOf('Editor', module)
|
|||||||
}),
|
}),
|
||||||
template: `<hc-editor :users="users" :value="content" />`,
|
template: `<hc-editor :users="users" :value="content" />`,
|
||||||
}))
|
}))
|
||||||
|
.add('Embeds with plain link', () => ({
|
||||||
|
components: { HcEditor },
|
||||||
|
store: helpers.store,
|
||||||
|
data: () => ({
|
||||||
|
users,
|
||||||
|
content: `
|
||||||
|
<a class="embed" href="https://telegram.org/">
|
||||||
|
<em>https://telegram.org/</em>
|
||||||
|
</a>
|
||||||
|
`,
|
||||||
|
}),
|
||||||
|
template: `<hc-editor :users="users" :value="content" />`,
|
||||||
|
}))
|
||||||
|
|||||||
@ -342,4 +342,84 @@ li > p {
|
|||||||
margin: 0 0 $space-x-small;
|
margin: 0 0 $space-x-small;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ProseMirror[contenteditable='false'] {
|
||||||
|
.embed-close-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-container {
|
||||||
|
position: relative;
|
||||||
|
padding: 0;
|
||||||
|
margin: $space-small auto;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: $border-radius-base;
|
||||||
|
border: 1px solid $color-neutral-70;
|
||||||
|
background-color: $color-neutral-90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: $space-small 0 0 $space-small;
|
||||||
|
}
|
||||||
|
|
||||||
|
p,
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
margin: 0 0 0 $space-small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-preview-image {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-preview-image--clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-html {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
padding: $space-large;
|
||||||
|
background-color: $color-neutral-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-buttons {
|
||||||
|
button {
|
||||||
|
margin-right: $space-small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-checkbox {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin-right: $space-small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-close-button {
|
||||||
|
position: absolute;
|
||||||
|
top: $space-x-small;
|
||||||
|
right: $space-x-small;
|
||||||
|
background-color: rgba(250, 249, 250, 0.6);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -35,7 +35,7 @@ describe('defaultExtensions', () => {
|
|||||||
it('renders mentioning as link', () => {
|
it('renders mentioning as link', () => {
|
||||||
const editor = createEditor()
|
const editor = createEditor()
|
||||||
const expected =
|
const expected =
|
||||||
'<p>This is a post content mentioning <a href="/profile/f0628376-e692-4167-bdb4-d521de5a014f" rel="noopener noreferrer nofollow">@alicia-luettgen</a>.</p>'
|
'<p>This is a post content mentioning <a href="/profile/f0628376-e692-4167-bdb4-d521de5a014f" rel="noopener noreferrer nofollow" target="_blank">@alicia-luettgen</a>.</p>'
|
||||||
expect(editor.getHTML()).toEqual(expected)
|
expect(editor.getHTML()).toEqual(expected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -49,7 +49,7 @@ describe('defaultExtensions', () => {
|
|||||||
it('renders hashtag as link', () => {
|
it('renders hashtag as link', () => {
|
||||||
const editor = createEditor()
|
const editor = createEditor()
|
||||||
const expected =
|
const expected =
|
||||||
'<p>This is a post content with a hashtag <a href="/search/hashtag/metoo" rel="noopener noreferrer nofollow">#metoo</a>.</p>'
|
'<p>This is a post content with a hashtag <a href="/search/hashtag/metoo" rel="noopener noreferrer nofollow" target="_blank">#metoo</a>.</p>'
|
||||||
expect(editor.getHTML()).toEqual(expected)
|
expect(editor.getHTML()).toEqual(expected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
import { Node } from 'tiptap'
|
import { Node } from 'tiptap'
|
||||||
import pasteRule from '../commands/pasteRule'
|
import pasteRule from '../commands/pasteRule'
|
||||||
import { compileToFunctions } from 'vue-template-compiler'
|
import { compileToFunctions } from 'vue-template-compiler'
|
||||||
|
import Vue from 'vue'
|
||||||
|
import EmbedComponent from '~/components/Embed/EmbedComponent'
|
||||||
|
|
||||||
|
Vue.component(EmbedComponent)
|
||||||
|
const template = `<component :dataEmbedUrl="dataEmbedUrl" :embedData="embedData" :is="componentType" />`
|
||||||
|
|
||||||
const template = `
|
|
||||||
<a class="embed" :href="dataEmbedUrl" rel="noopener noreferrer nofollow" target="_blank">
|
|
||||||
<div v-if="embedHtml" v-html="embedHtml" />
|
|
||||||
<em> {{ dataEmbedUrl }} </em>
|
|
||||||
</a>
|
|
||||||
`
|
|
||||||
const compiledTemplate = compileToFunctions(template)
|
const compiledTemplate = compileToFunctions(template)
|
||||||
|
|
||||||
export default class Embed extends Node {
|
export default class Embed extends Node {
|
||||||
@ -67,16 +66,13 @@ export default class Embed extends Node {
|
|||||||
embedData: {},
|
embedData: {},
|
||||||
}),
|
}),
|
||||||
async created() {
|
async created() {
|
||||||
if (!this.options) return {}
|
if (this.options) {
|
||||||
this.embedData = await this.options.onEmbed({ url: this.dataEmbedUrl })
|
this.embedData = await this.options.onEmbed({ url: this.dataEmbedUrl })
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
embedClass() {
|
componentType() {
|
||||||
return this.embedHtml ? 'embed' : ''
|
return EmbedComponent
|
||||||
},
|
|
||||||
embedHtml() {
|
|
||||||
const { html = '' } = this.embedData
|
|
||||||
return html
|
|
||||||
},
|
},
|
||||||
dataEmbedUrl: {
|
dataEmbedUrl: {
|
||||||
get() {
|
get() {
|
||||||
|
|||||||
@ -1,31 +1,30 @@
|
|||||||
import { shallowMount } from '@vue/test-utils'
|
import { shallowMount, createLocalVue } from '@vue/test-utils'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
import Styleguide from '@human-connection/styleguide'
|
||||||
import Embed from './Embed'
|
import Embed from './Embed'
|
||||||
|
|
||||||
let Wrapper
|
let Wrapper, propsData, component
|
||||||
let propsData
|
|
||||||
const someUrl = 'https://www.youtube.com/watch?v=qkdXAtO40Fo'
|
const someUrl = 'https://www.youtube.com/watch?v=qkdXAtO40Fo'
|
||||||
|
const localVue = createLocalVue()
|
||||||
|
|
||||||
|
localVue.use(Vuex)
|
||||||
|
localVue.use(Styleguide)
|
||||||
|
|
||||||
describe('Embed.vue', () => {
|
describe('Embed.vue', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
propsData = {}
|
propsData = {}
|
||||||
const component = new Embed()
|
component = new Embed()
|
||||||
Wrapper = ({ mocks, propsData }) => {
|
Wrapper = ({ propsData }) => {
|
||||||
return shallowMount(component.view, { propsData })
|
return shallowMount(component.view, { propsData })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders anchor', () => {
|
|
||||||
propsData = {
|
|
||||||
node: { attrs: { href: someUrl } },
|
|
||||||
}
|
|
||||||
expect(Wrapper({ propsData }).is('a')).toBe(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('given a href', () => {
|
describe('given a href', () => {
|
||||||
describe('onEmbed returned embed data', () => {
|
describe('onEmbed returned embed data', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
propsData.options = {
|
propsData.options = {
|
||||||
onEmbed: () => ({
|
onEmbed: () => ({
|
||||||
|
__typename: 'Embed',
|
||||||
type: 'video',
|
type: 'video',
|
||||||
title: 'Baby Loves Cat',
|
title: 'Baby Loves Cat',
|
||||||
author: 'Merkley Family',
|
author: 'Merkley Family',
|
||||||
@ -49,9 +48,7 @@ describe('Embed.vue', () => {
|
|||||||
propsData.node = { attrs: { href: 'https://www.youtube.com/watch?v=qkdXAtO40Fo' } }
|
propsData.node = { attrs: { href: 'https://www.youtube.com/watch?v=qkdXAtO40Fo' } }
|
||||||
const wrapper = Wrapper({ propsData })
|
const wrapper = Wrapper({ propsData })
|
||||||
await wrapper.html()
|
await wrapper.html()
|
||||||
expect(wrapper.find('div iframe').attributes('src')).toEqual(
|
expect(wrapper.contains('embed-component-stub')).toBe(true)
|
||||||
'https://www.youtube.com/embed/qkdXAtO40Fo?feature=oembed',
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export default class Link extends TipTapLink {
|
|||||||
{
|
{
|
||||||
...node.attrs,
|
...node.attrs,
|
||||||
rel: 'noopener noreferrer nofollow',
|
rel: 'noopener noreferrer nofollow',
|
||||||
|
target: '_blank',
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -10,7 +10,6 @@ export default class EventHandler extends Extension {
|
|||||||
new Plugin({
|
new Plugin({
|
||||||
props: {
|
props: {
|
||||||
transformPastedText(text) {
|
transformPastedText(text) {
|
||||||
// console.log('#### transformPastedText', text)
|
|
||||||
return text.trim()
|
return text.trim()
|
||||||
},
|
},
|
||||||
transformPastedHTML(html) {
|
transformPastedHTML(html) {
|
||||||
@ -33,7 +32,6 @@ export default class EventHandler extends Extension {
|
|||||||
.replace(/<p>(\s*<br ?\/?>\s*)+/gim, '<p>')
|
.replace(/<p>(\s*<br ?\/?>\s*)+/gim, '<p>')
|
||||||
// remove additional linebreaks when last child inside p tags
|
// remove additional linebreaks when last child inside p tags
|
||||||
.replace(/(\s*<br ?\/?>\s*)+<\/p>/gim, '</p>')
|
.replace(/(\s*<br ?\/?>\s*)+<\/p>/gim, '</p>')
|
||||||
// console.log('#### transformPastedHTML', html)
|
|
||||||
return html
|
return html
|
||||||
},
|
},
|
||||||
// transformPasted(slice) {
|
// transformPasted(slice) {
|
||||||
|
|||||||
206
webapp/components/Embed/EmbedComponent.spec.js
Normal file
206
webapp/components/Embed/EmbedComponent.spec.js
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
import { mount, createLocalVue } from '@vue/test-utils'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
import Styleguide from '@human-connection/styleguide'
|
||||||
|
import EmbedComponent from './EmbedComponent'
|
||||||
|
|
||||||
|
let wrapper, propsData, getters, mocks
|
||||||
|
const someUrl = 'https://www.youtube.com/watch?v=qkdXAtO40Fo'
|
||||||
|
const localVue = createLocalVue()
|
||||||
|
|
||||||
|
localVue.use(Vuex)
|
||||||
|
localVue.use(Styleguide)
|
||||||
|
|
||||||
|
describe('EmbedComponent.vue', () => {
|
||||||
|
const Wrapper = () => {
|
||||||
|
const store = new Vuex.Store({
|
||||||
|
getters,
|
||||||
|
})
|
||||||
|
return mount(EmbedComponent, { propsData, localVue, store, mocks })
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mocks = {
|
||||||
|
$t: a => a,
|
||||||
|
$apollo: {
|
||||||
|
mutate: jest
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValueOnce({ data: { UpdateUser: { allowEmbedIframes: true } } }),
|
||||||
|
},
|
||||||
|
$toast: {
|
||||||
|
success: jest.fn(),
|
||||||
|
error: jest.fn(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
propsData = {}
|
||||||
|
getters = {
|
||||||
|
'auth/user': () => {
|
||||||
|
return { id: 'u5', allowEmbedIframes: false }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('given a href only for a link ', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
propsData.embedData = {
|
||||||
|
__typename: 'Embed',
|
||||||
|
type: 'link',
|
||||||
|
title: '👻 ✉️ Bruno... le ciel sur répondeur ! 🔮 🧠 - Clément FREZE',
|
||||||
|
author: null,
|
||||||
|
publisher: 'PeerTube.social',
|
||||||
|
date: null,
|
||||||
|
description:
|
||||||
|
'Salut tout le monde ! Aujourd’hui, une vidéo sur le scepticisme, nous allons parler médiumnité avec le cas de Bruno CHARVET : « Bruno, un nouveau message ». Merci de rester respectueux dans les commentaires : SOURCES : Les sources des vi...',
|
||||||
|
url: 'https://peertube.social/videos/watch/f3cb1945-a8f7-481f-a465-946c6f884e50',
|
||||||
|
image: 'https://peertube.social/static/thumbnails/f3cb1945-a8f7-481f-a465-946c6f884e50.jpg',
|
||||||
|
audio: null,
|
||||||
|
video: null,
|
||||||
|
lang: 'fr',
|
||||||
|
sources: ['resource', 'oembed'],
|
||||||
|
html: null,
|
||||||
|
}
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows the title', () => {
|
||||||
|
expect(wrapper.find('h4').text()).toBe(
|
||||||
|
'👻 ✉️ Bruno... le ciel sur répondeur ! 🔮 🧠 - Clément FREZE',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows the description', () => {
|
||||||
|
expect(wrapper.find('.embed-content p').text()).toBe(
|
||||||
|
'Salut tout le monde ! Aujourd’hui, une vidéo sur le scepticisme, nous allons parler médiumnité avec le cas de Bruno CHARVET : « Bruno, un nouveau message ». Merci de rester respectueux dans les commentaires : SOURCES : Les sources des vi...',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows preview Images for link', () => {
|
||||||
|
expect(wrapper.find('.embed-preview-image').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('given a href with embed html', () => {
|
||||||
|
describe('onEmbed returned title and description', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
propsData.embedData = {
|
||||||
|
__typename: 'Embed',
|
||||||
|
title: 'Baby Loves Cat',
|
||||||
|
description:
|
||||||
|
'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...',
|
||||||
|
}
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('show the title', () => {
|
||||||
|
expect(wrapper.find('h4').text()).toBe('Baby Loves Cat')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('show the desciption', () => {
|
||||||
|
expect(wrapper.find('.embed-content p').text()).toBe(
|
||||||
|
'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('onEmbed returned embed data with html', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
propsData.embedData = {
|
||||||
|
__typename: 'Embed',
|
||||||
|
type: 'video',
|
||||||
|
title: 'Baby Loves Cat',
|
||||||
|
author: 'Merkley Family',
|
||||||
|
publisher: 'YouTube',
|
||||||
|
date: '2015-08-16T00:00:00.000Z',
|
||||||
|
description:
|
||||||
|
'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...',
|
||||||
|
url: someUrl,
|
||||||
|
image: 'https://i.ytimg.com/vi/qkdXAtO40Fo/maxresdefault.jpg',
|
||||||
|
audio: null,
|
||||||
|
video: null,
|
||||||
|
lang: 'de',
|
||||||
|
sources: ['resource', 'oembed'],
|
||||||
|
html:
|
||||||
|
'<iframe width="480" height="270" src="https://www.youtube.com/embed/qkdXAtO40Fo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>',
|
||||||
|
}
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows a simple link when a user closes the embed preview', () => {
|
||||||
|
wrapper.find('.embed-close-button').trigger('click')
|
||||||
|
expect(wrapper.vm.showLinkOnly).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('opens the data privacy overlay when a user clicks on the preview image', () => {
|
||||||
|
wrapper.find('.embed-preview-image--clickable').trigger('click')
|
||||||
|
expect(wrapper.vm.showOverlay).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('shows iframe', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper.setData({ showOverlay: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('when user agress', () => {
|
||||||
|
wrapper.find('.ds-button-primary').trigger('click')
|
||||||
|
expect(wrapper.vm.showEmbed).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not show iframe when user clicks to cancel', () => {
|
||||||
|
wrapper.find('.ds-button-ghost').trigger('click')
|
||||||
|
expect(wrapper.vm.showEmbed).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("doesn't set permanently", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper.find('.ds-button-primary').trigger('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
it("if user doesn't give consent", () => {
|
||||||
|
expect(wrapper.vm.checkedAlwaysAllowEmbeds).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("doesn't update the user's profile", () => {
|
||||||
|
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('sets permanently', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper.find('input[type=checkbox]').trigger('click')
|
||||||
|
wrapper.find('.ds-button-primary').trigger('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('changes setting permanetly when user requests', () => {
|
||||||
|
expect(wrapper.vm.checkedAlwaysAllowEmbeds).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("updates the user's profile", () => {
|
||||||
|
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('immediately shows', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
getters = {
|
||||||
|
'auth/user': () => {
|
||||||
|
return { id: 'u5', allowEmbedIframes: true }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets showEmbed to true', () => {
|
||||||
|
expect(wrapper.vm.showEmbed).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('the iframe returned from oEmbed', () => {
|
||||||
|
expect(wrapper.find('iframe').html()).toEqual(propsData.embedData.html)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not display image to click', () => {
|
||||||
|
expect(wrapper.find('.embed-preview-image--clickable').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
153
webapp/components/Embed/EmbedComponent.vue
Normal file
153
webapp/components/Embed/EmbedComponent.vue
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
<template>
|
||||||
|
<a v-if="showLinkOnly" :href="dataEmbedUrl" rel="noopener noreferrer nofollow" target="_blank">
|
||||||
|
{{ dataEmbedUrl }}
|
||||||
|
</a>
|
||||||
|
<ds-container v-else width="small" class="embed-container">
|
||||||
|
<section class="embed-content">
|
||||||
|
<div v-if="showEmbed" v-html="embedHtml" class="embed-html" />
|
||||||
|
<template v-else>
|
||||||
|
<img
|
||||||
|
v-if="embedHtml && embedImage"
|
||||||
|
:src="embedImage"
|
||||||
|
class="embed-preview-image embed-preview-image--clickable"
|
||||||
|
@click.prevent="openOverlay()"
|
||||||
|
/>
|
||||||
|
<img v-else-if="embedImage" :src="embedImage" class="embed-preview-image" />
|
||||||
|
</template>
|
||||||
|
<h4 v-if="embedTitle">{{ embedTitle }}</h4>
|
||||||
|
<p v-if="embedDescription">{{ embedDescription }}</p>
|
||||||
|
<a class="embed" :href="dataEmbedUrl" rel="noopener noreferrer nofollow" target="_blank">
|
||||||
|
{{ dataEmbedUrl }}
|
||||||
|
</a>
|
||||||
|
</section>
|
||||||
|
<aside v-if="showOverlay" class="embed-overlay">
|
||||||
|
<h3>{{ $t('editor.embed.data_privacy_warning') }}</h3>
|
||||||
|
<ds-text>{{ $t('editor.embed.data_privacy_info') }} {{ embedPublisher }}</ds-text>
|
||||||
|
<div class="embed-buttons">
|
||||||
|
<ds-button primary @click.prevent="allowEmbed()">
|
||||||
|
{{ $t('editor.embed.play_now') }}
|
||||||
|
</ds-button>
|
||||||
|
<ds-button ghost @click.prevent="closeOverlay()">{{ $t('actions.cancel') }}</ds-button>
|
||||||
|
</div>
|
||||||
|
<label class="embed-checkbox">
|
||||||
|
<input type="checkbox" v-model="checkedAlwaysAllowEmbeds" />
|
||||||
|
<span>{{ $t('editor.embed.always_allow') }}</span>
|
||||||
|
</label>
|
||||||
|
</aside>
|
||||||
|
<ds-button
|
||||||
|
icon="close"
|
||||||
|
ghost
|
||||||
|
size="small"
|
||||||
|
class="embed-close-button"
|
||||||
|
@click.prevent="removeEmbed()"
|
||||||
|
/>
|
||||||
|
</ds-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters, mapMutations } from 'vuex'
|
||||||
|
import { allowEmbedIframesMutation } from '~/graphql/User.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'embed-component',
|
||||||
|
props: {
|
||||||
|
dataEmbedUrl: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
embedData: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
checkedAlwaysAllowEmbeds: false,
|
||||||
|
showEmbed: false,
|
||||||
|
showOverlay: false,
|
||||||
|
showLinkOnly: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.currentUser.allowEmbedIframes) {
|
||||||
|
this.showEmbed = this.currentUser.allowEmbedIframes
|
||||||
|
this.checkedAlwaysAllowEmbeds = this.currentUser.allowEmbedIframes
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
currentUser: 'auth/user',
|
||||||
|
}),
|
||||||
|
embedHtml() {
|
||||||
|
const { html = '' } = this.embedData
|
||||||
|
return html
|
||||||
|
},
|
||||||
|
embedImage() {
|
||||||
|
const { image = '' } = this.embedData
|
||||||
|
return image
|
||||||
|
},
|
||||||
|
embedPublisher() {
|
||||||
|
const { publisher = '' } = this.embedData
|
||||||
|
return publisher
|
||||||
|
},
|
||||||
|
embedTitle() {
|
||||||
|
const { title = '' } = this.embedData
|
||||||
|
return title
|
||||||
|
},
|
||||||
|
embedAuthor() {
|
||||||
|
const { author = '' } = this.embedData
|
||||||
|
return author
|
||||||
|
},
|
||||||
|
embedDescription() {
|
||||||
|
const { description = '' } = this.embedData
|
||||||
|
return description
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations({
|
||||||
|
setCurrentUser: 'auth/SET_USER',
|
||||||
|
}),
|
||||||
|
openOverlay() {
|
||||||
|
this.showOverlay = true
|
||||||
|
},
|
||||||
|
closeOverlay() {
|
||||||
|
this.showOverlay = false
|
||||||
|
},
|
||||||
|
allowEmbed() {
|
||||||
|
this.showEmbed = true
|
||||||
|
this.closeOverlay()
|
||||||
|
|
||||||
|
if (this.checkedAlwaysAllowEmbeds !== this.currentUser.allowEmbedIframes) {
|
||||||
|
this.updateEmbedSettings(this.checkedAlwaysAllowEmbeds)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeEmbed() {
|
||||||
|
this.showLinkOnly = true
|
||||||
|
},
|
||||||
|
async updateEmbedSettings(allowEmbedIframes) {
|
||||||
|
try {
|
||||||
|
await this.$apollo.mutate({
|
||||||
|
mutation: allowEmbedIframesMutation(),
|
||||||
|
variables: {
|
||||||
|
id: this.currentUser.id,
|
||||||
|
allowEmbedIframes,
|
||||||
|
},
|
||||||
|
update: (store, { data: { UpdateUser } }) => {
|
||||||
|
const { allowEmbedIframes } = UpdateUser
|
||||||
|
this.setCurrentUser({
|
||||||
|
...this.currentUser,
|
||||||
|
allowEmbedIframes,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
this.$toast.success(this.$t('contribution.success'))
|
||||||
|
this.showEmbed = this.currentUser.allowEmbedIframes
|
||||||
|
} catch (err) {
|
||||||
|
this.$toast.error(err.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -1,12 +1,12 @@
|
|||||||
import { mount, createLocalVue } from '@vue/test-utils'
|
import { mount, createLocalVue } from '@vue/test-utils'
|
||||||
import VerifyNonce from './VerifyNonce.vue'
|
import EnterNonce from './EnterNonce.vue'
|
||||||
import Styleguide from '@human-connection/styleguide'
|
import Styleguide from '@human-connection/styleguide'
|
||||||
|
|
||||||
const localVue = createLocalVue()
|
const localVue = createLocalVue()
|
||||||
|
|
||||||
localVue.use(Styleguide)
|
localVue.use(Styleguide)
|
||||||
|
|
||||||
describe('VerifyNonce ', () => {
|
describe('EnterNonce ', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
let Wrapper
|
let Wrapper
|
||||||
let mocks
|
let mocks
|
||||||
@ -25,28 +25,28 @@ describe('VerifyNonce ', () => {
|
|||||||
beforeEach(jest.useFakeTimers)
|
beforeEach(jest.useFakeTimers)
|
||||||
|
|
||||||
Wrapper = () => {
|
Wrapper = () => {
|
||||||
return mount(VerifyNonce, {
|
return mount(EnterNonce, {
|
||||||
mocks,
|
mocks,
|
||||||
localVue,
|
localVue,
|
||||||
propsData,
|
propsData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
it('renders a verify nonce form', () => {
|
it('renders an enter nonce form', () => {
|
||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
expect(wrapper.find('.verify-nonce').exists()).toBe(true)
|
expect(wrapper.find('form').exists()).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('after verification nonce given', () => {
|
describe('after nonce entered', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
wrapper.find('input#nonce').setValue('123456')
|
wrapper.find('input#nonce').setValue('123456')
|
||||||
wrapper.find('form').trigger('submit')
|
wrapper.find('form').trigger('submit')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('emits `verification`', () => {
|
it('emits `nonceEntered`', () => {
|
||||||
const expected = [[{ nonce: '123456', email: 'mail@example.org' }]]
|
const expected = [[{ nonce: '123456', email: 'mail@example.org' }]]
|
||||||
expect(wrapper.emitted('verification')).toEqual(expected)
|
expect(wrapper.emitted('nonceEntered')).toEqual(expected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
66
webapp/components/EnterNonce/EnterNonce.vue
Normal file
66
webapp/components/EnterNonce/EnterNonce.vue
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<ds-space margin-top="large" margin-bottom="xxx-small">
|
||||||
|
<ds-form
|
||||||
|
v-model="formData"
|
||||||
|
:schema="formSchema"
|
||||||
|
@submit="handleSubmitVerify"
|
||||||
|
@input="handleInput"
|
||||||
|
@input-valid="handleInputValid"
|
||||||
|
>
|
||||||
|
<ds-input
|
||||||
|
:placeholder="$t('components.enter-nonce.form.nonce')"
|
||||||
|
model="nonce"
|
||||||
|
name="nonce"
|
||||||
|
id="nonce"
|
||||||
|
icon="question-circle"
|
||||||
|
/>
|
||||||
|
<ds-space margin-botton="large">
|
||||||
|
<ds-text>
|
||||||
|
{{ $t('components.enter-nonce.form.description') }}
|
||||||
|
</ds-text>
|
||||||
|
</ds-space>
|
||||||
|
<ds-button :disabled="disabled" primary fullwidth name="submit" type="submit">
|
||||||
|
{{ $t('components.enter-nonce.form.next') }}
|
||||||
|
</ds-button>
|
||||||
|
</ds-form>
|
||||||
|
<slot></slot>
|
||||||
|
</ds-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
email: { type: String, required: true },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
nonce: '',
|
||||||
|
},
|
||||||
|
formSchema: {
|
||||||
|
nonce: {
|
||||||
|
type: 'string',
|
||||||
|
min: 6,
|
||||||
|
max: 6,
|
||||||
|
required: true,
|
||||||
|
message: this.$t('components.enter-nonce.form.validations.length'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
disabled: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async handleInput() {
|
||||||
|
this.disabled = true
|
||||||
|
},
|
||||||
|
async handleInputValid() {
|
||||||
|
this.disabled = false
|
||||||
|
},
|
||||||
|
handleSubmitVerify() {
|
||||||
|
const { nonce } = this.formData
|
||||||
|
const email = this.email
|
||||||
|
this.$emit('nonceEntered', { email, nonce })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -36,6 +36,7 @@
|
|||||||
import Dropdown from '~/components/Dropdown'
|
import Dropdown from '~/components/Dropdown'
|
||||||
import find from 'lodash/find'
|
import find from 'lodash/find'
|
||||||
import orderBy from 'lodash/orderBy'
|
import orderBy from 'lodash/orderBy'
|
||||||
|
import locales from '~/locales'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -47,7 +48,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
locales: orderBy(process.env.locales, 'name'),
|
locales: orderBy(locales, 'name'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|||||||
@ -20,7 +20,7 @@ describe('ReportModal.vue', () => {
|
|||||||
id: 'c43',
|
id: 'c43',
|
||||||
}
|
}
|
||||||
mocks = {
|
mocks = {
|
||||||
$t: jest.fn(),
|
$t: jest.fn(a => a),
|
||||||
$filters: {
|
$filters: {
|
||||||
truncate: a => a,
|
truncate: a => a,
|
||||||
},
|
},
|
||||||
@ -29,7 +29,9 @@ describe('ReportModal.vue', () => {
|
|||||||
error: () => {},
|
error: () => {},
|
||||||
},
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
mutate: jest.fn().mockResolvedValue(),
|
mutate: jest.fn().mockResolvedValue({
|
||||||
|
data: {},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -154,6 +156,7 @@ describe('ReportModal.vue', () => {
|
|||||||
|
|
||||||
describe('click confirm button', () => {
|
describe('click confirm button', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
wrapper.find('.ds-radio-option-label').trigger('click')
|
||||||
wrapper.find('button.confirm').trigger('click')
|
wrapper.find('button.confirm').trigger('click')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,36 @@
|
|||||||
|
|
||||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
<p v-html="message" />
|
<p v-html="message" />
|
||||||
|
<ds-radio
|
||||||
<template slot="footer">
|
v-model="form.reasonCategory"
|
||||||
<ds-button class="cancel" icon="close" @click="cancel">{{ $t('report.cancel') }}</ds-button>
|
:schema="formSchema.reasonCategory"
|
||||||
|
:label="$t('report.reason.category.label')"
|
||||||
|
:options="form.reasonCategoryOptions"
|
||||||
|
labelProp="label"
|
||||||
|
/>
|
||||||
|
<ds-input
|
||||||
|
class="reason-description"
|
||||||
|
v-model="form.reasonDescription"
|
||||||
|
:schema="formSchema.reasonDescription"
|
||||||
|
:label="$t('report.reason.description.label')"
|
||||||
|
:placeholder="$t('report.reason.description.placeholder')"
|
||||||
|
type="textarea"
|
||||||
|
rows="5"
|
||||||
|
/>
|
||||||
|
<small class="smallTag">
|
||||||
|
{{ form.reasonDescription.length }}/{{ formSchema.reasonDescription.max }}
|
||||||
|
</small>
|
||||||
|
<ds-space />
|
||||||
|
<template #footer>
|
||||||
|
<ds-button class="cancel" icon="close" @click="cancel">
|
||||||
|
{{ $t('report.cancel') }}
|
||||||
|
</ds-button>
|
||||||
|
|
||||||
<ds-button
|
<ds-button
|
||||||
danger
|
danger
|
||||||
class="confirm"
|
class="confirm"
|
||||||
icon="exclamation-circle"
|
icon="exclamation-circle"
|
||||||
|
:disabled="!form.reasonCategory"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@click="confirm"
|
@click="confirm"
|
||||||
>
|
>
|
||||||
@ -26,8 +48,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import gql from 'graphql-tag'
|
|
||||||
import { SweetalertIcon } from 'vue-sweetalert-icons'
|
import { SweetalertIcon } from 'vue-sweetalert-icons'
|
||||||
|
import { reportMutation } from '~/graphql/Moderation.js'
|
||||||
|
import { valuesReasonCategoryOptions } from '~/constants/modals.js'
|
||||||
|
import validReport from '~/components/utils/ReportModal'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ReportModal',
|
name: 'ReportModal',
|
||||||
@ -44,8 +68,21 @@ export default {
|
|||||||
isOpen: true,
|
isOpen: true,
|
||||||
success: false,
|
success: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
form: {
|
||||||
|
reasonCategory: null,
|
||||||
|
reasonCategoryOptions: [],
|
||||||
|
reasonDescription: '',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.form.reasonCategoryOptions = valuesReasonCategoryOptions.map(reasonCategory => {
|
||||||
|
return {
|
||||||
|
label: this.$t('report.reason.category.options.' + reasonCategory),
|
||||||
|
value: reasonCategory,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
title() {
|
title() {
|
||||||
return this.$t(`report.${this.type}.title`)
|
return this.$t(`report.${this.type}.title`)
|
||||||
@ -54,6 +91,12 @@ export default {
|
|||||||
const name = this.$filters.truncate(this.name, 30)
|
const name = this.$filters.truncate(this.name, 30)
|
||||||
return this.$t(`report.${this.type}.message`, { name })
|
return this.$t(`report.${this.type}.message`, { name })
|
||||||
},
|
},
|
||||||
|
formSchema() {
|
||||||
|
const validReportSchema = validReport({ translate: this.$t })
|
||||||
|
return {
|
||||||
|
...validReportSchema.formSchema,
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async cancel() {
|
async cancel() {
|
||||||
@ -65,52 +108,74 @@ export default {
|
|||||||
}, 1000)
|
}, 1000)
|
||||||
},
|
},
|
||||||
async confirm() {
|
async confirm() {
|
||||||
|
const { reasonCategory, reasonDescription } = this.form
|
||||||
this.loading = true
|
this.loading = true
|
||||||
try {
|
// TODO: Use the "modalData" structure introduced in "ConfirmModal" and refactor this here. Be aware that all the Jest tests have to be refactored as well !!!
|
||||||
// TODO: Use the "modalData" structure introduced in "ConfirmModal" and refactor this here. Be aware that all the Jest tests have to be refactored as well !!!
|
// await this.modalData.buttons.confirm.callback()
|
||||||
// await this.modalData.buttons.confirm.callback()
|
this.$apollo
|
||||||
await this.$apollo.mutate({
|
.mutate({
|
||||||
mutation: gql`
|
mutation: reportMutation(),
|
||||||
mutation($id: ID!) {
|
variables: {
|
||||||
report(id: $id) {
|
resourceId: this.id,
|
||||||
id
|
reasonCategory: reasonCategory.value,
|
||||||
}
|
reasonDescription,
|
||||||
}
|
},
|
||||||
`,
|
|
||||||
variables: { id: this.id },
|
|
||||||
})
|
})
|
||||||
this.success = true
|
.then(({ _data }) => {
|
||||||
this.$toast.success(this.$t('report.success'))
|
this.success = true
|
||||||
setTimeout(() => {
|
this.$toast.success(this.$t('report.success'))
|
||||||
this.isOpen = false
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.success = false
|
this.isOpen = false
|
||||||
this.$emit('close')
|
setTimeout(() => {
|
||||||
}, 500)
|
this.success = false
|
||||||
}, 1500)
|
this.$emit('close')
|
||||||
} catch (err) {
|
}, 500)
|
||||||
this.$emit('close')
|
}, 1500)
|
||||||
this.success = false
|
this.loading = false
|
||||||
switch (err.message) {
|
})
|
||||||
case 'GraphQL error: User':
|
.catch(err => {
|
||||||
this.$toast.error(this.$t('report.user.error'))
|
this.$emit('close')
|
||||||
break
|
this.success = false
|
||||||
case 'GraphQL error: Post':
|
switch (err.message) {
|
||||||
this.$toast.error(this.$t('report.contribution.error'))
|
case 'GraphQL error: User':
|
||||||
break
|
this.$toast.error(this.$t('report.user.error'))
|
||||||
case 'GraphQL error: Comment':
|
break
|
||||||
this.$toast.error(this.$t('report.comment.error'))
|
case 'GraphQL error: Post':
|
||||||
break
|
this.$toast.error(this.$t('report.contribution.error'))
|
||||||
}
|
break
|
||||||
} finally {
|
case 'GraphQL error: Comment':
|
||||||
this.loading = false
|
this.$toast.error(this.$t('report.comment.error'))
|
||||||
}
|
break
|
||||||
|
default:
|
||||||
|
this.$toast.error(err.message)
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.ds-modal {
|
||||||
|
max-width: 600px !important;
|
||||||
|
}
|
||||||
|
.ds-radio-option:not(.ds-button) {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
.ds-radio-option-label {
|
||||||
|
margin: 5px 20px 5px 5px !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
.reason-description {
|
||||||
|
margin-top: $space-x-small !important;
|
||||||
|
margin-bottom: $space-xx-small !important;
|
||||||
|
}
|
||||||
|
.smallTag {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
left: 90%;
|
||||||
|
}
|
||||||
.hc-modal-success {
|
.hc-modal-success {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -39,7 +39,7 @@ describe('ChangePassword ', () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('given email and verification nonce', () => {
|
describe('given email and nonce', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
propsData.email = 'mail@example.org'
|
propsData.email = 'mail@example.org'
|
||||||
propsData.nonce = '123456'
|
propsData.nonce = '123456'
|
||||||
@ -66,7 +66,7 @@ describe('ChangePassword ', () => {
|
|||||||
|
|
||||||
describe('password reset successful', () => {
|
describe('password reset successful', () => {
|
||||||
it('displays success message', () => {
|
it('displays success message', () => {
|
||||||
const expected = 'verify-nonce.form.change-password.success'
|
const expected = 'components.password-reset.change-password.success'
|
||||||
expect(mocks.$t).toHaveBeenCalledWith(expected)
|
expect(mocks.$t).toHaveBeenCalledWith(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,54 +1,62 @@
|
|||||||
<template>
|
<template>
|
||||||
<ds-card class="verify-nonce">
|
<ds-space margin-top="base" margin-bottom="xxx-small">
|
||||||
<ds-space margin="large">
|
<ds-form
|
||||||
<ds-form
|
v-if="!changePasswordResult"
|
||||||
v-if="!changePasswordResult"
|
v-model="formData"
|
||||||
v-model="formData"
|
:schema="formSchema"
|
||||||
:schema="formSchema"
|
@submit="handleSubmitPassword"
|
||||||
@submit="handleSubmitPassword"
|
class="change-password"
|
||||||
class="change-password"
|
>
|
||||||
>
|
<template slot-scope="{ errors }">
|
||||||
<template slot-scope="{ errors }">
|
<ds-input
|
||||||
<ds-input
|
id="password"
|
||||||
id="password"
|
model="password"
|
||||||
model="password"
|
type="password"
|
||||||
type="password"
|
autocomplete="off"
|
||||||
autocomplete="off"
|
:label="$t('settings.security.change-password.label-new-password')"
|
||||||
:label="$t('settings.security.change-password.label-new-password')"
|
/>
|
||||||
/>
|
<ds-input
|
||||||
<ds-input
|
id="passwordConfirmation"
|
||||||
id="passwordConfirmation"
|
model="passwordConfirmation"
|
||||||
model="passwordConfirmation"
|
type="password"
|
||||||
type="password"
|
autocomplete="off"
|
||||||
autocomplete="off"
|
:label="$t('settings.security.change-password.label-new-password-confirm')"
|
||||||
:label="$t('settings.security.change-password.label-new-password-confirm')"
|
/>
|
||||||
/>
|
<password-strength :password="formData.password" />
|
||||||
<password-strength :password="formData.password" />
|
<ds-space margin-top="base" margin-bottom="xxx-small">
|
||||||
<ds-space margin-top="base">
|
<ds-button :loading="$apollo.loading" :disabled="errors" primary>
|
||||||
<ds-button :loading="$apollo.loading" :disabled="errors" primary>
|
{{ $t('settings.security.change-password.button') }}
|
||||||
{{ $t('settings.security.change-password.button') }}
|
</ds-button>
|
||||||
</ds-button>
|
</ds-space>
|
||||||
</ds-space>
|
</template>
|
||||||
</template>
|
</ds-form>
|
||||||
</ds-form>
|
<ds-space v-else>
|
||||||
<ds-text v-else>
|
<template v-if="changePasswordResult === 'success'">
|
||||||
<template v-if="changePasswordResult === 'success'">
|
<transition name="ds-transition-fade">
|
||||||
<sweetalert-icon icon="success" />
|
<sweetalert-icon icon="success" />
|
||||||
<ds-text>
|
</transition>
|
||||||
{{ $t(`verify-nonce.form.change-password.success`) }}
|
<ds-text>
|
||||||
</ds-text>
|
{{ $t('components.password-reset.change-password.success') }}
|
||||||
</template>
|
</ds-text>
|
||||||
<template v-else>
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<transition name="ds-transition-fade">
|
||||||
<sweetalert-icon icon="error" />
|
<sweetalert-icon icon="error" />
|
||||||
<ds-text align="left">
|
</transition>
|
||||||
{{ $t(`verify-nonce.form.change-password.error`) }}
|
<ds-text>
|
||||||
{{ $t('verify-nonce.form.change-password.help') }}
|
<p>
|
||||||
</ds-text>
|
{{ $t(`components.password-reset.change-password.error`) }}
|
||||||
<a href="mailto:support@human-connection.org">support@human-connection.org</a>
|
</p>
|
||||||
</template>
|
<p>
|
||||||
</ds-text>
|
{{ $t('components.password-reset.change-password.help') }}
|
||||||
|
<br />
|
||||||
|
<a href="mailto:support@human-connection.org">support@human-connection.org</a>
|
||||||
|
</p>
|
||||||
|
</ds-text>
|
||||||
|
</template>
|
||||||
|
<slot></slot>
|
||||||
</ds-space>
|
</ds-space>
|
||||||
</ds-card>
|
</ds-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@ -18,7 +18,7 @@ describe('Request', () => {
|
|||||||
success: jest.fn(),
|
success: jest.fn(),
|
||||||
error: jest.fn(),
|
error: jest.fn(),
|
||||||
},
|
},
|
||||||
$t: jest.fn(),
|
$t: jest.fn(t => t),
|
||||||
$apollo: {
|
$apollo: {
|
||||||
loading: false,
|
loading: false,
|
||||||
mutate: jest.fn().mockResolvedValue({ data: { reqestPasswordReset: true } }),
|
mutate: jest.fn().mockResolvedValue({ data: { reqestPasswordReset: true } }),
|
||||||
@ -45,7 +45,7 @@ describe('Request', () => {
|
|||||||
|
|
||||||
it('renders a password reset form', () => {
|
it('renders a password reset form', () => {
|
||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
expect(wrapper.find('.password-reset').exists()).toBe(true)
|
expect(wrapper.find('form').exists()).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('submit', () => {
|
describe('submit', () => {
|
||||||
@ -69,7 +69,10 @@ describe('Request', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('displays a message that a password email was requested', () => {
|
it('displays a message that a password email was requested', () => {
|
||||||
const expected = ['password-reset.form.submitted', { email: 'mail@example.org' }]
|
const expected = [
|
||||||
|
'components.password-reset.request.form.submitted',
|
||||||
|
{ email: 'mail@example.org' },
|
||||||
|
]
|
||||||
expect(mocks.$t).toHaveBeenCalledWith(...expected)
|
expect(mocks.$t).toHaveBeenCalledWith(...expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,77 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<ds-card class="password-reset">
|
<ds-form
|
||||||
<ds-flex gutter="small">
|
v-if="!submitted"
|
||||||
<ds-flex-item :width="{ base: '100%', sm: '50%' }" centered>
|
@input="handleInput"
|
||||||
<client-only>
|
@input-valid="handleInputValid"
|
||||||
<locale-switch class="login-locale-switch" offset="5" />
|
v-model="formData"
|
||||||
</client-only>
|
:schema="formSchema"
|
||||||
<ds-space margin-top="small" margin-bottom="xxx-small" centered>
|
@submit="handleSubmit"
|
||||||
<img class="login-image" alt="Human Connection" src="/img/sign-up/humanconnection.svg" />
|
>
|
||||||
</ds-space>
|
<ds-space margin="small">
|
||||||
</ds-flex-item>
|
<ds-input
|
||||||
<ds-flex-item :width="{ base: '100%', sm: '50%' }" centered>
|
:placeholder="$t('login.email')"
|
||||||
<ds-space margin="small">
|
type="email"
|
||||||
<ds-text size="small" align="left">{{ $t('login.copy') }}</ds-text>
|
id="email"
|
||||||
</ds-space>
|
model="email"
|
||||||
<ds-form
|
name="email"
|
||||||
v-if="!submitted"
|
icon="envelope"
|
||||||
@input="handleInput"
|
/>
|
||||||
@input-valid="handleInputValid"
|
</ds-space>
|
||||||
v-model="formData"
|
<ds-space margin-botton="large">
|
||||||
:schema="formSchema"
|
<ds-text align="left">{{ $t('components.password-reset.request.form.description') }}</ds-text>
|
||||||
@submit="handleSubmit"
|
</ds-space>
|
||||||
>
|
<ds-button
|
||||||
<ds-input
|
:disabled="disabled"
|
||||||
:placeholder="$t('login.email')"
|
:loading="$apollo.loading"
|
||||||
type="email"
|
primary
|
||||||
id="email"
|
fullwidth
|
||||||
model="email"
|
name="submit"
|
||||||
name="email"
|
type="submit"
|
||||||
icon="envelope"
|
icon="envelope"
|
||||||
/>
|
>
|
||||||
<ds-space margin-botton="large">
|
{{ $t('components.password-reset.request.form.submit') }}
|
||||||
<ds-text align="left">{{ $t('password-reset.form.description') }}</ds-text>
|
</ds-button>
|
||||||
</ds-space>
|
<slot></slot>
|
||||||
<ds-button
|
</ds-form>
|
||||||
:disabled="disabled"
|
<div v-else>
|
||||||
:loading="$apollo.loading"
|
<transition name="ds-transition-fade">
|
||||||
primary
|
<ds-flex centered>
|
||||||
fullwidth
|
<sweetalert-icon icon="info" />
|
||||||
name="submit"
|
</ds-flex>
|
||||||
type="submit"
|
</transition>
|
||||||
icon="envelope"
|
<ds-text v-html="submitMessage" align="left" />
|
||||||
>
|
</div>
|
||||||
{{ $t('password-reset.form.submit') }}
|
|
||||||
</ds-button>
|
|
||||||
</ds-form>
|
|
||||||
<div v-else>
|
|
||||||
<transition name="ds-transition-fade">
|
|
||||||
<ds-flex centered>
|
|
||||||
<sweetalert-icon icon="info" />
|
|
||||||
</ds-flex>
|
|
||||||
</transition>
|
|
||||||
<ds-text v-html="submitMessage" align="left" />
|
|
||||||
</div>
|
|
||||||
<ds-space margin-bottom="small" />
|
|
||||||
<div>
|
|
||||||
<nuxt-link to="/login">{{ $t('site.login') }}</nuxt-link>
|
|
||||||
</div>
|
|
||||||
</ds-flex-item>
|
|
||||||
</ds-flex>
|
|
||||||
|
|
||||||
<ds-space margin="x-small"></ds-space>
|
|
||||||
</ds-card>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import { SweetalertIcon } from 'vue-sweetalert-icons'
|
import { SweetalertIcon } from 'vue-sweetalert-icons'
|
||||||
import LocaleSwitch from '../LocaleSwitch/LocaleSwitch'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SweetalertIcon,
|
SweetalertIcon,
|
||||||
LocaleSwitch,
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -92,7 +70,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
submitMessage() {
|
submitMessage() {
|
||||||
const { email } = this.formData
|
const { email } = this.formData
|
||||||
return this.$t('password-reset.form.submitted', { email })
|
return this.$t('components.password-reset.request.form.submitted', { email })
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -124,17 +102,3 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
.login-image {
|
|
||||||
width: 90%;
|
|
||||||
max-width: 200px;
|
|
||||||
}
|
|
||||||
.password-reset {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.login-locale-switch {
|
|
||||||
position: absolute;
|
|
||||||
top: 1em;
|
|
||||||
left: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@ -1,67 +0,0 @@
|
|||||||
<template>
|
|
||||||
<ds-card class="verify-nonce">
|
|
||||||
<ds-space margin="large">
|
|
||||||
<ds-form
|
|
||||||
v-model="formData"
|
|
||||||
:schema="formSchema"
|
|
||||||
@submit="handleSubmitVerify"
|
|
||||||
@input="handleInput"
|
|
||||||
@input-valid="handleInputValid"
|
|
||||||
>
|
|
||||||
<ds-input
|
|
||||||
:placeholder="$t('verify-nonce.form.nonce')"
|
|
||||||
model="nonce"
|
|
||||||
name="nonce"
|
|
||||||
id="nonce"
|
|
||||||
icon="question-circle"
|
|
||||||
/>
|
|
||||||
<ds-space margin-botton="large">
|
|
||||||
<ds-text>
|
|
||||||
{{ $t('verify-nonce.form.description') }}
|
|
||||||
</ds-text>
|
|
||||||
</ds-space>
|
|
||||||
<ds-button :disabled="disabled" primary fullwidth name="submit" type="submit">
|
|
||||||
{{ $t('verify-nonce.form.next') }}
|
|
||||||
</ds-button>
|
|
||||||
</ds-form>
|
|
||||||
</ds-space>
|
|
||||||
</ds-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
email: { type: String, required: true },
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
formData: {
|
|
||||||
nonce: '',
|
|
||||||
},
|
|
||||||
formSchema: {
|
|
||||||
nonce: {
|
|
||||||
type: 'string',
|
|
||||||
min: 6,
|
|
||||||
max: 6,
|
|
||||||
required: true,
|
|
||||||
message: this.$t('common.validations.verification-nonce'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
disabled: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async handleInput() {
|
|
||||||
this.disabled = true
|
|
||||||
},
|
|
||||||
async handleInputValid() {
|
|
||||||
this.disabled = false
|
|
||||||
},
|
|
||||||
handleSubmitVerify() {
|
|
||||||
const { nonce } = this.formData
|
|
||||||
const email = this.email
|
|
||||||
this.$emit('verification', { email, nonce })
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -131,10 +131,11 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
.ds-card-image img {
|
.ds-card-image img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 300px;
|
max-height: 2000px;
|
||||||
|
object-fit: contain;
|
||||||
-o-object-fit: cover;
|
-o-object-fit: cover;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
-o-object-position: center;
|
-o-object-position: center;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ const localVue = createLocalVue()
|
|||||||
localVue.use(Styleguide)
|
localVue.use(Styleguide)
|
||||||
config.stubs['sweetalert-icon'] = '<span><slot /></span>'
|
config.stubs['sweetalert-icon'] = '<span><slot /></span>'
|
||||||
config.stubs['client-only'] = '<span><slot /></span>'
|
config.stubs['client-only'] = '<span><slot /></span>'
|
||||||
|
config.stubs['nuxt-link'] = '<span><slot /></span>'
|
||||||
|
|
||||||
describe('CreateUserAccount', () => {
|
describe('CreateUserAccount', () => {
|
||||||
let wrapper, Wrapper, mocks, propsData, stubs
|
let wrapper, Wrapper, mocks, propsData, stubs
|
||||||
@ -60,7 +61,9 @@ describe('CreateUserAccount', () => {
|
|||||||
wrapper.find('input#password').setValue('hellopassword')
|
wrapper.find('input#password').setValue('hellopassword')
|
||||||
wrapper.find('textarea#about').setValue('Hello I am the `about` attribute')
|
wrapper.find('textarea#about').setValue('Hello I am the `about` attribute')
|
||||||
wrapper.find('input#passwordConfirmation').setValue('hellopassword')
|
wrapper.find('input#passwordConfirmation').setValue('hellopassword')
|
||||||
wrapper.find('input#checkbox').setChecked()
|
wrapper.find('input#checkbox0').setChecked()
|
||||||
|
wrapper.find('input#checkbox1').setChecked()
|
||||||
|
wrapper.find('input#checkbox2').setChecked()
|
||||||
await wrapper.find('form').trigger('submit')
|
await wrapper.find('form').trigger('submit')
|
||||||
await wrapper.html()
|
await wrapper.html()
|
||||||
}
|
}
|
||||||
@ -102,7 +105,9 @@ describe('CreateUserAccount', () => {
|
|||||||
|
|
||||||
it('displays success', async () => {
|
it('displays success', async () => {
|
||||||
await action()
|
await action()
|
||||||
expect(mocks.$t).toHaveBeenCalledWith('registration.create-user-account.success')
|
expect(mocks.$t).toHaveBeenCalledWith(
|
||||||
|
'components.registration.create-user-account.success',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('after timeout', () => {
|
describe('after timeout', () => {
|
||||||
@ -130,7 +135,9 @@ describe('CreateUserAccount', () => {
|
|||||||
|
|
||||||
it('displays form errors', async () => {
|
it('displays form errors', async () => {
|
||||||
await action()
|
await action()
|
||||||
expect(wrapper.find('.backendErrors').text()).toContain('Invalid nonce')
|
expect(mocks.$t).toHaveBeenCalledWith(
|
||||||
|
'components.registration.create-user-account.error',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,117 +1,123 @@
|
|||||||
<template>
|
<template>
|
||||||
<ds-container width="small">
|
<div v-if="response === 'success'">
|
||||||
<ds-card v-if="success" class="success">
|
<transition name="ds-transition-fade">
|
||||||
<ds-space>
|
<sweetalert-icon icon="success" />
|
||||||
<sweetalert-icon icon="success" />
|
</transition>
|
||||||
<ds-text align="center" bold color="success">
|
<ds-text align="center" bold color="success">
|
||||||
{{ $t('registration.create-user-account.success') }}
|
{{ $t('components.registration.create-user-account.success') }}
|
||||||
</ds-text>
|
</ds-text>
|
||||||
</ds-space>
|
</div>
|
||||||
</ds-card>
|
<div v-else-if="response === 'error'">
|
||||||
<ds-card v-else class="create-account-card">
|
<transition name="ds-transition-fade">
|
||||||
<client-only>
|
<sweetalert-icon icon="error" />
|
||||||
<locale-switch />
|
</transition>
|
||||||
</client-only>
|
<ds-text align="center" bold color="danger">
|
||||||
<ds-space centered>
|
{{ $t('components.registration.create-user-account.error') }}
|
||||||
<img
|
</ds-text>
|
||||||
class="create-account-image"
|
<ds-text align="center">
|
||||||
alt="Create an account for Human Connection"
|
{{ $t('components.registration.create-user-account.help') }}
|
||||||
src="/img/sign-up/nicetomeetyou.svg"
|
<a :href="supportEmail.href">{{ supportEmail.label }}</a>
|
||||||
|
</ds-text>
|
||||||
|
<ds-space centered>
|
||||||
|
<nuxt-link to="/login">{{ $t('site.back-to-login') }}</nuxt-link>
|
||||||
|
</ds-space>
|
||||||
|
</div>
|
||||||
|
<div v-else class="create-account-card">
|
||||||
|
<ds-space margin-top="large">
|
||||||
|
<ds-heading size="h3">
|
||||||
|
{{ $t('components.registration.create-user-account.title') }}
|
||||||
|
</ds-heading>
|
||||||
|
</ds-space>
|
||||||
|
|
||||||
|
<ds-form class="create-user-account" v-model="formData" :schema="formSchema" @submit="submit">
|
||||||
|
<template v-slot="{ errors }">
|
||||||
|
<ds-input
|
||||||
|
id="name"
|
||||||
|
model="name"
|
||||||
|
icon="user"
|
||||||
|
:label="$t('settings.data.labelName')"
|
||||||
|
:placeholder="$t('settings.data.namePlaceholder')"
|
||||||
/>
|
/>
|
||||||
</ds-space>
|
<ds-input
|
||||||
<ds-space>
|
id="about"
|
||||||
<ds-heading size="h3">
|
model="about"
|
||||||
{{ $t('registration.create-user-account.title') }}
|
type="textarea"
|
||||||
</ds-heading>
|
rows="3"
|
||||||
</ds-space>
|
:label="$t('settings.data.labelBio')"
|
||||||
|
:placeholder="$t('settings.data.labelBio')"
|
||||||
|
/>
|
||||||
|
<ds-input
|
||||||
|
id="password"
|
||||||
|
model="password"
|
||||||
|
type="password"
|
||||||
|
autocomplete="off"
|
||||||
|
:label="$t('settings.security.change-password.label-new-password')"
|
||||||
|
/>
|
||||||
|
<ds-input
|
||||||
|
id="passwordConfirmation"
|
||||||
|
model="passwordConfirmation"
|
||||||
|
type="password"
|
||||||
|
autocomplete="off"
|
||||||
|
:label="$t('settings.security.change-password.label-new-password-confirm')"
|
||||||
|
/>
|
||||||
|
<password-strength :password="formData.password" />
|
||||||
|
|
||||||
<ds-form class="create-user-account" v-model="formData" :schema="formSchema" @submit="submit">
|
<ds-text>
|
||||||
<template v-slot="{ errors }">
|
<input
|
||||||
<ds-flex gutter="base">
|
id="checkbox0"
|
||||||
<ds-flex-item width="100%">
|
type="checkbox"
|
||||||
<ds-input
|
v-model="termsAndConditionsConfirmed"
|
||||||
id="name"
|
:checked="termsAndConditionsConfirmed"
|
||||||
model="name"
|
/>
|
||||||
icon="user"
|
<label
|
||||||
:label="$t('settings.data.labelName')"
|
for="checkbox"
|
||||||
:placeholder="$t('settings.data.namePlaceholder')"
|
v-html="$t('termsAndConditions.termsAndConditionsConfirmed')"
|
||||||
/>
|
></label>
|
||||||
<ds-input
|
</ds-text>
|
||||||
id="about"
|
<p>
|
||||||
model="about"
|
<label>
|
||||||
type="textarea"
|
<input id="checkbox1" type="checkbox" v-model="dataPrivacy" :checked="dataPrivacy" />
|
||||||
rows="3"
|
<span v-html="$t('components.registration.signup.form.data-privacy')"></span>
|
||||||
:label="$t('settings.data.labelBio')"
|
</label>
|
||||||
:placeholder="$t('settings.data.labelBio')"
|
</p>
|
||||||
/>
|
<p>
|
||||||
<ds-input
|
<label>
|
||||||
id="password"
|
<input id="checkbox2" type="checkbox" v-model="minimumAge" :checked="minimumAge" />
|
||||||
model="password"
|
<span v-html="$t('components.registration.signup.form.minimum-age')"></span>
|
||||||
type="password"
|
</label>
|
||||||
autocomplete="off"
|
</p>
|
||||||
:label="$t('settings.security.change-password.label-new-password')"
|
<ds-button
|
||||||
/>
|
style="float: right;"
|
||||||
<ds-input
|
icon="check"
|
||||||
id="passwordConfirmation"
|
type="submit"
|
||||||
model="passwordConfirmation"
|
:loading="$apollo.loading"
|
||||||
type="password"
|
:disabled="errors || !termsAndConditionsConfirmed || !dataPrivacy || !minimumAge"
|
||||||
autocomplete="off"
|
primary
|
||||||
:label="$t('settings.security.change-password.label-new-password-confirm')"
|
>
|
||||||
/>
|
{{ $t('actions.save') }}
|
||||||
<password-strength :password="formData.password" />
|
</ds-button>
|
||||||
|
</template>
|
||||||
<ds-text>
|
</ds-form>
|
||||||
<input
|
</div>
|
||||||
id="checkbox"
|
|
||||||
type="checkbox"
|
|
||||||
v-model="termsAndConditionsConfirmed"
|
|
||||||
:checked="termsAndConditionsConfirmed"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="checkbox"
|
|
||||||
v-html="$t('termsAndConditions.termsAndConditionsConfirmed')"
|
|
||||||
></label>
|
|
||||||
</ds-text>
|
|
||||||
</ds-flex-item>
|
|
||||||
<ds-flex-item width="100%">
|
|
||||||
<ds-space class="backendErrors" v-if="backendErrors">
|
|
||||||
<ds-text align="center" bold color="danger">{{ backendErrors.message }}</ds-text>
|
|
||||||
</ds-space>
|
|
||||||
<ds-button
|
|
||||||
style="float: right;"
|
|
||||||
icon="check"
|
|
||||||
type="submit"
|
|
||||||
:loading="$apollo.loading"
|
|
||||||
:disabled="errors || !termsAndConditionsConfirmed"
|
|
||||||
primary
|
|
||||||
>
|
|
||||||
{{ $t('actions.save') }}
|
|
||||||
</ds-button>
|
|
||||||
</ds-flex-item>
|
|
||||||
</ds-flex>
|
|
||||||
</template>
|
|
||||||
</ds-form>
|
|
||||||
</ds-card>
|
|
||||||
</ds-container>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import PasswordStrength from '../Password/Strength'
|
import PasswordStrength from '../Password/Strength'
|
||||||
import { SweetalertIcon } from 'vue-sweetalert-icons'
|
import { SweetalertIcon } from 'vue-sweetalert-icons'
|
||||||
import PasswordForm from '~/components/utils/PasswordFormHelper'
|
import PasswordForm from '~/components/utils/PasswordFormHelper'
|
||||||
|
import { SUPPORT_EMAIL } from '~/constants/emails.js'
|
||||||
import { VERSION } from '~/constants/terms-and-conditions-version.js'
|
import { VERSION } from '~/constants/terms-and-conditions-version.js'
|
||||||
import { SignupVerificationMutation } from '~/graphql/Registration.js'
|
import { SignupVerificationMutation } from '~/graphql/Registration.js'
|
||||||
import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
PasswordStrength,
|
PasswordStrength,
|
||||||
SweetalertIcon,
|
SweetalertIcon,
|
||||||
LocaleSwitch,
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const passwordForm = PasswordForm({ translate: this.$t })
|
const passwordForm = PasswordForm({ translate: this.$t })
|
||||||
return {
|
return {
|
||||||
|
supportEmail: SUPPORT_EMAIL,
|
||||||
formData: {
|
formData: {
|
||||||
name: '',
|
name: '',
|
||||||
about: '',
|
about: '',
|
||||||
@ -130,12 +136,13 @@ export default {
|
|||||||
...passwordForm.formSchema,
|
...passwordForm.formSchema,
|
||||||
},
|
},
|
||||||
disabled: true,
|
disabled: true,
|
||||||
success: null,
|
response: null,
|
||||||
backendErrors: null,
|
|
||||||
// TODO: Our styleguide does not support checkmarks.
|
// TODO: Our styleguide does not support checkmarks.
|
||||||
// Integrate termsAndConditionsConfirmed into `this.formData` once we
|
// Integrate termsAndConditionsConfirmed into `this.formData` once we
|
||||||
// have checkmarks available.
|
// have checkmarks available.
|
||||||
termsAndConditionsConfirmed: false,
|
termsAndConditionsConfirmed: false,
|
||||||
|
dataPrivacy: false,
|
||||||
|
minimumAge: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
@ -152,7 +159,7 @@ export default {
|
|||||||
mutation: SignupVerificationMutation,
|
mutation: SignupVerificationMutation,
|
||||||
variables: { name, password, about, email, nonce, termsAndConditionsAgreedVersion },
|
variables: { name, password, about, email, nonce, termsAndConditionsAgreedVersion },
|
||||||
})
|
})
|
||||||
this.success = true
|
this.response = 'success'
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$emit('userCreated', {
|
this.$emit('userCreated', {
|
||||||
email,
|
email,
|
||||||
@ -160,7 +167,7 @@ export default {
|
|||||||
})
|
})
|
||||||
}, 3000)
|
}, 3000)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.backendErrors = err
|
this.response = 'error'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -42,7 +42,7 @@ describe('Signup', () => {
|
|||||||
describe('without invitation code', () => {
|
describe('without invitation code', () => {
|
||||||
it('renders signup form', () => {
|
it('renders signup form', () => {
|
||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
expect(wrapper.find('.signup').exists()).toBe(true)
|
expect(wrapper.find('form').exists()).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('submit', () => {
|
describe('submit', () => {
|
||||||
@ -69,15 +69,18 @@ describe('Signup', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('displays a message that a mail for email verification was sent', () => {
|
it('displays a message that a mail for email verification was sent', () => {
|
||||||
const expected = ['registration.signup.form.success', { email: 'mail@example.org' }]
|
const expected = [
|
||||||
|
'components.registration.signup.form.success',
|
||||||
|
{ email: 'mail@example.org' },
|
||||||
|
]
|
||||||
expect(mocks.$t).toHaveBeenCalledWith(...expected)
|
expect(mocks.$t).toHaveBeenCalledWith(...expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('after animation', () => {
|
describe('after animation', () => {
|
||||||
beforeEach(jest.runAllTimers)
|
beforeEach(jest.runAllTimers)
|
||||||
|
|
||||||
it('emits `handleSubmitted`', () => {
|
it('emits `submit`', () => {
|
||||||
expect(wrapper.emitted('handleSubmitted')).toEqual([[{ email: 'mail@example.org' }]])
|
expect(wrapper.emitted('submit')).toEqual([[{ email: 'mail@example.org' }]])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -121,7 +124,9 @@ describe('Signup', () => {
|
|||||||
|
|
||||||
it('explains the error', async () => {
|
it('explains the error', async () => {
|
||||||
await action()
|
await action()
|
||||||
expect(mocks.$t).toHaveBeenCalledWith('registration.signup.form.errors.email-exists')
|
expect(mocks.$t).toHaveBeenCalledWith(
|
||||||
|
'components.registration.signup.form.errors.email-exists',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -137,7 +142,7 @@ describe('Signup', () => {
|
|||||||
it('explains the error', async () => {
|
it('explains the error', async () => {
|
||||||
await action()
|
await action()
|
||||||
expect(mocks.$t).toHaveBeenCalledWith(
|
expect(mocks.$t).toHaveBeenCalledWith(
|
||||||
'registration.signup.form.errors.invalid-invitation-token',
|
'components.registration.signup.form.errors.invalid-invitation-token',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,59 +1,63 @@
|
|||||||
<template>
|
<template>
|
||||||
<ds-card class="signup">
|
<ds-space v-if="!success && !error" margin="large">
|
||||||
<ds-space margin="large">
|
<ds-form
|
||||||
<ds-form
|
@input="handleInput"
|
||||||
v-if="!success && !error"
|
@input-valid="handleInputValid"
|
||||||
@input="handleInput"
|
v-model="formData"
|
||||||
@input-valid="handleInputValid"
|
:schema="formSchema"
|
||||||
v-model="formData"
|
@submit="handleSubmit"
|
||||||
:schema="formSchema"
|
>
|
||||||
@submit="handleSubmit"
|
<h1>
|
||||||
|
{{ invitation ? $t('profile.invites.title') : $t('components.registration.signup.title') }}
|
||||||
|
</h1>
|
||||||
|
<ds-space v-if="token" margin-botton="large">
|
||||||
|
<ds-text v-html="$t('registration.signup.form.invitation-code', { code: token })" />
|
||||||
|
</ds-space>
|
||||||
|
<ds-space margin-botton="large">
|
||||||
|
<ds-text>
|
||||||
|
{{
|
||||||
|
invitation
|
||||||
|
? $t('profile.invites.description')
|
||||||
|
: $t('components.registration.signup.form.description')
|
||||||
|
}}
|
||||||
|
</ds-text>
|
||||||
|
</ds-space>
|
||||||
|
<ds-input
|
||||||
|
:placeholder="invitation ? $t('profile.invites.emailPlaceholder') : $t('login.email')"
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
model="email"
|
||||||
|
name="email"
|
||||||
|
icon="envelope"
|
||||||
|
/>
|
||||||
|
<ds-button
|
||||||
|
:disabled="disabled"
|
||||||
|
:loading="$apollo.loading"
|
||||||
|
primary
|
||||||
|
fullwidth
|
||||||
|
name="submit"
|
||||||
|
type="submit"
|
||||||
|
icon="envelope"
|
||||||
>
|
>
|
||||||
<h1>{{ invitation ? $t('profile.invites.title') : $t('registration.signup.title') }}</h1>
|
{{ $t('components.registration.signup.form.submit') }}
|
||||||
<ds-space v-if="token" margin-botton="large">
|
</ds-button>
|
||||||
<ds-text v-html="$t('registration.signup.form.invitation-code', { code: token })" />
|
<slot></slot>
|
||||||
</ds-space>
|
</ds-form>
|
||||||
<ds-space margin-botton="large">
|
</ds-space>
|
||||||
<ds-text>
|
<div v-else margin="large">
|
||||||
{{
|
<template v-if="!error">
|
||||||
invitation
|
<transition name="ds-transition-fade">
|
||||||
? $t('profile.invites.description')
|
<sweetalert-icon icon="info" />
|
||||||
: $t('registration.signup.form.description')
|
</transition>
|
||||||
}}
|
<ds-text align="center" v-html="submitMessage" />
|
||||||
</ds-text>
|
</template>
|
||||||
</ds-space>
|
<template v-else>
|
||||||
<ds-input
|
<transition name="ds-transition-fade">
|
||||||
:placeholder="invitation ? $t('profile.invites.emailPlaceholder') : $t('login.email')"
|
<sweetalert-icon icon="error" />
|
||||||
type="email"
|
</transition>
|
||||||
id="email"
|
<ds-text align="center">{{ error.message }}</ds-text>
|
||||||
model="email"
|
</template>
|
||||||
name="email"
|
</div>
|
||||||
icon="envelope"
|
|
||||||
/>
|
|
||||||
<ds-button
|
|
||||||
:disabled="disabled"
|
|
||||||
:loading="$apollo.loading"
|
|
||||||
primary
|
|
||||||
fullwidth
|
|
||||||
name="submit"
|
|
||||||
type="submit"
|
|
||||||
icon="envelope"
|
|
||||||
>
|
|
||||||
{{ $t('registration.signup.form.submit') }}
|
|
||||||
</ds-button>
|
|
||||||
</ds-form>
|
|
||||||
<div v-else>
|
|
||||||
<template v-if="!error">
|
|
||||||
<sweetalert-icon icon="info" />
|
|
||||||
<ds-text align="center" v-html="submitMessage" />
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<sweetalert-icon icon="error" />
|
|
||||||
<ds-text align="center">{{ error.message }}</ds-text>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</ds-space>
|
|
||||||
</ds-card>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -103,7 +107,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
submitMessage() {
|
submitMessage() {
|
||||||
const { email } = this.formData
|
const { email } = this.formData
|
||||||
return this.$t('registration.signup.form.success', { email })
|
return this.$t('components.registration.signup.form.success', { email })
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -123,7 +127,7 @@ export default {
|
|||||||
this.success = true
|
this.success = true
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$emit('handleSubmitted', { email })
|
this.$emit('submit', { email })
|
||||||
}, 3000)
|
}, 3000)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const { message } = err
|
const { message } = err
|
||||||
@ -133,7 +137,10 @@ export default {
|
|||||||
}
|
}
|
||||||
for (const [pattern, key] of Object.entries(mapping)) {
|
for (const [pattern, key] of Object.entries(mapping)) {
|
||||||
if (message.includes(pattern))
|
if (message.includes(pattern))
|
||||||
this.error = { key, message: this.$t(`registration.signup.form.errors.${key}`) }
|
this.error = {
|
||||||
|
key,
|
||||||
|
message: this.$t(`components.registration.signup.form.errors.${key}`),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!this.error) {
|
if (!this.error) {
|
||||||
this.$toast.error(message)
|
this.$toast.error(message)
|
||||||
|
|||||||
@ -3,17 +3,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { getDateFnsLocale } from '~/locales'
|
||||||
import formatRelative from 'date-fns/formatRelative'
|
import formatRelative from 'date-fns/formatRelative'
|
||||||
import { enUS, de, nl, fr, pt, es } from 'date-fns/locale' // pl currently not working library wise
|
|
||||||
const locales = {
|
|
||||||
en: enUS,
|
|
||||||
de,
|
|
||||||
nl,
|
|
||||||
fr,
|
|
||||||
es,
|
|
||||||
pt,
|
|
||||||
// pl
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HcRelativeDateTime',
|
name: 'HcRelativeDateTime',
|
||||||
@ -25,8 +16,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
relativeDateTime() {
|
relativeDateTime() {
|
||||||
let locale = locales[this.$i18n.locale() || 'en']
|
return formatRelative(new Date(this.dateTime), new Date(), { locale: getDateFnsLocale(this) })
|
||||||
return formatRelative(new Date(this.dateTime), new Date(), { locale })
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,17 +25,6 @@ describe('TeaserImage.vue', () => {
|
|||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('File upload', () => {
|
|
||||||
const imageUpload = [
|
|
||||||
{ file: { filename: 'avataar.svg', previewElement: '' }, url: 'someUrlToImage' },
|
|
||||||
]
|
|
||||||
|
|
||||||
it('supports adding a teaser image', () => {
|
|
||||||
wrapper.vm.addTeaserImage(imageUpload)
|
|
||||||
expect(wrapper.emitted().addTeaserImage[0]).toEqual(imageUpload)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('handles errors', () => {
|
describe('handles errors', () => {
|
||||||
beforeEach(() => jest.useFakeTimers())
|
beforeEach(() => jest.useFakeTimers())
|
||||||
const message = 'File upload failed'
|
const message = 'File upload failed'
|
||||||
|
|||||||
@ -5,25 +5,24 @@
|
|||||||
id="postdropzone"
|
id="postdropzone"
|
||||||
class="ds-card-image"
|
class="ds-card-image"
|
||||||
:use-custom-slot="true"
|
:use-custom-slot="true"
|
||||||
@vdropzone-thumbnail="thumbnail"
|
|
||||||
@vdropzone-error="verror"
|
@vdropzone-error="verror"
|
||||||
|
@vdropzone-thumbnail="transformImage"
|
||||||
|
@vdropzone-drop="dropzoneDrop"
|
||||||
>
|
>
|
||||||
<div class="dz-message">
|
<div
|
||||||
|
:class="{
|
||||||
|
'hc-attachments-upload-area-post': true,
|
||||||
|
'hc-attachments-upload-area-update-post': contribution,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
<div
|
<div
|
||||||
:class="{
|
:class="{
|
||||||
'hc-attachments-upload-area-post': true,
|
'hc-drag-marker-post': true,
|
||||||
'hc-attachments-upload-area-update-post': contribution,
|
'hc-drag-marker-update-post': contribution,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<ds-icon name="image" size="xxx-large" />
|
||||||
<div
|
|
||||||
:class="{
|
|
||||||
'hc-drag-marker-post': true,
|
|
||||||
'hc-drag-marker-update-post': contribution,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<ds-icon name="image" size="xxx-large" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</vue-dropzone>
|
</vue-dropzone>
|
||||||
@ -31,6 +30,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import vueDropzone from 'nuxt-dropzone'
|
import vueDropzone from 'nuxt-dropzone'
|
||||||
|
import Cropper from 'cropperjs'
|
||||||
|
import 'cropperjs/dist/cropper.css'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -42,7 +43,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dropzoneOptions: {
|
dropzoneOptions: {
|
||||||
url: this.addTeaserImage,
|
url: () => '',
|
||||||
maxFilesize: 5.0,
|
maxFilesize: 5.0,
|
||||||
previewTemplate: this.template(),
|
previewTemplate: this.template(),
|
||||||
},
|
},
|
||||||
@ -70,27 +71,51 @@ export default {
|
|||||||
this.error = true
|
this.error = true
|
||||||
this.$toast.error(file.status, message)
|
this.$toast.error(file.status, message)
|
||||||
},
|
},
|
||||||
addTeaserImage(file) {
|
transformImage(file) {
|
||||||
this.$emit('addTeaserImage', file[0])
|
let thumbnailElement, editor, confirm, thumbnailPreview, contributionImage
|
||||||
return ''
|
// Create the image editor overlay
|
||||||
|
editor = document.createElement('div')
|
||||||
|
thumbnailElement = document.querySelectorAll('#postdropzone')[0]
|
||||||
|
thumbnailPreview = document.querySelectorAll('.thumbnail-preview')[0]
|
||||||
|
if (thumbnailPreview) thumbnailPreview.remove()
|
||||||
|
contributionImage = document.querySelectorAll('.contribution-image')[0]
|
||||||
|
if (contributionImage) contributionImage.remove()
|
||||||
|
editor.classList.add('crop-overlay')
|
||||||
|
thumbnailElement.appendChild(editor)
|
||||||
|
// Create the confirm button
|
||||||
|
confirm = document.createElement('button')
|
||||||
|
confirm.classList.add('crop-confirm', 'ds-button', 'ds-button-primary')
|
||||||
|
confirm.textContent = this.$t('contribution.teaserImage.cropperConfirm')
|
||||||
|
confirm.addEventListener('click', () => {
|
||||||
|
// Get the canvas with image data from Cropper.js
|
||||||
|
let canvas = cropper.getCroppedCanvas()
|
||||||
|
canvas.toBlob(blob => {
|
||||||
|
this.$refs.el.manuallyAddFile(blob, canvas.toDataURL(), null, null, {
|
||||||
|
dontSubstractMaxFiles: false,
|
||||||
|
addToFiles: true,
|
||||||
|
})
|
||||||
|
image = new Image()
|
||||||
|
image.src = canvas.toDataURL()
|
||||||
|
image.classList.add('thumbnail-preview')
|
||||||
|
thumbnailElement.appendChild(image)
|
||||||
|
// Remove the editor from view
|
||||||
|
editor.parentNode.removeChild(editor)
|
||||||
|
const croppedImageFile = new File([blob], file.name, { type: 'image/jpeg' })
|
||||||
|
this.$emit('addTeaserImage', croppedImageFile)
|
||||||
|
}, 'image/jpeg')
|
||||||
|
})
|
||||||
|
editor.appendChild(confirm)
|
||||||
|
|
||||||
|
// Load the image
|
||||||
|
let image = new Image()
|
||||||
|
image.src = URL.createObjectURL(file)
|
||||||
|
editor.appendChild(image)
|
||||||
|
// Create Cropper.js and pass image
|
||||||
|
let cropper = new Cropper(image, { zoomable: false })
|
||||||
},
|
},
|
||||||
thumbnail: (file, dataUrl) => {
|
dropzoneDrop() {
|
||||||
let thumbnailElement, contributionImage, uploadArea, thumbnailPreview, image
|
let cropOverlay = document.querySelectorAll('.crop-overlay')[0]
|
||||||
if (file.previewElement) {
|
if (cropOverlay) cropOverlay.remove()
|
||||||
thumbnailElement = document.querySelectorAll('#postdropzone')[0]
|
|
||||||
contributionImage = document.querySelectorAll('.contribution-image')[0]
|
|
||||||
thumbnailPreview = document.querySelectorAll('.thumbnail-preview')[0]
|
|
||||||
if (contributionImage) {
|
|
||||||
uploadArea = document.querySelectorAll('.hc-attachments-upload-area-update-post')[0]
|
|
||||||
uploadArea.removeChild(contributionImage)
|
|
||||||
uploadArea.classList.remove('hc-attachments-upload-area-update-post')
|
|
||||||
}
|
|
||||||
image = new Image()
|
|
||||||
image.src = URL.createObjectURL(file)
|
|
||||||
image.classList.add('thumbnail-preview')
|
|
||||||
if (thumbnailPreview) return thumbnailElement.replaceChild(image, thumbnailPreview)
|
|
||||||
thumbnailElement.appendChild(image)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -98,16 +123,10 @@ export default {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
#postdropzone {
|
#postdropzone {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 300px;
|
min-height: 500px;
|
||||||
background-color: $background-color-softest;
|
background-color: $background-color-softest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 960px) {
|
|
||||||
#postdropzone {
|
|
||||||
min-height: 200px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hc-attachments-upload-area-post {
|
.hc-attachments-upload-area-post {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -134,11 +153,10 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin: 180px 5px;
|
||||||
color: hsl(0, 0%, 25%);
|
color: hsl(0, 0%, 25%);
|
||||||
transition: all 0.2s ease-out;
|
transition: all 0.2s ease-out;
|
||||||
font-size: 60px;
|
font-size: 60px;
|
||||||
margin: 80px 5px;
|
|
||||||
|
|
||||||
background-color: $background-color-softest;
|
background-color: $background-color-softest;
|
||||||
opacity: 0.65;
|
opacity: 0.65;
|
||||||
|
|
||||||
@ -178,7 +196,17 @@ export default {
|
|||||||
border-top: $border-size-base solid $border-color-softest;
|
border-top: $border-size-base solid $border-color-softest;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contribution-image {
|
.crop-overlay {
|
||||||
max-height: 300px;
|
max-height: 2000px;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crop-confirm {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
top: 10px;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -56,7 +56,7 @@ const user = {
|
|||||||
storiesOf('User', module)
|
storiesOf('User', module)
|
||||||
.addDecorator(withA11y)
|
.addDecorator(withA11y)
|
||||||
.addDecorator(helpers.layout)
|
.addDecorator(helpers.layout)
|
||||||
.add('available user', () => ({
|
.add('available', () => ({
|
||||||
components: { User },
|
components: { User },
|
||||||
store: helpers.store,
|
store: helpers.store,
|
||||||
data: () => ({
|
data: () => ({
|
||||||
@ -64,7 +64,21 @@ storiesOf('User', module)
|
|||||||
}),
|
}),
|
||||||
template: '<user :user="user" :trunc="35" :date-time="new Date()" />',
|
template: '<user :user="user" :trunc="35" :date-time="new Date()" />',
|
||||||
}))
|
}))
|
||||||
.add('anonymous user', () => ({
|
.add('has edited something', () => ({
|
||||||
|
components: { User },
|
||||||
|
store: helpers.store,
|
||||||
|
data: () => ({
|
||||||
|
user,
|
||||||
|
}),
|
||||||
|
template: `
|
||||||
|
<user :user="user" :trunc="35" :date-time="new Date()">
|
||||||
|
<template v-slot:dateTime>
|
||||||
|
- HEY! I'm edited
|
||||||
|
</template>
|
||||||
|
</user>
|
||||||
|
`,
|
||||||
|
}))
|
||||||
|
.add('anonymous', () => ({
|
||||||
components: { User },
|
components: { User },
|
||||||
store: helpers.store,
|
store: helpers.store,
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
|||||||
@ -11,17 +11,17 @@
|
|||||||
<div @mouseover="openMenu(true)" @mouseleave="closeMenu(true)">
|
<div @mouseover="openMenu(true)" @mouseleave="closeMenu(true)">
|
||||||
<hc-avatar class="avatar" :user="user" />
|
<hc-avatar class="avatar" :user="user" />
|
||||||
<div>
|
<div>
|
||||||
<ds-text align="left">
|
<ds-text>
|
||||||
<b class="username">{{ userName | truncate(18) }}</b>
|
<b class="username">{{ userName | truncate(18) }}</b>
|
||||||
<ds-text v-if="dateTime" size="small" color="soft">
|
<ds-text v-if="dateTime" size="small" color="soft">
|
||||||
<ds-icon name="clock" />
|
<ds-icon name="clock" />
|
||||||
<client-only>
|
<client-only>
|
||||||
<hc-relative-date-time :date-time="dateTime" />
|
<hc-relative-date-time :date-time="dateTime" />
|
||||||
</client-only>
|
</client-only>
|
||||||
|
<slot name="dateTime"></slot>
|
||||||
</ds-text>
|
</ds-text>
|
||||||
</ds-text>
|
</ds-text>
|
||||||
</div>
|
</div>
|
||||||
<!-- Time -->
|
|
||||||
<ds-text align="left" size="small" color="soft">
|
<ds-text align="left" size="small" color="soft">
|
||||||
{{ userSlug }}
|
{{ userSlug }}
|
||||||
</ds-text>
|
</ds-text>
|
||||||
|
|||||||
25
webapp/components/utils/ReportModal.js
Normal file
25
webapp/components/utils/ReportModal.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { valuesReasonCategoryOptions } from '~/constants/modals.js'
|
||||||
|
|
||||||
|
export default function validReport({ translate }) {
|
||||||
|
return {
|
||||||
|
formSchema: {
|
||||||
|
reasonCategory: {
|
||||||
|
type: 'object',
|
||||||
|
required: true,
|
||||||
|
fields: {
|
||||||
|
value: {
|
||||||
|
type: 'enum',
|
||||||
|
enum: valuesReasonCategoryOptions,
|
||||||
|
required: true,
|
||||||
|
message: translate('report.reason.category.invalid'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reasonDescription: {
|
||||||
|
type: 'string',
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
36
webapp/components/utils/ReportModal.spec.js
Normal file
36
webapp/components/utils/ReportModal.spec.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import validReport from './ReportModal'
|
||||||
|
import Schema from 'async-validator'
|
||||||
|
|
||||||
|
let translate
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
translate = jest.fn(() => 'Validation error')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('validReport', () => {
|
||||||
|
let validate = object => {
|
||||||
|
const { formSchema } = validReport({ translate })
|
||||||
|
const validator = new Schema(formSchema)
|
||||||
|
return validator.validate(object, { suppressWarning: true }).catch(({ errors }) => {
|
||||||
|
throw new Error(errors[0].message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('reasonCategory', () => {
|
||||||
|
describe('invalid enum', () => {
|
||||||
|
it('rejects', async () => {
|
||||||
|
await expect(validate({ reasonCategory: { value: 'invalid_enum' } })).rejects.toThrow(
|
||||||
|
'Validation error',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('valid enum', () => {
|
||||||
|
it('resolves', async () => {
|
||||||
|
await expect(
|
||||||
|
validate({ reasonCategory: { value: 'discrimination_etc' } }),
|
||||||
|
).resolves.toBeUndefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -1 +1,3 @@
|
|||||||
export const COMMENT_MIN_LENGTH = 1
|
export const COMMENT_MIN_LENGTH = 1
|
||||||
|
export const COMMENT_MAX_UNTRUNCATED_LENGTH = 300
|
||||||
|
export const COMMENT_TRUNCATE_TO_LENGTH = 180
|
||||||
|
|||||||
4
webapp/constants/emails.js
Normal file
4
webapp/constants/emails.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export const SUPPORT_EMAIL = {
|
||||||
|
href: 'mailto:support@human-connection.org',
|
||||||
|
label: 'support@human-connection.org',
|
||||||
|
}
|
||||||
11
webapp/constants/modals.js
Normal file
11
webapp/constants/modals.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// this list equals to enums in GraphQL schema file "backend/src/schema/types/type/REPORTED.gql"
|
||||||
|
export const valuesReasonCategoryOptions = [
|
||||||
|
'discrimination_etc',
|
||||||
|
'pornographic_content_links',
|
||||||
|
'glorific_trivia_of_cruel_inhuman_acts',
|
||||||
|
'doxing',
|
||||||
|
'intentional_intimidation_stalking_persecution',
|
||||||
|
'advert_products_services_commercial',
|
||||||
|
'criminal_behavior_violation_german_law',
|
||||||
|
'other',
|
||||||
|
]
|
||||||
@ -10,6 +10,7 @@ export default i18n => {
|
|||||||
contentExcerpt
|
contentExcerpt
|
||||||
content
|
content
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
disabled
|
disabled
|
||||||
deleted
|
deleted
|
||||||
author {
|
author {
|
||||||
@ -39,6 +40,7 @@ export default i18n => {
|
|||||||
contentExcerpt
|
contentExcerpt
|
||||||
content
|
content
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
disabled
|
disabled
|
||||||
deleted
|
deleted
|
||||||
author {
|
author {
|
||||||
|
|||||||
@ -40,6 +40,7 @@ export const postFragment = lang => gql`
|
|||||||
content
|
content
|
||||||
contentExcerpt
|
contentExcerpt
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
disabled
|
disabled
|
||||||
deleted
|
deleted
|
||||||
slug
|
slug
|
||||||
@ -64,6 +65,7 @@ export const commentFragment = lang => gql`
|
|||||||
fragment comment on Comment {
|
fragment comment on Comment {
|
||||||
id
|
id
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
disabled
|
disabled
|
||||||
deleted
|
deleted
|
||||||
content
|
content
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
export default app => {
|
export const reportListQuery = () => {
|
||||||
|
// no limit vor the moment like before: "reports(first: 20, orderBy: createdAt_desc)"
|
||||||
return gql`
|
return gql`
|
||||||
query {
|
query {
|
||||||
Report(first: 20, orderBy: createdAt_desc) {
|
reports(orderBy: createdAt_desc) {
|
||||||
id
|
|
||||||
description
|
|
||||||
type
|
|
||||||
createdAt
|
createdAt
|
||||||
|
reasonCategory
|
||||||
|
reasonDescription
|
||||||
|
type
|
||||||
submitter {
|
submitter {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
@ -79,3 +80,17 @@ export default app => {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const reportMutation = () => {
|
||||||
|
return gql`
|
||||||
|
mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
|
||||||
|
report(
|
||||||
|
resourceId: $resourceId
|
||||||
|
reasonCategory: $reasonCategory
|
||||||
|
reasonDescription: $reasonDescription
|
||||||
|
) {
|
||||||
|
type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
@ -135,6 +135,17 @@ export const unfollowUserMutation = i18n => {
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const allowEmbedIframesMutation = () => {
|
||||||
|
return gql`
|
||||||
|
mutation($id: ID!, $allowEmbedIframes: Boolean) {
|
||||||
|
UpdateUser(id: $id, allowEmbedIframes: $allowEmbedIframes) {
|
||||||
|
id
|
||||||
|
allowEmbedIframes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
export const checkSlugAvailableQuery = gql`
|
export const checkSlugAvailableQuery = gql`
|
||||||
query($slug: String!) {
|
query($slug: String!) {
|
||||||
User(slug: $slug) {
|
User(slug: $slug) {
|
||||||
|
|||||||
@ -1,8 +1,59 @@
|
|||||||
{
|
{
|
||||||
|
"components": {
|
||||||
|
"password-reset": {
|
||||||
|
"request": {
|
||||||
|
"form": {
|
||||||
|
"description": "Eine Mail zum Zurücksetzen des Passworts wird an die angegebene E-Mail Adresse geschickt.",
|
||||||
|
"submit": "Email anfordern",
|
||||||
|
"submitted": "Eine E-Mail mit weiteren Instruktionen wurde verschickt an <b>{email}</b>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"change-password": {
|
||||||
|
"success": "Änderung des Passworts war erfolgreich!",
|
||||||
|
"error": "Passwort Änderung fehlgeschlagen. Möglicherweise falscher Sicherheitscode?",
|
||||||
|
"help": "Falls Probleme auftreten, schreib uns gerne eine Mail an:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enter-nonce": {
|
||||||
|
"form": {
|
||||||
|
"nonce": "Code eingeben",
|
||||||
|
"description": "Öffne dein E-Mail Postfach und gib den Code ein, den wir geschickt haben.",
|
||||||
|
"next": "Weiter",
|
||||||
|
"validations": {
|
||||||
|
"length": "muss genau 6 Buchstaben lang sein"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"registration": {
|
||||||
|
"signup": {
|
||||||
|
"unavailable": "Leider ist die öffentliche Registrierung von Benutzerkonten auf diesem Server derzeit nicht möglich.",
|
||||||
|
"title": "Mach mit bei Human Connection!",
|
||||||
|
"form": {
|
||||||
|
"description": "Um loszulegen, gib deine E-Mail Adresse ein:",
|
||||||
|
"terms-and-condition": "Ich stimme den <a href=\"/terms-and-conditions\"><ds-text bold color=\"primary\" > Nutzungsbedingungen</ds-text></a>zu.",
|
||||||
|
"data-privacy": "Ich habe die <a href=\"https://human-connection.org/datenschutz/\" target=\"_blank\"><ds-text bold color=\"primary\" >Datenschutzerklärung</ds-text></a> gelesen und verstanden",
|
||||||
|
"minimum-age": "Ich bin 18 Jahre oder älter.",
|
||||||
|
"invitation-code": "Dein Einladungscode lautet: <b>{code}</b>",
|
||||||
|
"errors": {
|
||||||
|
"email-exists": "Es gibt schon ein Benutzerkonto mit dieser E-Mail Adresse!",
|
||||||
|
"invalid-invitation-token": "Es sieht so aus, als ob der Einladungscode schon eingelöst wurde. Jeder Code kann nur einmalig benutzt werden."
|
||||||
|
},
|
||||||
|
"submit": "Konto erstellen",
|
||||||
|
"success": "Eine Mail mit einem Bestätigungslink für die Registrierung wurde an <b>{email}</b> geschickt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"create-user-account": {
|
||||||
|
"title": "Benutzerkonto anlegen",
|
||||||
|
"success": "Dein Benutzerkonto wurde erstellt!",
|
||||||
|
"error": "Es konnte kein Benutzerkonto erstellt werden!",
|
||||||
|
"help": "Vielleicht war der Bestätigungscode falsch oder abgelaufen? Wenn das Problem weiterhin besteht, schick uns gerne eine E-Mail an:"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"maintenance": {
|
"maintenance": {
|
||||||
"title": "Human Connection befindet sich in der Wartung",
|
"title": "Human Connection befindet sich in der Wartung",
|
||||||
"explanation": "Zurzeit führen wir einige geplante Wartungsarbeiten durch, bitte versuch es später erneut.",
|
"explanation": "Zurzeit führen wir einige geplante Wartungsarbeiten durch, bitte versuch es später erneut.",
|
||||||
"questions": "Bei Fragen oder Problemen erreichst du uns per E-Mail an"
|
"questions": "Bei Fragen oder Problemen erreichst du uns per E-Mail an"
|
||||||
},
|
},
|
||||||
"index": {
|
"index": {
|
||||||
"no-results": "Keine Beiträge gefunden.",
|
"no-results": "Keine Beiträge gefunden.",
|
||||||
@ -42,7 +93,7 @@
|
|||||||
"bank": "Bankverbindung",
|
"bank": "Bankverbindung",
|
||||||
"germany": "Deutschland",
|
"germany": "Deutschland",
|
||||||
"code-of-conduct": "Verhaltenscodex",
|
"code-of-conduct": "Verhaltenscodex",
|
||||||
"login": "Zurück zum Anmeldung"
|
"back-to-login": "Zurück zur Anmeldung"
|
||||||
},
|
},
|
||||||
"sorting": {
|
"sorting": {
|
||||||
"newest": "Neueste",
|
"newest": "Neueste",
|
||||||
@ -55,50 +106,14 @@
|
|||||||
"email": "Deine E-Mail",
|
"email": "Deine E-Mail",
|
||||||
"password": "Dein Passwort",
|
"password": "Dein Passwort",
|
||||||
"forgotPassword": "Passwort vergessen?",
|
"forgotPassword": "Passwort vergessen?",
|
||||||
|
"no-account": "Du hast noch kein Benutzerkonto?",
|
||||||
|
"register": "Benutzerkonto erstellen",
|
||||||
"moreInfo": "Was ist Human Connection?",
|
"moreInfo": "Was ist Human Connection?",
|
||||||
"moreInfoURL": "https://human-connection.org",
|
"moreInfoURL": "https://human-connection.org",
|
||||||
"moreInfoHint": "zur Präsentationsseite",
|
"moreInfoHint": "zur Präsentationsseite",
|
||||||
"hello": "Hallo",
|
"hello": "Hallo",
|
||||||
"success": "Du bist eingeloggt!"
|
"success": "Du bist eingeloggt!"
|
||||||
},
|
},
|
||||||
"password-reset": {
|
|
||||||
"form": {
|
|
||||||
"description": "Eine Mail zum Zurücksetzen des Passworts wird an die angegebene E-Mail Adresse geschickt.",
|
|
||||||
"submit": "Email anfordern",
|
|
||||||
"submitted": "Eine E-Mail mit weiteren Instruktionen wurde verschickt an <b>{email}</b>"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"registration": {
|
|
||||||
"signup": {
|
|
||||||
"title": "Mach mit bei Human Connection!",
|
|
||||||
"form": {
|
|
||||||
"description": "Um loszulegen, gib deine E-Mail Adresse ein:",
|
|
||||||
"invitation-code": "Dein Einladungscode lautet: <b>{code}</b>",
|
|
||||||
"errors": {
|
|
||||||
"email-exists": "Es gibt schon ein Benutzerkonto mit dieser E-Mail Adresse!",
|
|
||||||
"invalid-invitation-token": "Es sieht so aus, als ob der Einladungscode schon eingelöst wurde. Jeder Code kann nur einmalig benutzt werden."
|
|
||||||
},
|
|
||||||
"submit": "Konto erstellen",
|
|
||||||
"success": "Eine Mail mit einem Bestätigungslink für die Registrierung wurde an <b>{email}</b> geschickt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"create-user-account": {
|
|
||||||
"title": "Benutzerkonto anlegen",
|
|
||||||
"success": "Dein Benutzerkonto wurde erstellt!"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"verify-nonce": {
|
|
||||||
"form": {
|
|
||||||
"nonce": "Code eingeben",
|
|
||||||
"description": "Öffne dein E-Mail Postfach und gib den Code ein, den wir geschickt haben.",
|
|
||||||
"next": "Weiter",
|
|
||||||
"change-password": {
|
|
||||||
"success": "Änderung des Passworts war erfolgreich!",
|
|
||||||
"error": "Passwort Änderung fehlgeschlagen. Möglicherweise falscher Sicherheitscode?",
|
|
||||||
"help": "Falls Probleme auftreten, schreib uns gerne eine Mail an:"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"editor": {
|
"editor": {
|
||||||
"placeholder": "Schreib etwas Inspirierendes …",
|
"placeholder": "Schreib etwas Inspirierendes …",
|
||||||
"mention": {
|
"mention": {
|
||||||
@ -108,6 +123,12 @@
|
|||||||
"noHashtagsFound": "Keine Hashtags gefunden",
|
"noHashtagsFound": "Keine Hashtags gefunden",
|
||||||
"addHashtag": "Neuer Hashtag",
|
"addHashtag": "Neuer Hashtag",
|
||||||
"addLetter": "Tippe einen Buchstaben"
|
"addLetter": "Tippe einen Buchstaben"
|
||||||
|
},
|
||||||
|
"embed": {
|
||||||
|
"data_privacy_warning": "Achte auf deine Daten!",
|
||||||
|
"data_privacy_info": "Deine Daten wurden noch nicht an Drittanbieter weitergegeben. Wenn du dieses Video jetzt abspielst, registriert der folgende Anbieter wahrscheinlich deine Nutzerdaten:",
|
||||||
|
"play_now": "Jetzt ansehen",
|
||||||
|
"always_allow": "Inhalte von Drittanbietern immer anzeigen (diese Einstellung kannst du jederzeit ändern)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
@ -220,6 +241,22 @@
|
|||||||
"success": "Konto erfolgreich gelöscht!",
|
"success": "Konto erfolgreich gelöscht!",
|
||||||
"pleaseConfirm": "<b class='is-danger'>Zerstörerische Aktion!</b> Gib <b>{confirm}</b> ein, um zu bestätigen."
|
"pleaseConfirm": "<b class='is-danger'>Zerstörerische Aktion!</b> Gib <b>{confirm}</b> ein, um zu bestätigen."
|
||||||
},
|
},
|
||||||
|
"embeds": {
|
||||||
|
"name": "Drittanbieter",
|
||||||
|
"info-description": "Hier ist die Liste an Drittanbietern, deren Inhalte als Fremdcode z.B. in Form von eingebetteten Videos angezeigt werden kann:",
|
||||||
|
"status": {
|
||||||
|
"description": "Als Grundeinstellung für dich wird eingebetter Fremdcode von Drittanbietern",
|
||||||
|
"disabled": {
|
||||||
|
"off": "zunächst nicht angezeigt",
|
||||||
|
"on": "sofort angezeigt"
|
||||||
|
},
|
||||||
|
"change": {
|
||||||
|
"question": "Soll eingebetter Fremdcode von Dritten für dich immer angezeigt werden?",
|
||||||
|
"allow": "Na klar",
|
||||||
|
"deny": "Lieber nicht"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"organizations": {
|
"organizations": {
|
||||||
"name": "Meine Organisationen"
|
"name": "Meine Organisationen"
|
||||||
},
|
},
|
||||||
@ -280,6 +317,7 @@
|
|||||||
"columns": {
|
"columns": {
|
||||||
"number": "Nr.",
|
"number": "Nr.",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
|
"email": "E-mail",
|
||||||
"slug": "Slug",
|
"slug": "Slug",
|
||||||
"role": "Rolle",
|
"role": "Rolle",
|
||||||
"createdAt": "Erstellt am"
|
"createdAt": "Erstellt am"
|
||||||
@ -335,7 +373,8 @@
|
|||||||
"submit": "Kommentiere",
|
"submit": "Kommentiere",
|
||||||
"submitted": "Kommentar Gesendet",
|
"submitted": "Kommentar Gesendet",
|
||||||
"updated": "Änderungen gespeichert"
|
"updated": "Änderungen gespeichert"
|
||||||
}
|
},
|
||||||
|
"edited": "bearbeitet"
|
||||||
},
|
},
|
||||||
"comment": {
|
"comment": {
|
||||||
"content": {
|
"content": {
|
||||||
@ -348,10 +387,11 @@
|
|||||||
"show": {
|
"show": {
|
||||||
"more": "mehr anzeigen",
|
"more": "mehr anzeigen",
|
||||||
"less": "weniger anzeigen"
|
"less": "weniger anzeigen"
|
||||||
}
|
},
|
||||||
|
"edited": "bearbeitet"
|
||||||
},
|
},
|
||||||
"quotes": {
|
"quotes": {
|
||||||
"african": {
|
"african": {
|
||||||
"quote": "Viele kleine Leute an vielen kleinen Orten, die viele kleine Dinge tun, werden das Antlitz dieser Welt verändern.",
|
"quote": "Viele kleine Leute an vielen kleinen Orten, die viele kleine Dinge tun, werden das Antlitz dieser Welt verändern.",
|
||||||
"author": "Afrikanisches Sprichwort"
|
"author": "Afrikanisches Sprichwort"
|
||||||
}
|
}
|
||||||
@ -375,8 +415,7 @@
|
|||||||
"reportContent": "Melden",
|
"reportContent": "Melden",
|
||||||
"validations": {
|
"validations": {
|
||||||
"email": "muss eine gültige E-Mail Adresse sein",
|
"email": "muss eine gültige E-Mail Adresse sein",
|
||||||
"url": "muss eine gültige URL sein",
|
"url": "muss eine gültige URL sein"
|
||||||
"verification-nonce": "muss genau 6 Buchstaben lang sein"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
@ -393,8 +432,11 @@
|
|||||||
"reports": {
|
"reports": {
|
||||||
"empty": "Glückwunsch, es gibt nichts zu moderieren.",
|
"empty": "Glückwunsch, es gibt nichts zu moderieren.",
|
||||||
"name": "Meldungen",
|
"name": "Meldungen",
|
||||||
"submitter": "gemeldet von",
|
"reasonCategory": "Kategorie",
|
||||||
"disabledBy": "deaktiviert von"
|
"reasonDescription": "Beschreibung",
|
||||||
|
"createdAt": "Datum",
|
||||||
|
"submitter": "Gemeldet von",
|
||||||
|
"disabledBy": "Deaktiviert von"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"disable": {
|
"disable": {
|
||||||
@ -454,6 +496,27 @@
|
|||||||
"type": "Kommentar",
|
"type": "Kommentar",
|
||||||
"message": "Bist du sicher, dass du den Kommentar von \"<b>{name}</b>\" melden möchtest?",
|
"message": "Bist du sicher, dass du den Kommentar von \"<b>{name}</b>\" melden möchtest?",
|
||||||
"error": "Du hast den Kommentar bereits gemeldet!"
|
"error": "Du hast den Kommentar bereits gemeldet!"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"category": {
|
||||||
|
"label": "Wähle eine Kategorie:",
|
||||||
|
"placeholder": "Kategorie …",
|
||||||
|
"options": {
|
||||||
|
"discrimination_etc": "Diskriminierende Beiträge, Kommentare, Äußerungen oder Beleidigungen.",
|
||||||
|
"pornographic_content_links": "Das Posten oder Verlinken eindeutig pornografischen Materials.",
|
||||||
|
"glorific_trivia_of_cruel_inhuman_acts": "Verherrlichung oder Verharmlosung grausamer oder unmenschlicher Gewalttätigkeiten.",
|
||||||
|
"doxing": "Das Veröffentlichen von personenbezogenen Daten anderer ohne deren Einverständnis oder das Androhen dessen (\"Doxing\").",
|
||||||
|
"intentional_intimidation_stalking_persecution": "Absichtliche Einschüchterung, Stalking oder Verfolgung.",
|
||||||
|
"advert_products_services_commercial": "Bewerben von Produkten und Dienstleistungen mit kommerzieller Absicht.",
|
||||||
|
"criminal_behavior_violation_german_law": "Strafbares Verhalten bzw. Verstoß gegen deutsches Recht.",
|
||||||
|
"other": "Andere …"
|
||||||
|
},
|
||||||
|
"invalid": "Bitte wähle eine gültige Kategorie aus"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"label": "Bitte erkläre: Warum möchtest du dies melden?",
|
||||||
|
"placeholder": "Zusätzliche Information …"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"followButton": {
|
"followButton": {
|
||||||
@ -492,6 +555,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contribution": {
|
"contribution": {
|
||||||
|
"title": "Titel",
|
||||||
"newPost": "Erstelle einen neuen Beitrag",
|
"newPost": "Erstelle einen neuen Beitrag",
|
||||||
"filterFollow": "Beiträge filtern von Usern denen ich folge",
|
"filterFollow": "Beiträge filtern von Usern denen ich folge",
|
||||||
"filterALL": "Alle Beiträge anzeigen",
|
"filterALL": "Alle Beiträge anzeigen",
|
||||||
@ -526,6 +590,9 @@
|
|||||||
"it-internet-data-privacy": "IT, Internet & Datenschutz",
|
"it-internet-data-privacy": "IT, Internet & Datenschutz",
|
||||||
"art-culture-sport": "Kunst, Kultur & Sport"
|
"art-culture-sport": "Kunst, Kultur & Sport"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"teaserImage": {
|
||||||
|
"cropperConfirm": "Bestätigen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"code-of-conduct": {
|
"code-of-conduct": {
|
||||||
|
|||||||
@ -1,8 +1,60 @@
|
|||||||
{
|
{
|
||||||
|
"components": {
|
||||||
|
"password-reset": {
|
||||||
|
"request": {
|
||||||
|
"title": "Reset your password",
|
||||||
|
"form": {
|
||||||
|
"description": "A password reset e-mail will be sent to the given e-mail address.",
|
||||||
|
"submit": "Request e-mail",
|
||||||
|
"submitted": "An e-mail with further instructions has been sent to <b>{email}</b>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"change-password": {
|
||||||
|
"success": "Changing your password was successful!",
|
||||||
|
"error": "Changing your password failed. Maybe the security code was not correct?",
|
||||||
|
"help": "In case of problems, feel free to ask for help by sending us a mail to:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enter-nonce": {
|
||||||
|
"form": {
|
||||||
|
"nonce": "Enter your code",
|
||||||
|
"description": "Open your inbox and enter the code that we've sent to you.",
|
||||||
|
"next": "Continue",
|
||||||
|
"validations": {
|
||||||
|
"length": "must be 6 characters long"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"registration": {
|
||||||
|
"signup": {
|
||||||
|
"unavailable": "Unfortunately, public registration of user accounts is not available right now on this server.",
|
||||||
|
"title": "Join Human Connection!",
|
||||||
|
"form": {
|
||||||
|
"description": "To get started, enter your e-mail address:",
|
||||||
|
"terms-and-condition": "I confirm to the <a href=\"/terms-and-conditions\"><ds-text bold color=\"primary\" > Terms and conditions</ds-text></a>.",
|
||||||
|
"data-privacy": " I have read and understood the <a href=\"https://human-connection.org/datenschutz/\" target=\"_blank\"><ds-text bold color=\"primary\" >Privacy Statement</ds-text></a> ",
|
||||||
|
"minimum-age": "I'm 18 years or older.",
|
||||||
|
"invitation-code": "Your invitation code is: <b>{code}</b>",
|
||||||
|
"errors": {
|
||||||
|
"email-exists": "There is already a user account with this e-mail address!",
|
||||||
|
"invalid-invitation-token": "It looks like as if the invitation has been used already. Invitation links can only be used once."
|
||||||
|
},
|
||||||
|
"submit": "Create an account",
|
||||||
|
"success": "A mail with a link to complete your registration has been sent to <b>{email}</b>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"create-user-account": {
|
||||||
|
"title": "Create user account",
|
||||||
|
"success": "Your account has been created!",
|
||||||
|
"error": "No user account could be created!",
|
||||||
|
"help": " Maybe the confirmation was invalid? In case of problems, feel free to ask for help by sending us a mail to:"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"maintenance": {
|
"maintenance": {
|
||||||
"title": "Human Connection is under maintenance",
|
"title": "Human Connection is under maintenance",
|
||||||
"explanation": "At the moment we are doing some scheduled maintenance, please try again later.",
|
"explanation": "At the moment we are doing some scheduled maintenance, please try again later.",
|
||||||
"questions": "Any Questions or concerns, send an email to"
|
"questions": "Any Questions or concerns, send an e-mail to"
|
||||||
},
|
},
|
||||||
"index": {
|
"index": {
|
||||||
"no-results": "No contributions found.",
|
"no-results": "No contributions found.",
|
||||||
@ -42,7 +94,7 @@
|
|||||||
"bank": "bank account",
|
"bank": "bank account",
|
||||||
"germany": "Germany",
|
"germany": "Germany",
|
||||||
"code-of-conduct": "Code of Conduct",
|
"code-of-conduct": "Code of Conduct",
|
||||||
"login": "Back to login"
|
"back-to-login": "Back to login page"
|
||||||
},
|
},
|
||||||
"sorting": {
|
"sorting": {
|
||||||
"newest": "Newest",
|
"newest": "Newest",
|
||||||
@ -52,54 +104,17 @@
|
|||||||
"copy": "If you already have a human-connection account, please login.",
|
"copy": "If you already have a human-connection account, please login.",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
"email": "Your Email",
|
"email": "Your E-mail",
|
||||||
"password": "Your Password",
|
"password": "Your Password",
|
||||||
"forgotPassword": "Forgot Password?",
|
"forgotPassword": "Forgot Password?",
|
||||||
|
"no-account": "Don't have an account?",
|
||||||
|
"register": "Sign up",
|
||||||
"moreInfo": "What is Human Connection?",
|
"moreInfo": "What is Human Connection?",
|
||||||
"moreInfoURL": "https://human-connection.org/en/",
|
"moreInfoURL": "https://human-connection.org/en/",
|
||||||
"moreInfoHint": "to the presentation page",
|
"moreInfoHint": "to the presentation page",
|
||||||
"hello": "Hello",
|
"hello": "Hello",
|
||||||
"success": "You are logged in!"
|
"success": "You are logged in!"
|
||||||
},
|
},
|
||||||
"password-reset": {
|
|
||||||
"title": "Reset your password",
|
|
||||||
"form": {
|
|
||||||
"description": "A password reset email will be sent to the given email address.",
|
|
||||||
"submit": "Request email",
|
|
||||||
"submitted": "An email with further instructions has been sent to <b>{email}</b>"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"registration": {
|
|
||||||
"signup": {
|
|
||||||
"title": "Join Human Connection!",
|
|
||||||
"form": {
|
|
||||||
"description": "To get started, enter your email address:",
|
|
||||||
"invitation-code": "Your invitation code is: <b>{code}</b>",
|
|
||||||
"errors": {
|
|
||||||
"email-exists": "There is already a user account with this email address!",
|
|
||||||
"invalid-invitation-token": "It looks like as if the invitation has been used already. Invitation links can only be used once."
|
|
||||||
},
|
|
||||||
"submit": "Create an account",
|
|
||||||
"success": "A mail with a link to complete your registration has been sent to <b>{email}</b>"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"create-user-account": {
|
|
||||||
"title": "Create user account",
|
|
||||||
"success": "Your account has been created!"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"verify-nonce": {
|
|
||||||
"form": {
|
|
||||||
"nonce": "Enter your code",
|
|
||||||
"description": "Open your inbox and enter the code that we've sent to you.",
|
|
||||||
"next": "Continue",
|
|
||||||
"change-password": {
|
|
||||||
"success": "Changing your password was successful!",
|
|
||||||
"error": "Changing your password failed. Maybe the security code was not correct?",
|
|
||||||
"help": "In case of problems, feel free to ask for help by sending us a mail to:"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"editor": {
|
"editor": {
|
||||||
"placeholder": "Leave your inspirational thoughts …",
|
"placeholder": "Leave your inspirational thoughts …",
|
||||||
"mention": {
|
"mention": {
|
||||||
@ -109,6 +124,12 @@
|
|||||||
"noHashtagsFound": "No hashtags found",
|
"noHashtagsFound": "No hashtags found",
|
||||||
"addHashtag": "New hashtag",
|
"addHashtag": "New hashtag",
|
||||||
"addLetter": "Type a letter"
|
"addLetter": "Type a letter"
|
||||||
|
},
|
||||||
|
"embed": {
|
||||||
|
"data_privacy_warning": "Data Privacy Warning!",
|
||||||
|
"data_privacy_info": "Your data has not yet been shared with any third party providers. If you proceed to watch this video the following provider will likely collect user data:",
|
||||||
|
"play_now": "Watch now",
|
||||||
|
"always_allow": "Always allow embedded content by third party providers (this setting can be changed any time)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
@ -131,8 +152,8 @@
|
|||||||
},
|
},
|
||||||
"invites": {
|
"invites": {
|
||||||
"title": "Invite somebody to Human Connection!",
|
"title": "Invite somebody to Human Connection!",
|
||||||
"description": "Enter thier email address for invitation.",
|
"description": "Enter thier e-mail address for invitation.",
|
||||||
"emailPlaceholder": "Email to invite"
|
"emailPlaceholder": "E-mail to invite"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
@ -161,23 +182,23 @@
|
|||||||
},
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"validation": {
|
"validation": {
|
||||||
"same-email": "This is your current email address"
|
"same-email": "This is your current e-mail address"
|
||||||
},
|
},
|
||||||
"name": "Your email",
|
"name": "Your e-mail",
|
||||||
"labelEmail": "Change your email address",
|
"labelEmail": "Change your e-mail address",
|
||||||
"labelNewEmail": "New email Address",
|
"labelNewEmail": "New e-mail Address",
|
||||||
"labelNonce": "Enter your code",
|
"labelNonce": "Enter your code",
|
||||||
"success": "A new email address has been registered.",
|
"success": "A new e-mail address has been registered.",
|
||||||
"submitted": "An email to verify your address has been sent to <b>{email}</b>.",
|
"submitted": "An e-mail to verify your address has been sent to <b>{email}</b>.",
|
||||||
"change-successful": "Your email address has been changed successfully.",
|
"change-successful": "Your e-mail address has been changed successfully.",
|
||||||
"verification-error": {
|
"verification-error": {
|
||||||
"message": "Your email could not be changed.",
|
"message": "Your e-mail could not be changed.",
|
||||||
"explanation": "This can have different causes:",
|
"explanation": "This can have different causes:",
|
||||||
"reason": {
|
"reason": {
|
||||||
"invalid-nonce": "Is the confirmation code invalid?",
|
"invalid-nonce": "Is the confirmation code invalid?",
|
||||||
"no-email-request": "Are you certain that you requested a change of your email address?"
|
"no-email-request": "Are you certain that you requested a change of your e-mail address?"
|
||||||
},
|
},
|
||||||
"support": "If the problem persists, please contact us by email at"
|
"support": "If the problem persists, please contact us by e-mail at"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
@ -221,6 +242,22 @@
|
|||||||
"success": "Account successfully deleted!",
|
"success": "Account successfully deleted!",
|
||||||
"pleaseConfirm": "<b class='is-danger'>Destructive action!</b> Type <b>{confirm}</b> to confirm"
|
"pleaseConfirm": "<b class='is-danger'>Destructive action!</b> Type <b>{confirm}</b> to confirm"
|
||||||
},
|
},
|
||||||
|
"embeds": {
|
||||||
|
"name": "Third party providers",
|
||||||
|
"info-description": "Here is the list of third-party providers whose content can be displayed as third-party code, e.g. in the form of embedded videos.",
|
||||||
|
"status": {
|
||||||
|
"description": "As a default for you, embedded code of third-party providers is",
|
||||||
|
"disabled": {
|
||||||
|
"off": "initially not displayed",
|
||||||
|
"on": "displayed immediately"
|
||||||
|
},
|
||||||
|
"change": {
|
||||||
|
"question": "Should embedded source code from third parties always be displayed to you?",
|
||||||
|
"allow": "Sure",
|
||||||
|
"deny": "No thanks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"organizations": {
|
"organizations": {
|
||||||
"name": "My Organizations"
|
"name": "My Organizations"
|
||||||
},
|
},
|
||||||
@ -275,12 +312,13 @@
|
|||||||
"users": {
|
"users": {
|
||||||
"name": "Users",
|
"name": "Users",
|
||||||
"form": {
|
"form": {
|
||||||
"placeholder": "email, name or description"
|
"placeholder": "e-mail, name or description"
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"columns": {
|
"columns": {
|
||||||
"number": "No.",
|
"number": "No.",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
|
"email": "E-mail",
|
||||||
"slug": "Slug",
|
"slug": "Slug",
|
||||||
"role": "Role",
|
"role": "Role",
|
||||||
"createdAt": "Created at"
|
"createdAt": "Created at"
|
||||||
@ -336,7 +374,8 @@
|
|||||||
"submit": "Comment",
|
"submit": "Comment",
|
||||||
"submitted": "Comment Submitted",
|
"submitted": "Comment Submitted",
|
||||||
"updated": "Changes Saved"
|
"updated": "Changes Saved"
|
||||||
}
|
},
|
||||||
|
"edited": "edited"
|
||||||
},
|
},
|
||||||
"comment": {
|
"comment": {
|
||||||
"content": {
|
"content": {
|
||||||
@ -349,7 +388,8 @@
|
|||||||
"show": {
|
"show": {
|
||||||
"more": "show more",
|
"more": "show more",
|
||||||
"less": "show less"
|
"less": "show less"
|
||||||
}
|
},
|
||||||
|
"edited": "edited"
|
||||||
},
|
},
|
||||||
"quotes": {
|
"quotes": {
|
||||||
"african": {
|
"african": {
|
||||||
@ -375,9 +415,8 @@
|
|||||||
"loading": "loading",
|
"loading": "loading",
|
||||||
"reportContent": "Report",
|
"reportContent": "Report",
|
||||||
"validations": {
|
"validations": {
|
||||||
"email": "must be a valid email address",
|
"email": "must be a valid e-mail address",
|
||||||
"url": "must be a valid URL",
|
"url": "must be a valid URL"
|
||||||
"verification-nonce": "must be 6 characters long"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
@ -394,8 +433,11 @@
|
|||||||
"reports": {
|
"reports": {
|
||||||
"empty": "Congratulations, nothing to moderate.",
|
"empty": "Congratulations, nothing to moderate.",
|
||||||
"name": "Reports",
|
"name": "Reports",
|
||||||
"submitter": "reported by",
|
"reasonCategory": "Category",
|
||||||
"disabledBy": "disabled by"
|
"reasonDescription": "Description",
|
||||||
|
"createdAt": "Date",
|
||||||
|
"submitter": "Reported by",
|
||||||
|
"disabledBy": "Disabled by"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"disable": {
|
"disable": {
|
||||||
@ -455,6 +497,27 @@
|
|||||||
"type": "Comment",
|
"type": "Comment",
|
||||||
"message": "Do you really want to report the comment from \"<b>{name}</b>\"?",
|
"message": "Do you really want to report the comment from \"<b>{name}</b>\"?",
|
||||||
"error": "You have already reported the comment!"
|
"error": "You have already reported the comment!"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"category": {
|
||||||
|
"label": "Select a category:",
|
||||||
|
"placeholder": "Category …",
|
||||||
|
"options": {
|
||||||
|
"discrimination_etc": "Discriminatory posts, comments, utterances or insults.",
|
||||||
|
"pornographic_content_links": "Posting or linking of clearly pornographic material.",
|
||||||
|
"glorific_trivia_of_cruel_inhuman_acts": "Glorification or trivialization of cruel or inhuman acts of violence.",
|
||||||
|
"doxing": "The disclosure of others' personal information without their consent or threat there of (\"doxing\").",
|
||||||
|
"intentional_intimidation_stalking_persecution": "Intentional intimidation, stalking or persecution.",
|
||||||
|
"advert_products_services_commercial": "Advertising products and services with commercial intent.",
|
||||||
|
"criminal_behavior_violation_german_law": "Criminal behavior or violation of German law.",
|
||||||
|
"other": "Other …"
|
||||||
|
},
|
||||||
|
"invalid": "Please select a valid category"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"label": "Please explain: Why you like to report this?",
|
||||||
|
"placeholder": "Additional information …"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"followButton": {
|
"followButton": {
|
||||||
@ -493,6 +556,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contribution": {
|
"contribution": {
|
||||||
|
"title": "Title",
|
||||||
"newPost": "Create a new Post",
|
"newPost": "Create a new Post",
|
||||||
"filterFollow": "Filter contributions from users I follow",
|
"filterFollow": "Filter contributions from users I follow",
|
||||||
"filterALL": "View all contributions",
|
"filterALL": "View all contributions",
|
||||||
@ -527,6 +591,9 @@
|
|||||||
"it-internet-data-privacy": "IT, Internet & Data Privacy",
|
"it-internet-data-privacy": "IT, Internet & Data Privacy",
|
||||||
"art-culture-sport": "Art, Culture, & Sport"
|
"art-culture-sport": "Art, Culture, & Sport"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"teaserImage": {
|
||||||
|
"cropperConfirm": "Confirm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"code-of-conduct": {
|
"code-of-conduct": {
|
||||||
|
|||||||
@ -292,6 +292,11 @@
|
|||||||
"message": "¿Realmente quieres liberar el comentario de \"<b>{name}</b>\"?"
|
"message": "¿Realmente quieres liberar el comentario de \"<b>{name}</b>\"?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"contribution": {
|
||||||
|
"teaserImage": {
|
||||||
|
"cropperConfirm": "Confirmar"
|
||||||
|
}
|
||||||
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"avatar": {
|
"avatar": {
|
||||||
"submitted": "Carga con éxito"
|
"submitted": "Carga con éxito"
|
||||||
|
|||||||
@ -287,6 +287,11 @@
|
|||||||
"message": "Voulez-vous vraiment publier le commentaire de \"<b>{name}</b>\"?"
|
"message": "Voulez-vous vraiment publier le commentaire de \"<b>{name}</b>\"?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"contribution": {
|
||||||
|
"teaserImage": {
|
||||||
|
"cropperConfirm": "Confirmer"
|
||||||
|
}
|
||||||
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"avatar": {
|
"avatar": {
|
||||||
"submitted": "Téléchargement réussi"
|
"submitted": "Téléchargement réussi"
|
||||||
|
|||||||
@ -1,50 +1,67 @@
|
|||||||
module.exports = [
|
import { enUS, de, nl, fr, es, it, pt, pl } from 'date-fns/locale'
|
||||||
|
import find from 'lodash/find'
|
||||||
|
|
||||||
|
const locales = [
|
||||||
{
|
{
|
||||||
name: 'English',
|
name: 'English',
|
||||||
code: 'en',
|
code: 'en',
|
||||||
iso: 'en-US',
|
iso: 'en-US',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
dateFnsLocale: enUS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Deutsch',
|
name: 'Deutsch',
|
||||||
code: 'de',
|
code: 'de',
|
||||||
iso: 'de-DE',
|
iso: 'de-DE',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
dateFnsLocale: de,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Nederlands',
|
name: 'Nederlands',
|
||||||
code: 'nl',
|
code: 'nl',
|
||||||
iso: 'nl-NL',
|
iso: 'nl-NL',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
dateFnsLocale: nl,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Français',
|
name: 'Français',
|
||||||
code: 'fr',
|
code: 'fr',
|
||||||
iso: 'fr-FR',
|
iso: 'fr-FR',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
dateFnsLocale: fr,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Italiano',
|
name: 'Italiano',
|
||||||
code: 'it',
|
code: 'it',
|
||||||
iso: 'it-IT',
|
iso: 'it-IT',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
dateFnsLocale: it,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Español',
|
name: 'Español',
|
||||||
code: 'es',
|
code: 'es',
|
||||||
iso: 'es-ES',
|
iso: 'es-ES',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
dateFnsLocale: es,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Português',
|
name: 'Português',
|
||||||
code: 'pt',
|
code: 'pt',
|
||||||
iso: 'pt-PT',
|
iso: 'pt-PT',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
dateFnsLocale: pt,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Polski',
|
name: 'Polski',
|
||||||
code: 'pl',
|
code: 'pl',
|
||||||
iso: 'pl-PL',
|
iso: 'pl-PL',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
dateFnsLocale: pl,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export default locales
|
||||||
|
export function getDateFnsLocale({ $i18n }) {
|
||||||
|
const { dateFnsLocale } = find(locales, { code: $i18n.locale() }) || {}
|
||||||
|
return dateFnsLocale || enUS
|
||||||
|
}
|
||||||
|
|||||||
@ -140,5 +140,10 @@
|
|||||||
"save": "Salva",
|
"save": "Salva",
|
||||||
"edit": "Modifica",
|
"edit": "Modifica",
|
||||||
"delete": "Cancella"
|
"delete": "Cancella"
|
||||||
|
},
|
||||||
|
"contribution": {
|
||||||
|
"teaserImage": {
|
||||||
|
"cropperConfirm": "Confermare"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -158,7 +158,10 @@
|
|||||||
},
|
},
|
||||||
"contribution": {
|
"contribution": {
|
||||||
"edit": "Bijdrage bewerken",
|
"edit": "Bijdrage bewerken",
|
||||||
"delete": "Bijdrage verwijderen"
|
"delete": "Bijdrage verwijderen",
|
||||||
|
"teaserImage": {
|
||||||
|
"cropperConfirm": "Bevestigen"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"comment": {
|
"comment": {
|
||||||
"edit": "Commentaar bewerken",
|
"edit": "Commentaar bewerken",
|
||||||
|
|||||||
@ -1,4 +1,31 @@
|
|||||||
{
|
{
|
||||||
|
"components": {
|
||||||
|
"password-reset": {
|
||||||
|
"request": {
|
||||||
|
"title": "Zresetuj hasło",
|
||||||
|
"form": {
|
||||||
|
"description": "Na podany adres e-mail zostanie wysłany email z resetem hasła.",
|
||||||
|
"submit": "Poproś o wiadomość e-mail",
|
||||||
|
"submitted": "Na adres <b>{email}</b> została wysłana wiadomość z dalszymi instrukcjami."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"change-password": {
|
||||||
|
"success": "Zmiana hasła zakończyła się sukcesem!",
|
||||||
|
"error": "Zmiana hasła nie powiodła się. Może kod bezpieczeństwa nie był poprawny?",
|
||||||
|
"help": "W przypadku problemów, zachęcamy do zwrócenia się o pomoc, wysyłając do nas wiadomość e-mail:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enter-nonce": {
|
||||||
|
"form": {
|
||||||
|
"nonce": "Wprowadź swój kod",
|
||||||
|
"description": "Otwórz swoją skrzynkę odbiorczą i wpisz kod, który do Ciebie wysłaliśmy.",
|
||||||
|
"next": "Kontynuuj",
|
||||||
|
"validations": {
|
||||||
|
"length": "musi mieć długość 6 znaków."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"filter-menu": {
|
"filter-menu": {
|
||||||
"title": "Twoja bańka filtrująca"
|
"title": "Twoja bańka filtrująca"
|
||||||
},
|
},
|
||||||
@ -29,26 +56,6 @@
|
|||||||
"moreInfoHint": "idź po więcej szczegółów",
|
"moreInfoHint": "idź po więcej szczegółów",
|
||||||
"hello": "Cześć"
|
"hello": "Cześć"
|
||||||
},
|
},
|
||||||
"password-reset": {
|
|
||||||
"title": "Zresetuj hasło",
|
|
||||||
"form": {
|
|
||||||
"description": "Na podany adres e-mail zostanie wysłany email z resetem hasła.",
|
|
||||||
"submit": "Poproś o wiadomość e-mail",
|
|
||||||
"submitted": "Na adres <b>{email}</b> została wysłana wiadomość z dalszymi instrukcjami."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"verify-nonce": {
|
|
||||||
"form": {
|
|
||||||
"nonce": "Wprowadź swój kod",
|
|
||||||
"description": "Otwórz swoją skrzynkę odbiorczą i wpisz kod, który do Ciebie wysłaliśmy.",
|
|
||||||
"next": "Kontynuuj",
|
|
||||||
"change-password": {
|
|
||||||
"success": "Zmiana hasła zakończyła się sukcesem!",
|
|
||||||
"error": "Zmiana hasła nie powiodła się. Może kod bezpieczeństwa nie był poprawny?",
|
|
||||||
"help": "W przypadku problemów, zachęcamy do zwrócenia się o pomoc, wysyłając do nas wiadomość e-mail:"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"editor": {
|
"editor": {
|
||||||
"placeholder": "Napisz coś inspirującego..."
|
"placeholder": "Napisz coś inspirującego..."
|
||||||
},
|
},
|
||||||
@ -236,8 +243,7 @@
|
|||||||
"loading": "załadunek",
|
"loading": "załadunek",
|
||||||
"reportContent": "Sprawozdanie",
|
"reportContent": "Sprawozdanie",
|
||||||
"validations": {
|
"validations": {
|
||||||
"email": "musi być ważny adres e-mail.",
|
"email": "musi być ważny adres e-mail."
|
||||||
"verification-nonce": "musi mieć długość 6 znaków."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
@ -356,6 +362,9 @@
|
|||||||
"languageSelectLabel": "Język",
|
"languageSelectLabel": "Język",
|
||||||
"categories": {
|
"categories": {
|
||||||
"infoSelectedNoOfMaxCategories": "{chosen} z {max} wybrane kategorie"
|
"infoSelectedNoOfMaxCategories": "{chosen} z {max} wybrane kategorie"
|
||||||
|
},
|
||||||
|
"teaserImage": {
|
||||||
|
"cropperConfirm": "Potwierdzać"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -118,7 +118,11 @@
|
|||||||
},
|
},
|
||||||
"takeAction": {
|
"takeAction": {
|
||||||
"name": "Tomar uma ação"
|
"name": "Tomar uma ação"
|
||||||
}
|
},
|
||||||
|
"comment": {
|
||||||
|
"submit": "Commentar"
|
||||||
|
},
|
||||||
|
"edited": "editado"
|
||||||
},
|
},
|
||||||
"quotes": {
|
"quotes": {
|
||||||
"african": {
|
"african": {
|
||||||
@ -198,12 +202,26 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"contribution": {
|
"contribution": {
|
||||||
|
"title": "Título",
|
||||||
"edit": "Editar Contribuição",
|
"edit": "Editar Contribuição",
|
||||||
"delete": "Apagar Contribuição"
|
"delete": "Apagar Contribuição",
|
||||||
|
"teaserImage": {
|
||||||
|
"cropperConfirm": "Confirmar"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"comment": {
|
"comment": {
|
||||||
"edit": "Editar Comentário",
|
"content": {
|
||||||
"delete": "Apagar Comentário"
|
"unavailable-placeholder": "… este commenttário não está disponível"
|
||||||
|
},
|
||||||
|
"menu": {
|
||||||
|
"edit": "Editar Comentário",
|
||||||
|
"delete": "Apagar Comentário"
|
||||||
|
},
|
||||||
|
"show": {
|
||||||
|
"more": "mostrar mais",
|
||||||
|
"less": "mostrar menos"
|
||||||
|
},
|
||||||
|
"edited": "editado"
|
||||||
},
|
},
|
||||||
"followButton": {
|
"followButton": {
|
||||||
"follow": "Seguir",
|
"follow": "Seguir",
|
||||||
@ -212,4 +230,4 @@
|
|||||||
"shoutButton": {
|
"shoutButton": {
|
||||||
"shouted": "Aclamou"
|
"shouted": "Aclamou"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,10 @@
|
|||||||
import defaultConfig from './nuxt.config.js'
|
import defaultConfig from './nuxt.config.js'
|
||||||
|
|
||||||
const {
|
const { css, styleResources, manifest } = defaultConfig
|
||||||
css,
|
|
||||||
styleResources,
|
|
||||||
env: { locales },
|
|
||||||
manifest,
|
|
||||||
} = defaultConfig
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
css,
|
css,
|
||||||
styleResources,
|
styleResources,
|
||||||
env: { locales },
|
|
||||||
manifest,
|
manifest,
|
||||||
|
|
||||||
head: {
|
head: {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user