mirror of
https://github.com/wassname/talk.git
synced 2026-06-27 19:17:09 +08:00
Merge pull request #1837 from coralproject/relay-1.7
[next] Implement PostComment Mutation, Upgrade Relay
This commit is contained in:
@@ -45,6 +45,9 @@ jobs:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ~/coralproject/talk
|
||||
- run:
|
||||
name: Compile schemas and types
|
||||
command: npm run compile
|
||||
- run:
|
||||
name: Perform linting
|
||||
command: npm run lint
|
||||
|
||||
Generated
+286
-161
@@ -1342,9 +1342,9 @@
|
||||
}
|
||||
},
|
||||
"@coralproject/rte": {
|
||||
"version": "0.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@coralproject/rte/-/rte-0.10.6.tgz",
|
||||
"integrity": "sha512-oUK/KSw28AkmpX5D8v1IkQT0iIxKxPmSG0euTFgqEthSgnAUQgoOmQengaR/nsS9zE31KPbbWMIAzH0aN/YwNA==",
|
||||
"version": "0.10.9",
|
||||
"resolved": "https://registry.npmjs.org/@coralproject/rte/-/rte-0.10.9.tgz",
|
||||
"integrity": "sha512-0K+bc3JaOhjgJJ91uupev4EmSoldd/IizfjRgAQ8LbZjRc3pWprzIBhoTMChApBzz7eI9DUfw2ULg5muziV8BA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bowser": "^1.0.0",
|
||||
@@ -1580,6 +1580,15 @@
|
||||
"lodash.deburr": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"@sinonjs/commons": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.0.2.tgz",
|
||||
"integrity": "sha512-WR3dlgqJP4QNrLC4iXN/5/2WaLQQ0VijOOkmflqFGVJ6wLEpbSjo7c0ZeGIdtY8Crk7xBBp87sM6+Mkerz7alw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-detect": "4.0.8"
|
||||
}
|
||||
},
|
||||
"@sinonjs/formatio": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz",
|
||||
@@ -2069,9 +2078,14 @@
|
||||
}
|
||||
},
|
||||
"@types/react-relay": {
|
||||
"version": "github:coralproject/patched#ba4c8d01bb737e5f073534b32d870294e39cc5a8",
|
||||
"from": "github:coralproject/patched#types/react-relay",
|
||||
"dev": true
|
||||
"version": "1.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-relay/-/react-relay-1.3.9.tgz",
|
||||
"integrity": "sha512-DFhFrEiDUYxR6VWpkf14CnzS7vtpWaVku0EmnxT2X4U45rOUP75nnOEnRCixZyyxIgr7ULpg5Zc1G9VJpQF7GQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*",
|
||||
"@types/relay-runtime": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-responsive": {
|
||||
"version": "3.0.1",
|
||||
@@ -2107,8 +2121,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/relay-runtime": {
|
||||
"version": "github:coralproject/patched#ba8d413696e97b4f67450de3525cc319b9980cba",
|
||||
"from": "github:coralproject/patched#types/relay-runtime",
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/relay-runtime/-/relay-runtime-1.3.6.tgz",
|
||||
"integrity": "sha512-NobpY0XFh0O9FTRkFJsN5ZNd+M+4eac8ZgM5LP3C0tLd1JkfrwuGkyBUMTuDDGYf+T5zl6vTO6EGgXKD+0QpGA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/sane": {
|
||||
@@ -2188,6 +2203,15 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/vinyl": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.2.tgz",
|
||||
"integrity": "sha512-2iYpNuOl98SrLPBZfEN9Mh2JCJ2EI9HU35SfgBEb51DcmaHkhp8cKMblYeBqMQiwXMgAD3W60DbQ4i/UdLiXhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/webpack": {
|
||||
"version": "4.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.4.7.tgz",
|
||||
@@ -3697,13 +3721,14 @@
|
||||
}
|
||||
},
|
||||
"babel-plugin-relay": {
|
||||
"version": "github:coralproject/patched#80c179a21ece1a43e4782c776f3041fe5ab14a4a",
|
||||
"from": "github:coralproject/patched#babel-plugin-relay",
|
||||
"version": "1.7.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-relay/-/babel-plugin-relay-1.7.0-rc.1.tgz",
|
||||
"integrity": "sha512-VklvYrB0kSZeDHGtwJNtDtoQNVrI+ZclURnsCBwWU5oIX4f21//cYeQ9oooJDIvXcCApFKhaozP5tfWgk+Fo5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-plugin-macros": "^2.0.0",
|
||||
"babel-runtime": "^6.23.0",
|
||||
"babel-types": "^6.24.1",
|
||||
"graphql": "^0.13.0"
|
||||
"babel-types": "^6.24.1"
|
||||
}
|
||||
},
|
||||
"babel-plugin-syntax-class-properties": {
|
||||
@@ -4043,9 +4068,9 @@
|
||||
}
|
||||
},
|
||||
"babel-preset-fbjs": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-2.1.4.tgz",
|
||||
"integrity": "sha512-6XVQwlO26V5/0P9s2Eje8Epqkv/ihaMJ798+W98ktOA8fCn2IFM6wEi7CDW3fTbKFZ/8fDGvGZH01B6GSuNiWA==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-2.2.0.tgz",
|
||||
"integrity": "sha512-jj0KFJDioYZMtPtZf77dQuU+Ad/1BtN0UnAYlHDa8J8f4tGXr3YrPoJImD5MdueaOPeN/jUdrCgu330EfXr0XQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-plugin-check-es2015-constants": "^6.8.0",
|
||||
@@ -5157,12 +5182,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"babylon": {
|
||||
"version": "7.0.0-beta.31",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz",
|
||||
"integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ==",
|
||||
"dev": true
|
||||
},
|
||||
"bach": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz",
|
||||
@@ -8430,6 +8449,12 @@
|
||||
"long": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||
"dev": true
|
||||
},
|
||||
"babylon": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
|
||||
@@ -8490,14 +8515,6 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8548,6 +8565,21 @@
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
|
||||
"integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
|
||||
@@ -8573,9 +8605,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-5.0.1.tgz",
|
||||
"integrity": "sha512-+y92rG6pmXt3cpcg/NGmG4w/W309tWNSmyyPL8hCMxuCSg2UP/hUg3npACj2UZc8UKVSXexyLrCnxowizGoAsw==",
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-5.0.2.tgz",
|
||||
"integrity": "sha512-d2FbKvYe4XAQx5gjHBoWG+ADqC3fGZzjb7i9vxd/Y5xfLkBGtQyX7aOb8lBRQPYUhjngiD3d49LevjY1stUR0Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"address": "1.0.3",
|
||||
@@ -8590,10 +8622,10 @@
|
||||
"inquirer": "3.3.0",
|
||||
"is-root": "1.0.0",
|
||||
"opn": "5.2.0",
|
||||
"react-error-overlay": "^4.0.0",
|
||||
"react-error-overlay": "^4.0.1",
|
||||
"recursive-readdir": "2.2.1",
|
||||
"shell-quote": "1.6.1",
|
||||
"sockjs-client": "1.1.4",
|
||||
"sockjs-client": "1.1.5",
|
||||
"strip-ansi": "3.0.1",
|
||||
"text-table": "0.2.0"
|
||||
},
|
||||
@@ -8610,6 +8642,121 @@
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"filesize": {
|
||||
"version": "3.5.11",
|
||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.5.11.tgz",
|
||||
"integrity": "sha512-ZH7loueKBoDb7yG9esn1U+fgq7BzlzW6NRi5/rMdxIZ05dj7GFD/Xc5rq2CDt5Yq86CyfSYVyx4242QQNZbx1g==",
|
||||
"dev": true
|
||||
},
|
||||
"gzip-size": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz",
|
||||
"integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"duplexer": "^0.1.1"
|
||||
}
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
|
||||
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "^3.0.0",
|
||||
"chalk": "^2.0.0",
|
||||
"cli-cursor": "^2.1.0",
|
||||
"cli-width": "^2.0.0",
|
||||
"external-editor": "^2.0.4",
|
||||
"figures": "^2.0.0",
|
||||
"lodash": "^4.3.0",
|
||||
"mute-stream": "0.0.7",
|
||||
"run-async": "^2.2.0",
|
||||
"rx-lite": "^4.0.8",
|
||||
"rx-lite-aggregates": "^4.0.8",
|
||||
"string-width": "^2.1.0",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"through": "^2.3.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
|
||||
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-error-overlay": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-4.0.1.tgz",
|
||||
"integrity": "sha512-xXUbDAZkU08aAkjtUvldqbvI04ogv+a1XdHxvYuHPYKIVk/42BIOD0zSKTHAWV4+gDy3yGm283z2072rA2gdtw==",
|
||||
"dev": true
|
||||
},
|
||||
"recursive-readdir": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.1.tgz",
|
||||
"integrity": "sha1-kO8jHQd4xc4JPJpI105cVCLROpk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimatch": "3.0.3"
|
||||
}
|
||||
},
|
||||
"sockjs-client": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.5.tgz",
|
||||
"integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^2.6.6",
|
||||
"eventsource": "0.1.6",
|
||||
"faye-websocket": "~0.11.0",
|
||||
"inherits": "^2.0.1",
|
||||
"json3": "^3.3.2",
|
||||
"url-parse": "^1.1.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -9792,12 +9939,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"filesize": {
|
||||
"version": "3.5.11",
|
||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.5.11.tgz",
|
||||
"integrity": "sha512-ZH7loueKBoDb7yG9esn1U+fgq7BzlzW6NRi5/rMdxIZ05dj7GFD/Xc5rq2CDt5Yq86CyfSYVyx4242QQNZbx1g==",
|
||||
"dev": true
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
|
||||
@@ -11095,6 +11236,32 @@
|
||||
"iterall": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"graphql-compiler": {
|
||||
"version": "1.7.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/graphql-compiler/-/graphql-compiler-1.7.0-rc.1.tgz",
|
||||
"integrity": "sha512-wu1HMcI39I2Ion1N+nrn9ELGMFGi6lFDz+dJuJwnlO3BdXTrSVvYnnusxNaim4/Gkmf9tM/ErYSbpvRzBWPk3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^1.1.1",
|
||||
"fb-watchman": "^2.0.0",
|
||||
"immutable": "~3.7.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"graphql-config": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-2.0.1.tgz",
|
||||
@@ -11518,15 +11685,6 @@
|
||||
"glogg": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"gzip-size": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz",
|
||||
"integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"duplexer": "^0.1.1"
|
||||
}
|
||||
},
|
||||
"handle-thing": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
|
||||
@@ -12208,45 +12366,6 @@
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"dev": true
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
|
||||
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "^3.0.0",
|
||||
"chalk": "^2.0.0",
|
||||
"cli-cursor": "^2.1.0",
|
||||
"cli-width": "^2.0.0",
|
||||
"external-editor": "^2.0.4",
|
||||
"figures": "^2.0.0",
|
||||
"lodash": "^4.3.0",
|
||||
"mute-stream": "0.0.7",
|
||||
"run-async": "^2.2.0",
|
||||
"rx-lite": "^4.0.8",
|
||||
"rx-lite-aggregates": "^4.0.8",
|
||||
"string-width": "^2.1.0",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"through": "^2.3.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||
"dev": true
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal-ip": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz",
|
||||
@@ -15120,9 +15239,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"just-extend": {
|
||||
"version": "1.1.27",
|
||||
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz",
|
||||
"integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-3.0.0.tgz",
|
||||
"integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==",
|
||||
"dev": true
|
||||
},
|
||||
"jwa": {
|
||||
@@ -16670,13 +16789,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"nise": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/nise/-/nise-1.4.2.tgz",
|
||||
"integrity": "sha512-BxH/DxoQYYdhKgVAfqVy4pzXRZELHOIewzoesxpjYvpU+7YOalQhGNPf7wAx8pLrTNPrHRDlLOkAl8UI0ZpXjw==",
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/nise/-/nise-1.4.4.tgz",
|
||||
"integrity": "sha512-pxE0c9PzgrUTyhfv5p+5eMIdfU2bLEsq8VQEuE0kxM4zP7SujSar7rk9wpI2F7RyyCEvLyj5O7Is3RER5F36Fg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sinonjs/formatio": "^2.0.0",
|
||||
"just-extend": "^1.1.27",
|
||||
"just-extend": "^3.0.0",
|
||||
"lolex": "^2.3.2",
|
||||
"path-to-regexp": "^1.7.0",
|
||||
"text-encoding": "^0.6.4"
|
||||
@@ -20780,12 +20899,6 @@
|
||||
"create-emotion-styled": "^9.2.6"
|
||||
}
|
||||
},
|
||||
"react-error-overlay": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-4.0.0.tgz",
|
||||
"integrity": "sha512-FlsPxavEyMuR6TjVbSSywovXSEyOg6ZDj5+Z8nbsRl9EkOzAhEIcS+GLoQDC5fz/t9suhUXWmUrOBrgeUvrMxw==",
|
||||
"dev": true
|
||||
},
|
||||
"react-feather": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-feather/-/react-feather-1.1.1.tgz",
|
||||
@@ -20889,13 +21002,15 @@
|
||||
}
|
||||
},
|
||||
"react-relay": {
|
||||
"version": "github:coralproject/patched#aad037f8cbcd9c14d5f6fd96cfafb24c39eab937",
|
||||
"from": "github:coralproject/patched#react-relay",
|
||||
"version": "1.7.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/react-relay/-/react-relay-1.7.0-rc.1.tgz",
|
||||
"integrity": "sha512-5BcnFr++zkfq5AVoCjcqr8eotuJwVN+57+BnhJZuw3EoY8Yi+avV/AqZ7Tz9F6r9p5xZkCoYZw3kRTtpK9lPSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-runtime": "^6.23.0",
|
||||
"fbjs": "^0.8.14",
|
||||
"prop-types": "^15.5.8"
|
||||
"fbjs": "0.8.17",
|
||||
"prop-types": "^15.5.8",
|
||||
"relay-runtime": "1.7.0-rc.1"
|
||||
}
|
||||
},
|
||||
"react-responsive": {
|
||||
@@ -21120,26 +21235,6 @@
|
||||
"symbol-observable": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"recursive-readdir": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.1.tgz",
|
||||
"integrity": "sha1-kO8jHQd4xc4JPJpI105cVCLROpk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimatch": "3.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
|
||||
"integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"redent": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz",
|
||||
@@ -21332,27 +21427,59 @@
|
||||
"dev": true
|
||||
},
|
||||
"relay-compiler": {
|
||||
"version": "github:coralproject/patched#652bdfa85cf35ed3e8dc4e26cf26e9d1744873cb",
|
||||
"from": "github:coralproject/patched#relay-compiler",
|
||||
"version": "1.7.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/relay-compiler/-/relay-compiler-1.7.0-rc.1.tgz",
|
||||
"integrity": "sha512-NCbrAWG692dp0on3sefX0pZ+1/eWDPOnme/i0vAbH38ejfRW5vPS9pznHYS7A0y7OC5lABMZT+DCyEYeHFpflA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-generator": "^6.26.0",
|
||||
"@babel/generator": "7.0.0-beta.56",
|
||||
"@babel/parser": "7.0.0-beta.56",
|
||||
"@babel/types": "7.0.0-beta.56",
|
||||
"babel-polyfill": "^6.20.0",
|
||||
"babel-preset-fbjs": "^2.1.4",
|
||||
"babel-preset-fbjs": "2.2.0",
|
||||
"babel-runtime": "^6.23.0",
|
||||
"babel-traverse": "^6.26.0",
|
||||
"babel-types": "^6.24.1",
|
||||
"babylon": "^7.0.0-beta",
|
||||
"chalk": "^1.1.1",
|
||||
"fast-glob": "^2.0.0",
|
||||
"fast-glob": "^2.2.2",
|
||||
"fb-watchman": "^2.0.0",
|
||||
"fbjs": "^0.8.14",
|
||||
"graphql": "^0.13.0",
|
||||
"fbjs": "0.8.17",
|
||||
"graphql-compiler": "1.7.0-rc.1",
|
||||
"immutable": "~3.7.6",
|
||||
"relay-runtime": "1.7.0-rc.1",
|
||||
"signedsource": "^1.0.0",
|
||||
"yargs": "^9.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/generator": {
|
||||
"version": "7.0.0-beta.56",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.56.tgz",
|
||||
"integrity": "sha512-d+Ls/Vr5OU5FBDYQToXSqAluI3r2UaSoNZ41zD3sxdoVoaT8K5Bdh4So4eG4o//INGM7actValXGfb+5J1+r8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "7.0.0-beta.56",
|
||||
"jsesc": "^2.5.1",
|
||||
"lodash": "^4.17.10",
|
||||
"source-map": "^0.5.0",
|
||||
"trim-right": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.0.0-beta.56",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.0.0-beta.56.tgz",
|
||||
"integrity": "sha512-JM0ughhbo+sPXw2Z+SUyowfYrAOhjanzjMshcLswBdXVelJCOeEKe/FqMqPWGVPQr7wByongXIn+MKdCpY7DBw==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.0.0-beta.56",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.56.tgz",
|
||||
"integrity": "sha512-fRIBeHtKxAD3D1E7hYSpG4MnLt0AfzHHs5gfVclOB0NlfLu3qiWU/IqdbK2ixTK61424iEkV1P/VAzndx6ungA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2",
|
||||
"lodash": "^4.17.10",
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"babel-polyfill": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
|
||||
@@ -21535,8 +21662,9 @@
|
||||
}
|
||||
},
|
||||
"relay-compiler-language-typescript": {
|
||||
"version": "github:coralproject/patched#0da4835cf006e905c154d1e41aa978f81ace54f3",
|
||||
"from": "github:coralproject/patched#relay-compiler-language-typescript",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/relay-compiler-language-typescript/-/relay-compiler-language-typescript-1.1.0.tgz",
|
||||
"integrity": "sha512-HDWTEsSsNuphmNrjbc1Tf1ljVjbi2CSA7zArsFFYCYHfVU/O7oS3qv/u5E+LrHdYSM80AjpUVjdcFGsqkgOmNw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"immutable": "^3.7.6",
|
||||
@@ -21550,23 +21678,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"relay-runtime": {
|
||||
"version": "github:coralproject/patched#9dda7718393cb3aa6647bd3badf574c025f79d12",
|
||||
"from": "github:coralproject/patched#relay-runtime",
|
||||
"version": "1.7.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-1.7.0-rc.1.tgz",
|
||||
"integrity": "sha512-gdhtIKojPA0FJPc4hPGAbxZBAR2xpnCvCuoL4/wu3ffHxwUFvSSlBIptW3GSxTRM2F55vl7I1IeehCS9IAfQPA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-runtime": "^6.23.0",
|
||||
"fbjs": "^0.8.14"
|
||||
}
|
||||
},
|
||||
"relay-test-utils": {
|
||||
"version": "github:coralproject/patched#eee4232d3996db88c4ae9030023adcf1f3674615",
|
||||
"from": "github:coralproject/patched#relay-test-utils",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-runtime": "^6.23.0",
|
||||
"fbjs": "^0.8.14",
|
||||
"graphql": "^0.13.0",
|
||||
"prop-types": "^15.5.8"
|
||||
"fbjs": "0.8.17"
|
||||
}
|
||||
},
|
||||
"remark": {
|
||||
@@ -22406,25 +22524,26 @@
|
||||
"dev": true
|
||||
},
|
||||
"sinon": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/sinon/-/sinon-6.1.3.tgz",
|
||||
"integrity": "sha512-yeTza8xIZZdiXntCHJAzKll/sSYE+DuJOS8hiSapzaLqdW8eCNVVC9je9SZYYTkPm2bLts9x6UYxwuMAVVrM6Q==",
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/sinon/-/sinon-6.1.5.tgz",
|
||||
"integrity": "sha512-TcbRoWs1SdY6NOqfj0c9OEQquBoZH+qEf8799m1jjcbfWrrpyCQ3B/BpX7+NKa7Vn33Jl+Z50H4Oys3bzygK2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sinonjs/commons": "^1.0.1",
|
||||
"@sinonjs/formatio": "^2.0.0",
|
||||
"@sinonjs/samsam": "^2.0.0",
|
||||
"diff": "^3.5.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"lolex": "^2.4.2",
|
||||
"nise": "^1.3.3",
|
||||
"lolex": "^2.7.1",
|
||||
"nise": "^1.4.2",
|
||||
"supports-color": "^5.4.0",
|
||||
"type-detect": "^4.0.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
|
||||
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
@@ -23396,6 +23515,12 @@
|
||||
"integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=",
|
||||
"dev": true
|
||||
},
|
||||
"timekeeper": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/timekeeper/-/timekeeper-2.1.2.tgz",
|
||||
"integrity": "sha512-fc1DDqbiyz5vxRO4xkiATwfWUw1FV7W20+FJYal1SnoIYgNuB4WNxYLtbG3zjUBwOSk3P4u1TgBAZYG/aqBWMw==",
|
||||
"dev": true
|
||||
},
|
||||
"timers-browserify": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
|
||||
@@ -24153,9 +24278,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.1.tgz",
|
||||
"integrity": "sha512-zQIMOmC+372pC/CCVLqnQ0zSBiY7HHodU7mpQdjiZddek4GMj31I3dUJ7gAs9o65X7mnRma6OokOkc6f9jjfBg==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.3.tgz",
|
||||
"integrity": "sha512-kk80vLW9iGtjMnIv11qyxLqZm20UklzuR2tL0QAnDIygIUIemcZMxlMWudl9OOt76H3ntVzcTiddQ1/pAAJMYg==",
|
||||
"dev": true
|
||||
},
|
||||
"ua-parser-js": {
|
||||
|
||||
+13
-12
@@ -15,7 +15,7 @@
|
||||
"start": "node dist/index.js",
|
||||
"start:development": "ts-node --project ./src/tsconfig.json -r tsconfig-paths/register ./src/index.ts",
|
||||
"start:webpackDevServer": "ts-node ./scripts/start.ts",
|
||||
"lint": "npm-run-all --parallel lint:*",
|
||||
"lint": "npm-run-all --parallel lint:* tscheck:*",
|
||||
"lint:server": "tslint --project ./src/tsconfig.json",
|
||||
"lint:client": "tslint --project ./src/core/client/tsconfig.json",
|
||||
"lint:client-embed": "tslint --project ./src/core/client/embed/tsconfig.json",
|
||||
@@ -76,7 +76,7 @@
|
||||
"@babel/polyfill": "7.0.0-beta.49",
|
||||
"@babel/preset-env": "7.0.0-beta.49",
|
||||
"@babel/preset-react": "7.0.0-beta.49",
|
||||
"@coralproject/rte": "^0.10.6",
|
||||
"@coralproject/rte": "^0.10.9",
|
||||
"@types/bcryptjs": "^2.4.1",
|
||||
"@types/bunyan": "^1.8.4",
|
||||
"@types/case-sensitive-paths-webpack-plugin": "^2.1.2",
|
||||
@@ -116,16 +116,17 @@
|
||||
"@types/query-string": "^6.1.0",
|
||||
"@types/react-copy-to-clipboard": "^4.2.5",
|
||||
"@types/react-dom": "^16.0.6",
|
||||
"@types/react-relay": "github:coralproject/patched#types/react-relay",
|
||||
"@types/react-relay": "^1.3.9",
|
||||
"@types/react-responsive": "^3.0.1",
|
||||
"@types/react-test-renderer": "^16.0.1",
|
||||
"@types/recompose": "^0.26.1",
|
||||
"@types/relay-runtime": "github:coralproject/patched#types/relay-runtime",
|
||||
"@types/relay-runtime": "^1.3.6",
|
||||
"@types/sane": "^2.0.0",
|
||||
"@types/sinon": "^5.0.1",
|
||||
"@types/tlds": "^1.199.0",
|
||||
"@types/uglifyjs-webpack-plugin": "^1.1.0",
|
||||
"@types/uuid": "^3.4.3",
|
||||
"@types/vinyl": "^2.0.2",
|
||||
"@types/webpack": "^4.4.7",
|
||||
"@types/webpack-dev-server": "^2.9.5",
|
||||
"@types/webpack-manifest-plugin": "^1.3.2",
|
||||
@@ -134,7 +135,7 @@
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-loader": "^8.0.0-beta",
|
||||
"babel-plugin-module-resolver": "^3.1.1",
|
||||
"babel-plugin-relay": "github:coralproject/patched#babel-plugin-relay",
|
||||
"babel-plugin-relay": "^1.7.0-rc.1",
|
||||
"babel-preset-react-optimize": "^1.0.1",
|
||||
"case-sensitive-paths-webpack-plugin": "^2.1.2",
|
||||
"chalk": "^2.4.1",
|
||||
@@ -194,21 +195,21 @@
|
||||
"react-dom": "^16.4.0",
|
||||
"react-final-form": "^3.6.4",
|
||||
"react-popper": "^1.0.0",
|
||||
"react-relay": "github:coralproject/patched#react-relay",
|
||||
"react-relay": "^1.7.0-rc.1",
|
||||
"react-responsive": "^5.0.0",
|
||||
"react-test-renderer": "^16.4.2",
|
||||
"react-timeago": "^4.1.9",
|
||||
"react-with-state-props": "^2.0.4",
|
||||
"recompose": "^0.27.1",
|
||||
"relay-compiler": "github:coralproject/patched#relay-compiler",
|
||||
"relay-compiler-language-typescript": "github:coralproject/patched#relay-compiler-language-typescript",
|
||||
"relay-compiler": "^1.7.0-rc.1",
|
||||
"relay-compiler-language-typescript": "^1.1.0",
|
||||
"relay-local-schema": "^0.7.0",
|
||||
"relay-runtime": "github:coralproject/patched#relay-runtime",
|
||||
"relay-test-utils": "github:coralproject/patched#relay-test-utils",
|
||||
"relay-runtime": "^1.7.0-rc.1",
|
||||
"sane": "^2.5.2",
|
||||
"simulant": "^0.2.2",
|
||||
"sinon": "^6.1.3",
|
||||
"sinon": "^6.1.5",
|
||||
"style-loader": "^0.21.0",
|
||||
"timekeeper": "^2.1.2",
|
||||
"ts-jest": "^23.0.0",
|
||||
"ts-loader": "^4.4.2",
|
||||
"ts-node": "^6.2.0",
|
||||
@@ -222,7 +223,7 @@
|
||||
"typed-css-modules": "^0.3.4",
|
||||
"typeface-manuale": "0.0.54",
|
||||
"typeface-source-sans-pro": "0.0.54",
|
||||
"typescript": "^3.0.0",
|
||||
"typescript": "^3.0.3",
|
||||
"uglifyjs-webpack-plugin": "^1.2.5",
|
||||
"webpack": "4.12.0",
|
||||
"webpack-cli": "^3.0.2",
|
||||
|
||||
@@ -6,8 +6,6 @@ import ResetPasswordContainer from "../containers/ResetPasswordContainer";
|
||||
import SignInContainer from "../containers/SignInContainer";
|
||||
import SignUpContainer from "../containers/SignUpContainer";
|
||||
|
||||
// TODO: (cvle) Remove %future added value when we have Relay 1.6
|
||||
// https://github.com/facebook/relay/commit/1e87e43add7667a494f7ff4cfa7f03f1ab8d81a2
|
||||
export type View =
|
||||
| "SIGN_UP"
|
||||
| "SIGN_IN"
|
||||
|
||||
@@ -14,7 +14,7 @@ const AppContainer: StatelessComponent<InnerProps> = ({ local: { view } }) => {
|
||||
return <App view={view} />;
|
||||
};
|
||||
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
const enhanced = withLocalStateContainer(
|
||||
graphql`
|
||||
fragment AppContainerLocal on Local {
|
||||
view
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Environment, ROOT_ID } from "relay-runtime";
|
||||
|
||||
export default function getMe(environment: Environment) {
|
||||
const source = environment.getStore().getSource();
|
||||
const root = source.get(ROOT_ID)!;
|
||||
const meKey = Object.keys(root).find(s => s.startsWith("me("))!;
|
||||
if (!root[meKey]) {
|
||||
return null;
|
||||
}
|
||||
const meID = root[meKey].__ref;
|
||||
return source.get(meID)!;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default as getMe } from "./getMe";
|
||||
@@ -3,23 +3,25 @@ import {
|
||||
QueryRenderer,
|
||||
QueryRendererProps as QueryRendererPropsOrig,
|
||||
} from "react-relay";
|
||||
import { OperationBase, OperationDefaults } from "relay-runtime";
|
||||
|
||||
import { Omit } from "talk-framework/types";
|
||||
|
||||
import { TalkContextConsumer } from "../bootstrap/TalkContext";
|
||||
|
||||
// Omit environment as we are passing this from the context.
|
||||
export type QueryRendererProps<V, R> = Omit<
|
||||
QueryRendererPropsOrig<V, R>,
|
||||
"environment"
|
||||
>;
|
||||
export type QueryRendererProps<
|
||||
T extends OperationBase = OperationDefaults
|
||||
> = Omit<QueryRendererPropsOrig<T>, "environment">;
|
||||
|
||||
/**
|
||||
* TalkQueryRenderer is a wrappper around Relay's `QueryRenderer`.
|
||||
* It supplies the `environment` from the context and has better
|
||||
* generics type support.
|
||||
*/
|
||||
class TalkQueryRenderer<V, R> extends Component<QueryRendererProps<V, R>> {
|
||||
class TalkQueryRenderer<
|
||||
T extends OperationBase = OperationDefaults
|
||||
> extends Component<QueryRendererProps<T>> {
|
||||
public render() {
|
||||
return (
|
||||
<TalkContextConsumer>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { commitMutation } from "react-relay";
|
||||
import { Environment, MutationConfig } from "relay-runtime";
|
||||
import { Environment, MutationConfig, OperationBase } from "relay-runtime";
|
||||
|
||||
import { Omit } from "talk-framework/types";
|
||||
|
||||
@@ -7,8 +7,8 @@ import { Omit } from "talk-framework/types";
|
||||
* Like `MutationConfig` but omits `onCompleted` and `onError`
|
||||
* because we are going to use a Promise API.
|
||||
*/
|
||||
export type MutationPromiseConfig<T, U> = Omit<
|
||||
MutationConfig<T, U>,
|
||||
export type MutationPromiseConfig<T extends OperationBase> = Omit<
|
||||
MutationConfig<T>,
|
||||
"onCompleted" | "onError"
|
||||
>;
|
||||
|
||||
@@ -27,10 +27,10 @@ function getPayload(response: { [key: string]: any }): any {
|
||||
* and errors are wrapped inside of application specific
|
||||
* error instances.
|
||||
*/
|
||||
export async function commitMutationPromiseNormalized<R, V>(
|
||||
export async function commitMutationPromiseNormalized<T extends OperationBase>(
|
||||
environment: Environment,
|
||||
config: MutationPromiseConfig<R, V>
|
||||
): Promise<R> {
|
||||
config: MutationPromiseConfig<T>
|
||||
): Promise<T["response"][keyof T["response"]]> {
|
||||
try {
|
||||
const response = await commitMutationPromise(environment, config);
|
||||
return getPayload(response);
|
||||
@@ -42,10 +42,10 @@ export async function commitMutationPromiseNormalized<R, V>(
|
||||
/**
|
||||
* Like `commitMutation` of the Relay API but returns a Promise.
|
||||
*/
|
||||
export function commitMutationPromise<R, V>(
|
||||
export function commitMutationPromise<T extends OperationBase>(
|
||||
environment: Environment,
|
||||
config: MutationPromiseConfig<R, V>
|
||||
): Promise<R> {
|
||||
config: MutationPromiseConfig<T>
|
||||
): Promise<T["response"][keyof T["response"]]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
commitMutation(environment, {
|
||||
...config,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import React, { ComponentType, StatelessComponent } from "react";
|
||||
|
||||
// TODO: (cvle) This currently a workaround to hide ForwardRef from
|
||||
// enzyme which does not support it well yet.
|
||||
export default function hideForwardRef(component: ComponentType) {
|
||||
const wrapped: StatelessComponent = (props: any) =>
|
||||
React.createElement(component, props);
|
||||
wrapped.displayName = component.displayName;
|
||||
return wrapped;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { _RefType } from "react-relay";
|
||||
|
||||
export type FragmentKeys<T> = {
|
||||
[P in keyof T]: T[P] extends _RefType<any> | null ? P : never
|
||||
}[keyof T];
|
||||
|
||||
export type FragmentKeysNoLocal<T> = Exclude<FragmentKeys<T>, "local">;
|
||||
@@ -1,12 +1,30 @@
|
||||
import { createFragmentContainer, GraphQLTaggedNode } from "react-relay";
|
||||
import {
|
||||
_RefType,
|
||||
createFragmentContainer,
|
||||
FragmentOrRegularProp,
|
||||
GraphQLTaggedNode,
|
||||
} from "react-relay";
|
||||
import { InferableComponentEnhancerWithProps } from "recompose";
|
||||
import { wrapDisplayName } from "recompose";
|
||||
|
||||
import hideForwardRef from "./hideForwardRef";
|
||||
import { FragmentKeysNoLocal } from "./types";
|
||||
|
||||
/**
|
||||
* withFragmentContainer is a curried version of `createFragmentContainers`
|
||||
* from Relay.
|
||||
*/
|
||||
export default <T>(
|
||||
fragmentSpec: { [P in keyof T]: GraphQLTaggedNode }
|
||||
): InferableComponentEnhancerWithProps<T, { [P in keyof T]: any }> => (
|
||||
component: React.ComponentType<any>
|
||||
) => createFragmentContainer(component, fragmentSpec) as any;
|
||||
fragmentSpec: { [P in FragmentKeysNoLocal<T>]: GraphQLTaggedNode } & {
|
||||
_?: never;
|
||||
}
|
||||
): InferableComponentEnhancerWithProps<
|
||||
{ [P in FragmentKeysNoLocal<T>]: T[P] },
|
||||
{ [P in FragmentKeysNoLocal<T>]: FragmentOrRegularProp<T[P]> }
|
||||
> => (component: React.ComponentType<any>) => {
|
||||
const result = createFragmentContainer(component, fragmentSpec);
|
||||
result.displayName = wrapDisplayName(component, "Relay");
|
||||
// TODO: (cvle) We wrap this currently to hide the ForwardRef which is not
|
||||
// well supported yet in enzyme.
|
||||
return hideForwardRef(result) as any;
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
GraphQLTaggedNode,
|
||||
} from "relay-runtime";
|
||||
|
||||
import { _RefType } from "react-relay";
|
||||
import { withContext } from "../bootstrap";
|
||||
|
||||
interface Props {
|
||||
@@ -35,9 +36,9 @@ export const LOCAL_ID = "client:root.local";
|
||||
* The `fragmentSpec` must be a `Fragment` on the `LOCAL_TYPE` which
|
||||
* must have the `LOCAL_ID`.
|
||||
*/
|
||||
function withLocalStateContainer<T>(
|
||||
function withLocalStateContainer(
|
||||
fragmentSpec: GraphQLTaggedNode
|
||||
): InferableComponentEnhancer<{ local: T }> {
|
||||
): InferableComponentEnhancer<{ local: _RefType<any> }> {
|
||||
return compose(
|
||||
withContext(({ relayEnvironment }) => ({ relayEnvironment })),
|
||||
hoistStatics((BaseComponent: React.ComponentType<any>) => {
|
||||
|
||||
@@ -1,24 +1,62 @@
|
||||
import {
|
||||
ConnectionConfig,
|
||||
ConnectionData,
|
||||
createPaginationContainer,
|
||||
FragmentOrRegularProp,
|
||||
GraphQLTaggedNode,
|
||||
RelayPaginationProp,
|
||||
} from "react-relay";
|
||||
import { InferableComponentEnhancerWithProps } from "recompose";
|
||||
import {
|
||||
InferableComponentEnhancerWithProps,
|
||||
wrapDisplayName,
|
||||
} from "recompose";
|
||||
import { Variables } from "relay-runtime";
|
||||
|
||||
import hideForwardRef from "./hideForwardRef";
|
||||
import { FragmentKeysNoLocal } from "./types";
|
||||
|
||||
// TODO: (cvle) at some point we might switch these to stock react-relay typings
|
||||
// when they become versatile enough.
|
||||
export type FragmentVariablesGetter<V extends Variables = Variables> = (
|
||||
prevVars: V,
|
||||
totalCount: number
|
||||
) => V;
|
||||
|
||||
export interface ConnectionConfig<
|
||||
P,
|
||||
V extends Variables = Variables,
|
||||
F extends Variables = Variables
|
||||
> {
|
||||
direction?: "backward" | "forward";
|
||||
getConnectionFromProps?(props: P): ConnectionData | undefined | null;
|
||||
getFragmentVariables?: FragmentVariablesGetter<F>;
|
||||
getVariables(
|
||||
props: P,
|
||||
paginationInfo: { count: number; cursor?: string },
|
||||
fragmentVariables: F
|
||||
): V;
|
||||
query: GraphQLTaggedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* withPaginationContainer is a curried version of `createPaginationContainers`
|
||||
* from Relay.
|
||||
*/
|
||||
export default <T, InnerProps, FragmentVariables, QueryVariables>(
|
||||
fragmentSpec: { [P in keyof T]: GraphQLTaggedNode },
|
||||
connectionConfig: ConnectionConfig<
|
||||
InnerProps,
|
||||
FragmentVariables,
|
||||
QueryVariables
|
||||
>
|
||||
export default <T, QueryVariables, FragmentVariables>(
|
||||
fragmentSpec: { [P in FragmentKeysNoLocal<T>]: GraphQLTaggedNode } & {
|
||||
_?: never;
|
||||
},
|
||||
connectionConfig: ConnectionConfig<T, QueryVariables, FragmentVariables>
|
||||
): InferableComponentEnhancerWithProps<
|
||||
T & { relay: RelayPaginationProp },
|
||||
{ [P in keyof T]: any }
|
||||
> => (component: React.ComponentType<any>) =>
|
||||
createPaginationContainer(component, fragmentSpec, connectionConfig) as any;
|
||||
{ [P in FragmentKeysNoLocal<T>]: T[P] } & { relay: RelayPaginationProp },
|
||||
{ [P in FragmentKeysNoLocal<T>]: FragmentOrRegularProp<T[P]> }
|
||||
> => (component: React.ComponentType<any>) => {
|
||||
const result = createPaginationContainer(
|
||||
component,
|
||||
fragmentSpec,
|
||||
connectionConfig
|
||||
);
|
||||
result.displayName = wrapDisplayName(component, "Relay");
|
||||
// TODO: (cvle) We wrap this currently to hide the ForwardRef which is not
|
||||
// well supported yet in enzyme.
|
||||
return hideForwardRef(result) as any;
|
||||
};
|
||||
|
||||
@@ -1,19 +1,33 @@
|
||||
import {
|
||||
createRefetchContainer,
|
||||
FragmentOrRegularProp,
|
||||
GraphQLTaggedNode,
|
||||
RelayRefetchProp,
|
||||
} from "react-relay";
|
||||
import { InferableComponentEnhancerWithProps } from "recompose";
|
||||
import {
|
||||
InferableComponentEnhancerWithProps,
|
||||
wrapDisplayName,
|
||||
} from "recompose";
|
||||
|
||||
import hideForwardRef from "./hideForwardRef";
|
||||
import { FragmentKeysNoLocal } from "./types";
|
||||
|
||||
/**
|
||||
* withRefetchContainer is a curried version of `createRefetchContainers`
|
||||
* from Relay.
|
||||
*/
|
||||
export default <T>(
|
||||
fragmentSpec: { [P in keyof T]: GraphQLTaggedNode },
|
||||
fragmentSpec: { [P in FragmentKeysNoLocal<T>]: GraphQLTaggedNode } & {
|
||||
_?: never;
|
||||
},
|
||||
refetchQuery: GraphQLTaggedNode
|
||||
): InferableComponentEnhancerWithProps<
|
||||
T & { relay: RelayRefetchProp },
|
||||
{ [P in keyof T]: any }
|
||||
> => (component: React.ComponentType<any>) =>
|
||||
createRefetchContainer(component, fragmentSpec, refetchQuery) as any;
|
||||
{ [P in FragmentKeysNoLocal<T>]: T[P] } & { relay: RelayRefetchProp },
|
||||
{ [P in FragmentKeysNoLocal<T>]: FragmentOrRegularProp<T[P]> }
|
||||
> => (component: React.ComponentType<any>) => {
|
||||
const result = createRefetchContainer(component, fragmentSpec, refetchQuery);
|
||||
result.displayName = wrapDisplayName(component, "Relay");
|
||||
// TODO: (cvle) We wrap this currently to hide the ForwardRef which is not
|
||||
// well supported yet in enzyme.
|
||||
return hideForwardRef(result) as any;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import sinon, { SinonStub } from "sinon";
|
||||
|
||||
/**
|
||||
* createSinonStub assist in setting up a stub with different
|
||||
* return paths.
|
||||
*
|
||||
* e.g.
|
||||
* ```
|
||||
* const s = sinon.stub();
|
||||
* s.throws();
|
||||
* s.withArgs("a").returns(0);
|
||||
* s.withArgs("b").returns(1);
|
||||
* ```
|
||||
* is equivalent to.
|
||||
* ```
|
||||
* const s = createSinonStub(
|
||||
* s => s.throws(),
|
||||
* s => s.withArgs("a").returns(0),
|
||||
* s => s.withArgs("b").returns(1),
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export default function createSinonStub(
|
||||
...callbacks: Array<(s: SinonStub) => void>
|
||||
): SinonStub {
|
||||
const stub = sinon.stub();
|
||||
callbacks.forEach(cb => cb(stub));
|
||||
return stub;
|
||||
}
|
||||
@@ -2,5 +2,9 @@ export {
|
||||
default as createRelayEnvironment,
|
||||
CreateRelayEnvironmentParams,
|
||||
} from "./createRelayEnvironment";
|
||||
|
||||
export { default as createFluentBundle } from "./createFluentBundle";
|
||||
export { default as createSinonStub } from "./createSinonStub";
|
||||
export {
|
||||
default as removeFragmentRefs,
|
||||
NoFragmentRefs,
|
||||
} from "./removeFragmentRefs";
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { ComponentType } from "react";
|
||||
|
||||
/** Remove all traces of `$fragmentRefs` and `$refType` from type recursively */
|
||||
export type NoFragmentRefs<T> = T extends object
|
||||
? {
|
||||
[P in Exclude<keyof T, " $fragmentRefs" | " $refType">]: NoFragmentRefs<
|
||||
T[P]
|
||||
>
|
||||
}
|
||||
: T;
|
||||
|
||||
export default function removeFragmentRefs<T>(
|
||||
component: ComponentType<T>
|
||||
): ComponentType<NoFragmentRefs<T>> {
|
||||
return component as any;
|
||||
}
|
||||
@@ -2,9 +2,9 @@ import * as React from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
|
||||
import { Flex } from "talk-ui/components";
|
||||
|
||||
import PermalinkViewQuery from "../queries/PermalinkViewQuery";
|
||||
import StreamQuery from "../queries/StreamQuery";
|
||||
|
||||
import * as styles from "./App.css";
|
||||
|
||||
export interface AppProps {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React from "react";
|
||||
|
||||
import { oncePerFrame } from "talk-common/utils";
|
||||
import {
|
||||
Button,
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { MouseEvent, StatelessComponent } from "react";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
import { Button, Typography } from "talk-ui/components";
|
||||
|
||||
import CommentContainer from "../containers/CommentContainer";
|
||||
import * as styles from "./PermalinkView.css";
|
||||
|
||||
export interface PermalinkViewProps {
|
||||
comment: {} | null;
|
||||
comment: PropTypesOf<typeof CommentContainer>["data"] | null;
|
||||
showAllCommentsHref: string | null;
|
||||
onShowAllComments: (e: MouseEvent<any>) => void;
|
||||
}
|
||||
|
||||
@@ -27,13 +27,21 @@ export interface PostCommentFormProps {
|
||||
const PostCommentForm: StatelessComponent<PostCommentFormProps> = props => (
|
||||
<Form onSubmit={props.onSubmit}>
|
||||
{({ handleSubmit, submitting }) => (
|
||||
<form autoComplete="off" onSubmit={handleSubmit} className={styles.root}>
|
||||
<form
|
||||
autoComplete="off"
|
||||
onSubmit={handleSubmit}
|
||||
className={styles.root}
|
||||
id="comments-postCommentForm-form"
|
||||
>
|
||||
<HorizontalGutter>
|
||||
<Field name="body" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<div>
|
||||
<Localized id="comments-postCommentForm-rteLabel">
|
||||
<AriaInfo component="label" htmlFor="postCommentField">
|
||||
<AriaInfo
|
||||
component="label"
|
||||
htmlFor="comments-postCommentForm-field"
|
||||
>
|
||||
Post a comment
|
||||
</AriaInfo>
|
||||
</Localized>
|
||||
@@ -42,7 +50,7 @@ const PostCommentForm: StatelessComponent<PostCommentFormProps> = props => (
|
||||
attrs={{ placeholder: true }}
|
||||
>
|
||||
<RTE
|
||||
inputId="postCommentField"
|
||||
inputId="comments-postCommentForm-field"
|
||||
onChange={({ html }) => input.onChange(html)}
|
||||
value={input.value}
|
||||
placeholder="Post a comment"
|
||||
|
||||
@@ -3,24 +3,27 @@ import { noop } from "lodash";
|
||||
import React from "react";
|
||||
import sinon, { SinonSpy } from "sinon";
|
||||
|
||||
import { removeFragmentRefs } from "talk-framework/testHelpers";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import ReplyList from "./ReplyList";
|
||||
|
||||
const ReplyListN = removeFragmentRefs(ReplyList);
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof ReplyList> = {
|
||||
const props: PropTypesOf<typeof ReplyListN> = {
|
||||
commentID: "comment-id",
|
||||
comments: [{ id: "comment-1" }, { id: "comment-2" }],
|
||||
onShowAll: noop,
|
||||
hasMore: false,
|
||||
disableShowAll: false,
|
||||
};
|
||||
const wrapper = shallow(<ReplyList {...props} />);
|
||||
const wrapper = shallow(<ReplyListN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when there is more", () => {
|
||||
const props: PropTypesOf<typeof ReplyList> = {
|
||||
const props: PropTypesOf<typeof ReplyListN> = {
|
||||
commentID: "comment-id",
|
||||
comments: [{ id: "comment-1" }, { id: "comment-2" }],
|
||||
onShowAll: sinon.spy(),
|
||||
@@ -28,7 +31,7 @@ describe("when there is more", () => {
|
||||
disableShowAll: false,
|
||||
};
|
||||
|
||||
const wrapper = shallow(<ReplyList {...props} />);
|
||||
const wrapper = shallow(<ReplyListN {...props} />);
|
||||
it("renders a load more button", () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
@@ -41,7 +44,7 @@ describe("when there is more", () => {
|
||||
});
|
||||
|
||||
const wrapperDisabledButton = shallow(
|
||||
<ReplyList {...props} disableShowAll />
|
||||
<ReplyListN {...props} disableShowAll />
|
||||
);
|
||||
it("disables load more button", () => {
|
||||
expect(wrapperDisabledButton).toMatchSnapshot();
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Localized } from "fluent-react/compat";
|
||||
import * as React from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
import { Button, HorizontalGutter } from "talk-ui/components";
|
||||
|
||||
import CommentContainer from "../containers/CommentContainer";
|
||||
@@ -9,7 +10,9 @@ import Indent from "./Indent";
|
||||
|
||||
export interface ReplyListProps {
|
||||
commentID: string;
|
||||
comments: ReadonlyArray<{ id: string }>;
|
||||
comments: ReadonlyArray<
|
||||
{ id: string } & PropTypesOf<typeof CommentContainer>["data"]
|
||||
>;
|
||||
onShowAll: () => void;
|
||||
hasMore: boolean;
|
||||
disableShowAll: boolean;
|
||||
|
||||
@@ -3,12 +3,15 @@ import { noop } from "lodash";
|
||||
import React from "react";
|
||||
import sinon, { SinonSpy } from "sinon";
|
||||
|
||||
import { removeFragmentRefs } from "talk-framework/testHelpers";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import Stream from "./Stream";
|
||||
|
||||
const StreamN = removeFragmentRefs(Stream);
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof Stream> = {
|
||||
const props: PropTypesOf<typeof StreamN> = {
|
||||
assetID: "asset-id",
|
||||
isClosed: false,
|
||||
comments: [{ id: "comment-1" }, { id: "comment-2" }],
|
||||
@@ -17,13 +20,13 @@ it("renders correctly", () => {
|
||||
hasMore: false,
|
||||
user: null,
|
||||
};
|
||||
const wrapper = shallow(<Stream {...props} />);
|
||||
const wrapper = shallow(<StreamN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when use is logged in", () => {
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof Stream> = {
|
||||
const props: PropTypesOf<typeof StreamN> = {
|
||||
assetID: "asset-id",
|
||||
isClosed: false,
|
||||
comments: [{ id: "comment-1" }, { id: "comment-2" }],
|
||||
@@ -32,13 +35,13 @@ describe("when use is logged in", () => {
|
||||
hasMore: false,
|
||||
user: {},
|
||||
};
|
||||
const wrapper = shallow(<Stream {...props} />);
|
||||
const wrapper = shallow(<StreamN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there is more", () => {
|
||||
const props: PropTypesOf<typeof Stream> = {
|
||||
const props: PropTypesOf<typeof StreamN> = {
|
||||
assetID: "asset-id",
|
||||
isClosed: false,
|
||||
comments: [{ id: "comment-1" }, { id: "comment-2" }],
|
||||
@@ -48,7 +51,7 @@ describe("when there is more", () => {
|
||||
user: null,
|
||||
};
|
||||
|
||||
const wrapper = shallow(<Stream {...props} />);
|
||||
const wrapper = shallow(<StreamN {...props} />);
|
||||
it("renders a load more button", () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
@@ -58,7 +61,7 @@ describe("when there is more", () => {
|
||||
expect((props.onLoadMore as SinonSpy).calledOnce).toBe(true);
|
||||
});
|
||||
|
||||
const wrapperDisabledButton = shallow(<Stream {...props} disableLoadMore />);
|
||||
const wrapperDisabledButton = shallow(<StreamN {...props} disableLoadMore />);
|
||||
it("disables load more button", () => {
|
||||
expect(wrapperDisabledButton).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Localized } from "fluent-react/compat";
|
||||
import * as React from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
import { Button, HorizontalGutter } from "talk-ui/components";
|
||||
|
||||
import CommentContainer from "../containers/CommentContainer";
|
||||
@@ -14,11 +15,14 @@ import * as styles from "./Stream.css";
|
||||
export interface StreamProps {
|
||||
assetID: string;
|
||||
isClosed?: boolean;
|
||||
comments: ReadonlyArray<{ id: string }>;
|
||||
comments: ReadonlyArray<
|
||||
{ id: string } & PropTypesOf<typeof CommentContainer>["data"] &
|
||||
PropTypesOf<typeof ReplyListContainer>["comment"]
|
||||
>;
|
||||
onLoadMore?: () => void;
|
||||
hasMore?: boolean;
|
||||
disableLoadMore?: boolean;
|
||||
user: {} | null;
|
||||
user: PropTypesOf<typeof UserBoxContainer>["user"] | null;
|
||||
}
|
||||
|
||||
const Stream: StatelessComponent<StreamProps> = props => {
|
||||
|
||||
@@ -16,7 +16,7 @@ const AppContainer: StatelessComponent<InnerProps> = ({
|
||||
return <App showPermalinkView={!!commentID} />;
|
||||
};
|
||||
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
const enhanced = withLocalStateContainer(
|
||||
graphql`
|
||||
fragment AppContainerLocal on Local {
|
||||
commentID
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
import { removeFragmentRefs } from "talk-framework/testHelpers";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import { CommentContainer } from "./CommentContainer";
|
||||
|
||||
// Remove relay refs so we can stub the props.
|
||||
const CommentContainerN = removeFragmentRefs(CommentContainer);
|
||||
|
||||
it("renders username and body", () => {
|
||||
const props: PropTypesOf<typeof CommentContainer> = {
|
||||
const props: PropTypesOf<typeof CommentContainerN> = {
|
||||
data: {
|
||||
id: "comment-id",
|
||||
author: {
|
||||
@@ -17,12 +21,12 @@ it("renders username and body", () => {
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = shallow(<CommentContainer {...props} />);
|
||||
const wrapper = shallow(<CommentContainerN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders body only", () => {
|
||||
const props: PropTypesOf<typeof CommentContainer> = {
|
||||
const props: PropTypesOf<typeof CommentContainerN> = {
|
||||
data: {
|
||||
id: "comment-id",
|
||||
author: {
|
||||
@@ -33,6 +37,6 @@ it("renders body only", () => {
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = shallow(<CommentContainer {...props} />);
|
||||
const wrapper = shallow(<CommentContainerN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ export const CommentContainer: StatelessComponent<InnerProps> = props => {
|
||||
return <Comment {...rest} {...props.data} />;
|
||||
};
|
||||
|
||||
const enhanced = withFragmentContainer<{ data: Data }>({
|
||||
const enhanced = withFragmentContainer<InnerProps>({
|
||||
data: graphql`
|
||||
fragment CommentContainer on Comment {
|
||||
...CommentContainer_comment @relay(mask: false)
|
||||
|
||||
@@ -19,7 +19,7 @@ export const PermalinkContainer: StatelessComponent<InnerProps> = ({
|
||||
) : null;
|
||||
};
|
||||
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
const enhanced = withLocalStateContainer(
|
||||
graphql`
|
||||
fragment PermalinkButtonContainerLocal on Local {
|
||||
assetURL
|
||||
|
||||
@@ -52,9 +52,7 @@ const enhanced = withContext(ctx => ({
|
||||
pym: ctx.pym,
|
||||
}))(
|
||||
withSetCommentIDMutation(
|
||||
withFragmentContainer<{
|
||||
comment: CommentData | null;
|
||||
}>({
|
||||
withFragmentContainer<PermalinkViewContainerProps>({
|
||||
comment: graphql`
|
||||
fragment PermalinkViewContainer_comment on Comment {
|
||||
...CommentContainer
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { Component } from "react";
|
||||
import React, { Component, ReactNode } from "react";
|
||||
|
||||
import { BadUserInputError } from "talk-framework/lib/errors";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
@@ -11,6 +11,7 @@ import { CreateCommentMutation, withCreateCommentMutation } from "../mutations";
|
||||
interface InnerProps {
|
||||
createComment: CreateCommentMutation;
|
||||
assetID: string;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
class PostCommentFormContainer extends Component<InnerProps> {
|
||||
|
||||
@@ -2,13 +2,17 @@ import { shallow, ShallowWrapper } from "enzyme";
|
||||
import { noop } from "lodash";
|
||||
import React from "react";
|
||||
|
||||
import { removeFragmentRefs } from "talk-framework/testHelpers";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import ReplyList from "../components/ReplyList";
|
||||
import { ReplyListContainer } from "./ReplyListContainer";
|
||||
|
||||
// Remove relay refs so we can stub the props.
|
||||
const ReplyListContainerN = removeFragmentRefs(ReplyListContainer);
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof ReplyListContainer> = {
|
||||
const props: PropTypesOf<typeof ReplyListContainerN> = {
|
||||
comment: {
|
||||
id: "comment-id",
|
||||
replies: {
|
||||
@@ -20,12 +24,12 @@ it("renders correctly", () => {
|
||||
isLoading: noop,
|
||||
} as any,
|
||||
};
|
||||
const wrapper = shallow(<ReplyListContainer {...props} />);
|
||||
const wrapper = shallow(<ReplyListContainerN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders correctly when replies are null", () => {
|
||||
const props: PropTypesOf<typeof ReplyListContainer> = {
|
||||
const props: PropTypesOf<typeof ReplyListContainerN> = {
|
||||
comment: {
|
||||
id: "comment-id",
|
||||
replies: null,
|
||||
@@ -35,13 +39,13 @@ it("renders correctly when replies are null", () => {
|
||||
isLoading: noop,
|
||||
} as any,
|
||||
};
|
||||
const wrapper = shallow(<ReplyListContainer {...props} />);
|
||||
const wrapper = shallow(<ReplyListContainerN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when has more replies", () => {
|
||||
let finishLoading: ((error?: Error) => void) | null = null;
|
||||
const props: PropTypesOf<ReplyListContainer> = {
|
||||
const props: PropTypesOf<typeof ReplyListContainerN> = {
|
||||
comment: {
|
||||
id: "comment-id",
|
||||
replies: {
|
||||
@@ -57,7 +61,7 @@ describe("when has more replies", () => {
|
||||
|
||||
let wrapper: ShallowWrapper;
|
||||
|
||||
beforeAll(() => (wrapper = shallow(<ReplyListContainer {...props} />)));
|
||||
beforeAll(() => (wrapper = shallow(<ReplyListContainerN {...props} />)));
|
||||
|
||||
it("renders hasMore", () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
@@ -23,7 +23,7 @@ export class ReplyListContainer extends React.Component<InnerProps> {
|
||||
|
||||
public render() {
|
||||
if (
|
||||
this.props.comment.replies === null ||
|
||||
this.props.comment.replies == null ||
|
||||
this.props.comment.replies.edges.length === 0
|
||||
) {
|
||||
return null;
|
||||
@@ -67,10 +67,9 @@ interface FragmentVariables {
|
||||
}
|
||||
|
||||
const enhanced = withPaginationContainer<
|
||||
{ comment: Data },
|
||||
InnerProps,
|
||||
FragmentVariables,
|
||||
ReplyListContainerPaginationQueryVariables
|
||||
ReplyListContainerPaginationQueryVariables,
|
||||
FragmentVariables
|
||||
>(
|
||||
{
|
||||
comment: graphql`
|
||||
|
||||
@@ -2,13 +2,17 @@ import { shallow, ShallowWrapper } from "enzyme";
|
||||
import { noop } from "lodash";
|
||||
import React from "react";
|
||||
|
||||
import { removeFragmentRefs } from "talk-framework/testHelpers";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import Stream from "../components/Stream";
|
||||
import { StreamContainer } from "./StreamContainer";
|
||||
|
||||
// Remove relay refs so we can stub the props.
|
||||
const StreamContainerN = removeFragmentRefs(StreamContainer);
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<StreamContainer> = {
|
||||
const props: PropTypesOf<typeof StreamContainerN> = {
|
||||
asset: {
|
||||
id: "asset-id",
|
||||
isClosed: false,
|
||||
@@ -16,18 +20,19 @@ it("renders correctly", () => {
|
||||
edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }],
|
||||
},
|
||||
},
|
||||
user: null,
|
||||
relay: {
|
||||
hasMore: noop,
|
||||
isLoading: noop,
|
||||
} as any,
|
||||
};
|
||||
const wrapper = shallow(<StreamContainer {...props} />);
|
||||
const wrapper = shallow(<StreamContainerN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe("when has more comments", () => {
|
||||
let finishLoading: ((error?: Error) => void) | null = null;
|
||||
const props: PropTypesOf<StreamContainer> = {
|
||||
const props: PropTypesOf<typeof StreamContainerN> = {
|
||||
asset: {
|
||||
id: "asset-id",
|
||||
isClosed: false,
|
||||
@@ -35,6 +40,7 @@ describe("when has more comments", () => {
|
||||
edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }],
|
||||
},
|
||||
},
|
||||
user: null,
|
||||
relay: {
|
||||
hasMore: () => true,
|
||||
isLoading: () => false,
|
||||
@@ -44,7 +50,7 @@ describe("when has more comments", () => {
|
||||
|
||||
let wrapper: ShallowWrapper;
|
||||
|
||||
beforeAll(() => (wrapper = shallow(<StreamContainer {...props} />)));
|
||||
beforeAll(() => (wrapper = shallow(<StreamContainerN {...props} />)));
|
||||
|
||||
it("renders hasMore", () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
@@ -64,10 +64,9 @@ interface FragmentVariables {
|
||||
}
|
||||
|
||||
const enhanced = withPaginationContainer<
|
||||
{ asset: AssetData; user: UserData | null },
|
||||
InnerProps,
|
||||
FragmentVariables,
|
||||
StreamContainerPaginationQueryVariables
|
||||
StreamContainerPaginationQueryVariables,
|
||||
FragmentVariables
|
||||
>(
|
||||
{
|
||||
asset: graphql`
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
import { removeFragmentRefs } from "talk-framework/testHelpers";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import { UserBoxContainer } from "./UserBoxContainer";
|
||||
|
||||
// Remove relay refs so we can stub the props.
|
||||
const UserBoxContainerN = removeFragmentRefs(UserBoxContainer);
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<UserBoxContainer> = {
|
||||
const props: PropTypesOf<typeof UserBoxContainerN> = {
|
||||
local: {
|
||||
authPopup: {
|
||||
open: false,
|
||||
@@ -22,6 +26,6 @@ it("renders correctly", () => {
|
||||
// tslint:disable-next-line:no-empty
|
||||
signOut: async () => {},
|
||||
};
|
||||
const wrapper = shallow(<UserBoxContainer {...props} />);
|
||||
const wrapper = shallow(<UserBoxContainerN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -78,7 +78,7 @@ export class UserBoxContainer extends Component<InnerProps> {
|
||||
const enhanced = withSignOutMutation(
|
||||
withSetAuthPopupStateMutation(
|
||||
withShowAuthPopupMutation(
|
||||
withLocalStateContainer<Local>(
|
||||
withLocalStateContainer(
|
||||
graphql`
|
||||
fragment UserBoxContainerLocal on Local {
|
||||
authPopup {
|
||||
@@ -89,7 +89,7 @@ const enhanced = withSignOutMutation(
|
||||
}
|
||||
`
|
||||
)(
|
||||
withFragmentContainer<{ user: UserData | null }>({
|
||||
withFragmentContainer<InnerProps>({
|
||||
user: graphql`
|
||||
fragment UserBoxContainer_user on User {
|
||||
username
|
||||
|
||||
@@ -16,6 +16,7 @@ exports[`renders correctly 1`] = `
|
||||
disableLoadMore={false}
|
||||
isClosed={false}
|
||||
onLoadMore={[Function]}
|
||||
user={null}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -36,6 +37,7 @@ exports[`when has more comments renders hasMore 1`] = `
|
||||
hasMore={true}
|
||||
isClosed={false}
|
||||
onLoadMore={[Function]}
|
||||
user={null}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -56,6 +58,7 @@ exports[`when has more comments when loading more disables load more button 1`]
|
||||
hasMore={true}
|
||||
isClosed={false}
|
||||
onLoadMore={[Function]}
|
||||
user={null}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -76,5 +79,6 @@ exports[`when has more comments when loading more enable load more button after
|
||||
hasMore={true}
|
||||
isClosed={false}
|
||||
onLoadMore={[Function]}
|
||||
user={null}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
import { graphql } from "react-relay";
|
||||
import { Environment } from "relay-runtime";
|
||||
import uuid from "uuid/v4";
|
||||
|
||||
import { getMe } from "talk-framework/helpers";
|
||||
import {
|
||||
commitMutationPromiseNormalized,
|
||||
createMutationContainer,
|
||||
} from "talk-framework/lib/relay";
|
||||
import { Omit } from "talk-framework/types";
|
||||
import {
|
||||
CreateCommentMutationResponse,
|
||||
CreateCommentMutationVariables,
|
||||
} from "talk-stream/__generated__/CreateCommentMutation.graphql";
|
||||
|
||||
import { CreateCommentMutation as MutationTypes } from "talk-stream/__generated__/CreateCommentMutation.graphql";
|
||||
|
||||
export type CreateCommentInput = Omit<
|
||||
CreateCommentMutationVariables["input"],
|
||||
MutationTypes["variables"]["input"],
|
||||
"clientMutationId"
|
||||
>;
|
||||
|
||||
const mutation = graphql`
|
||||
mutation CreateCommentMutation($input: CreateCommentInput!) {
|
||||
createComment(input: $input) {
|
||||
comment {
|
||||
id
|
||||
author {
|
||||
username
|
||||
commentEdge {
|
||||
cursor
|
||||
node {
|
||||
id
|
||||
author {
|
||||
id
|
||||
username
|
||||
}
|
||||
body
|
||||
createdAt
|
||||
}
|
||||
body
|
||||
}
|
||||
clientMutationId
|
||||
}
|
||||
@@ -34,30 +39,47 @@ const mutation = graphql`
|
||||
let clientMutationId = 0;
|
||||
|
||||
function commit(environment: Environment, input: CreateCommentInput) {
|
||||
return commitMutationPromiseNormalized<
|
||||
CreateCommentMutationResponse["createComment"],
|
||||
CreateCommentMutationVariables
|
||||
>(environment, {
|
||||
const me = getMe(environment)!;
|
||||
const currentDate = new Date().toISOString();
|
||||
return commitMutationPromiseNormalized<MutationTypes>(environment, {
|
||||
mutation,
|
||||
variables: {
|
||||
input: {
|
||||
...input,
|
||||
clientMutationId: clientMutationId.toString(),
|
||||
},
|
||||
},
|
||||
optimisticResponse: {
|
||||
createComment: {
|
||||
commentEdge: {
|
||||
cursor: currentDate,
|
||||
node: {
|
||||
id: uuid(),
|
||||
createdAt: currentDate,
|
||||
author: {
|
||||
id: me.id,
|
||||
username: me.username,
|
||||
},
|
||||
body: input.body,
|
||||
},
|
||||
},
|
||||
clientMutationId: (clientMutationId++).toString(),
|
||||
},
|
||||
},
|
||||
updater: store => {
|
||||
const payload = store.getRootField("createComment");
|
||||
if (payload) {
|
||||
const newRecord = payload.getLinkedRecord("comment")!;
|
||||
const root = store.getRoot();
|
||||
const records = root.getLinkedRecords("comments");
|
||||
if (!records) {
|
||||
throw new Error("Unexpected cache state");
|
||||
}
|
||||
|
||||
root.setLinkedRecords([...records, newRecord], "comments");
|
||||
}
|
||||
},
|
||||
configs: [
|
||||
{
|
||||
type: "RANGE_ADD",
|
||||
connectionInfo: [
|
||||
{
|
||||
key: "Stream_comments",
|
||||
rangeBehavior: "prepend",
|
||||
filters: { orderBy: "CREATED_AT_DESC" },
|
||||
},
|
||||
],
|
||||
parentID: input.assetID,
|
||||
edgeName: "commentEdge",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,4 +90,4 @@ export const withCreateCommentMutation = createMutationContainer(
|
||||
|
||||
export type CreateCommentMutation = (
|
||||
input: CreateCommentInput
|
||||
) => Promise<CreateCommentMutationResponse["createComment"]>;
|
||||
) => Promise<MutationTypes["response"]["createComment"]>;
|
||||
|
||||
@@ -7,10 +7,7 @@ import {
|
||||
QueryRenderer,
|
||||
withLocalStateContainer,
|
||||
} from "talk-framework/lib/relay";
|
||||
import {
|
||||
PermalinkViewQueryResponse,
|
||||
PermalinkViewQueryVariables,
|
||||
} from "talk-stream/__generated__/PermalinkViewQuery.graphql";
|
||||
import { PermalinkViewQuery as QueryTypes } from "talk-stream/__generated__/PermalinkViewQuery.graphql";
|
||||
import { PermalinkViewQueryLocal as Local } from "talk-stream/__generated__/PermalinkViewQueryLocal.graphql";
|
||||
|
||||
import { Spinner } from "talk-ui/components";
|
||||
@@ -23,7 +20,7 @@ interface InnerProps {
|
||||
export const render = ({
|
||||
error,
|
||||
props,
|
||||
}: ReadyState<PermalinkViewQueryResponse>) => {
|
||||
}: ReadyState<QueryTypes["response"]>) => {
|
||||
if (error) {
|
||||
return <div>{error.message}</div>;
|
||||
}
|
||||
@@ -36,7 +33,7 @@ export const render = ({
|
||||
const PermalinkViewQuery: StatelessComponent<InnerProps> = ({
|
||||
local: { commentID },
|
||||
}) => (
|
||||
<QueryRenderer<PermalinkViewQueryVariables, PermalinkViewQueryResponse>
|
||||
<QueryRenderer<QueryTypes>
|
||||
query={graphql`
|
||||
query PermalinkViewQuery($commentID: ID!) {
|
||||
comment(id: $commentID) {
|
||||
@@ -45,13 +42,13 @@ const PermalinkViewQuery: StatelessComponent<InnerProps> = ({
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
commentID,
|
||||
commentID: commentID!,
|
||||
}}
|
||||
render={render}
|
||||
/>
|
||||
);
|
||||
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
const enhanced = withLocalStateContainer(
|
||||
graphql`
|
||||
fragment PermalinkViewQueryLocal on Local {
|
||||
commentID
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Localized } from "fluent-react/compat";
|
||||
import React, { StatelessComponent } from "react";
|
||||
import { ReadyState } from "react-relay";
|
||||
import {
|
||||
@@ -5,10 +6,7 @@ import {
|
||||
QueryRenderer,
|
||||
withLocalStateContainer,
|
||||
} from "talk-framework/lib/relay";
|
||||
import {
|
||||
StreamQueryResponse,
|
||||
StreamQueryVariables,
|
||||
} from "talk-stream/__generated__/StreamQuery.graphql";
|
||||
import { StreamQuery as QueryTypes } from "talk-stream/__generated__/StreamQuery.graphql";
|
||||
import { StreamQueryLocal as Local } from "talk-stream/__generated__/StreamQueryLocal.graphql";
|
||||
import { Spinner } from "talk-ui/components";
|
||||
import StreamContainer from "../containers/StreamContainer";
|
||||
@@ -17,12 +15,22 @@ interface InnerProps {
|
||||
local: Local;
|
||||
}
|
||||
|
||||
export const render = ({ error, props }: ReadyState<StreamQueryResponse>) => {
|
||||
export const render = ({
|
||||
error,
|
||||
props,
|
||||
}: ReadyState<QueryTypes["response"]>) => {
|
||||
if (error) {
|
||||
return <div>{error.message}</div>;
|
||||
}
|
||||
|
||||
if (props) {
|
||||
if (!props.asset) {
|
||||
return (
|
||||
<Localized id="comments-streamQuery-assetNotFound">
|
||||
<div>Asset not found</div>
|
||||
</Localized>
|
||||
);
|
||||
}
|
||||
return <StreamContainer asset={props.asset} user={props.me} />;
|
||||
}
|
||||
|
||||
@@ -32,7 +40,7 @@ export const render = ({ error, props }: ReadyState<StreamQueryResponse>) => {
|
||||
const StreamQuery: StatelessComponent<InnerProps> = ({
|
||||
local: { assetID, authRevision },
|
||||
}) => (
|
||||
<QueryRenderer<StreamQueryVariables, StreamQueryResponse>
|
||||
<QueryRenderer<QueryTypes>
|
||||
query={graphql`
|
||||
query StreamQuery($assetID: ID!, $authRevision: Int!) {
|
||||
asset(id: $assetID) {
|
||||
@@ -47,14 +55,14 @@ const StreamQuery: StatelessComponent<InnerProps> = ({
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
assetID,
|
||||
assetID: assetID!,
|
||||
authRevision,
|
||||
}}
|
||||
render={render}
|
||||
/>
|
||||
);
|
||||
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
const enhanced = withLocalStateContainer(
|
||||
graphql`
|
||||
fragment StreamQueryLocal on Local {
|
||||
assetID
|
||||
|
||||
@@ -0,0 +1,847 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`post a comment 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-flex Flex-justifyCenter"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-half"
|
||||
>
|
||||
<div
|
||||
className="Flex-root"
|
||||
>
|
||||
<div
|
||||
className="Flex-flex Flex-halfItemGutter Flex-wrap"
|
||||
>
|
||||
<div
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Signed in as
|
||||
<span
|
||||
className="Typography-root Typography-bodyCopyBold Typography-colorTextPrimary"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
.
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Typography-root Typography-bodyCopy Typography-colorTextPrimary Flex-flex"
|
||||
>
|
||||
<span>
|
||||
Not you?
|
||||
</span>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
autoComplete="off"
|
||||
className="PostCommentForm-root"
|
||||
id="comments-postCommentForm-form"
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div>
|
||||
<label
|
||||
className="AriaInfo-root"
|
||||
htmlFor="comments-postCommentForm-field"
|
||||
>
|
||||
Post a comment
|
||||
</label>
|
||||
<div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Toolbar-toolbar"
|
||||
>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Bold"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_bold
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Italic"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_italic
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Blockquote"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_quote
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
aria-placeholder="Post a comment"
|
||||
className="RTE-contentEditable RTE-content"
|
||||
contentEditable={true}
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<strong>Hello world!</strong>",
|
||||
}
|
||||
}
|
||||
id="comments-postCommentForm-field"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onCut={[Function]}
|
||||
onFocus={[Function]}
|
||||
onInput={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onPaste={[Function]}
|
||||
onSelect={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-justifySpaceBetween Flex-alignFlexStart Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="PostCommentForm-poweredBy"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
|
||||
>
|
||||
Powered by
|
||||
<span
|
||||
className="Typography-root Typography-heading4 Typography-colorTextPrimary"
|
||||
>
|
||||
The Coral Project
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-disabled"
|
||||
disabled={true}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
aria-live="polite"
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.002Z"
|
||||
title="2018-07-06T18:24:00.002Z"
|
||||
>
|
||||
2018-07-06T18:24:00.002Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<strong>Hello world!</strong>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`post a comment 2`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-flex Flex-justifyCenter"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-half"
|
||||
>
|
||||
<div
|
||||
className="Flex-root"
|
||||
>
|
||||
<div
|
||||
className="Flex-flex Flex-halfItemGutter Flex-wrap"
|
||||
>
|
||||
<div
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Signed in as
|
||||
<span
|
||||
className="Typography-root Typography-bodyCopyBold Typography-colorTextPrimary"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
.
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Typography-root Typography-bodyCopy Typography-colorTextPrimary Flex-flex"
|
||||
>
|
||||
<span>
|
||||
Not you?
|
||||
</span>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
autoComplete="off"
|
||||
className="PostCommentForm-root"
|
||||
id="comments-postCommentForm-form"
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div>
|
||||
<label
|
||||
className="AriaInfo-root"
|
||||
htmlFor="comments-postCommentForm-field"
|
||||
>
|
||||
Post a comment
|
||||
</label>
|
||||
<div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Toolbar-toolbar"
|
||||
>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Bold"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_bold
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Italic"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_italic
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Blockquote"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_quote
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="RTE-placeholder RTE-placeholder"
|
||||
>
|
||||
Post a comment
|
||||
</div>
|
||||
<div
|
||||
aria-placeholder="Post a comment"
|
||||
className="RTE-contentEditable RTE-content"
|
||||
contentEditable={true}
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "",
|
||||
}
|
||||
}
|
||||
id="comments-postCommentForm-field"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onCut={[Function]}
|
||||
onFocus={[Function]}
|
||||
onInput={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onPaste={[Function]}
|
||||
onSelect={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-justifySpaceBetween Flex-alignFlexStart Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="PostCommentForm-poweredBy"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
|
||||
>
|
||||
Powered by
|
||||
<span
|
||||
className="Typography-root Typography-heading4 Typography-colorTextPrimary"
|
||||
>
|
||||
The Coral Project
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
aria-live="polite"
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<strong>Hello world! (from server)</strong>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders comment stream 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-flex Flex-justifyCenter"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-half"
|
||||
>
|
||||
<div
|
||||
className="Flex-root"
|
||||
>
|
||||
<div
|
||||
className="Flex-flex Flex-halfItemGutter Flex-wrap"
|
||||
>
|
||||
<div
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Signed in as
|
||||
<span
|
||||
className="Typography-root Typography-bodyCopyBold Typography-colorTextPrimary"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
.
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Typography-root Typography-bodyCopy Typography-colorTextPrimary Flex-flex"
|
||||
>
|
||||
<span>
|
||||
Not you?
|
||||
</span>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
autoComplete="off"
|
||||
className="PostCommentForm-root"
|
||||
id="comments-postCommentForm-form"
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div>
|
||||
<label
|
||||
className="AriaInfo-root"
|
||||
htmlFor="comments-postCommentForm-field"
|
||||
>
|
||||
Post a comment
|
||||
</label>
|
||||
<div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Toolbar-toolbar"
|
||||
>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Bold"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_bold
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Italic"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_italic
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Blockquote"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_quote
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="RTE-placeholder RTE-placeholder"
|
||||
>
|
||||
Post a comment
|
||||
</div>
|
||||
<div
|
||||
aria-placeholder="Post a comment"
|
||||
className="RTE-contentEditable RTE-content"
|
||||
contentEditable={true}
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "",
|
||||
}
|
||||
}
|
||||
id="comments-postCommentForm-field"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onCut={[Function]}
|
||||
onFocus={[Function]}
|
||||
onInput={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onPaste={[Function]}
|
||||
onSelect={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-justifySpaceBetween Flex-alignFlexStart Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="PostCommentForm-poweredBy"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
|
||||
>
|
||||
Powered by
|
||||
<span
|
||||
className="Typography-root Typography-heading4 Typography-colorTextPrimary"
|
||||
>
|
||||
The Coral Project
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
aria-live="polite"
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,12 +1,12 @@
|
||||
import React from "react";
|
||||
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
|
||||
import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import { PostMessageService } from "talk-framework/lib/postMessage";
|
||||
import { RestClient } from "talk-framework/lib/rest";
|
||||
import { createInMemoryStorage } from "talk-framework/lib/storage";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
@@ -16,54 +16,55 @@ import { assets, comments } from "./fixtures";
|
||||
|
||||
let testRenderer: ReactTestRenderer;
|
||||
beforeEach(() => {
|
||||
const connectionStub = sinon.stub().throws();
|
||||
connectionStub.withArgs({ first: 5, orderBy: "CREATED_AT_DESC" }).returns({
|
||||
edges: [
|
||||
{
|
||||
node: comments[0],
|
||||
cursor: comments[0].createdAt,
|
||||
},
|
||||
{
|
||||
node: comments[1],
|
||||
cursor: comments[1].createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: comments[1].createdAt,
|
||||
hasNextPage: true,
|
||||
},
|
||||
});
|
||||
connectionStub
|
||||
.withArgs({
|
||||
first: 10,
|
||||
orderBy: "CREATED_AT_DESC",
|
||||
after: comments[1].createdAt,
|
||||
})
|
||||
.returns({
|
||||
edges: [
|
||||
{
|
||||
node: comments[2],
|
||||
cursor: comments[2].createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: comments[2].createdAt,
|
||||
hasNextPage: false,
|
||||
},
|
||||
});
|
||||
|
||||
const assetStub = {
|
||||
...assets[0],
|
||||
comments: connectionStub,
|
||||
comments: createSinonStub(
|
||||
s => s.throws(),
|
||||
s =>
|
||||
s.withArgs({ first: 5, orderBy: "CREATED_AT_DESC" }).returns({
|
||||
edges: [
|
||||
{
|
||||
node: comments[0],
|
||||
cursor: comments[0].createdAt,
|
||||
},
|
||||
{
|
||||
node: comments[1],
|
||||
cursor: comments[1].createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: comments[1].createdAt,
|
||||
hasNextPage: true,
|
||||
},
|
||||
}),
|
||||
s =>
|
||||
s
|
||||
.withArgs({
|
||||
first: 10,
|
||||
orderBy: "CREATED_AT_DESC",
|
||||
after: comments[1].createdAt,
|
||||
})
|
||||
.returns({
|
||||
edges: [
|
||||
{
|
||||
node: comments[2],
|
||||
cursor: comments[2].createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: comments[2].createdAt,
|
||||
hasNextPage: false,
|
||||
},
|
||||
})
|
||||
),
|
||||
};
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
asset: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: assetStub.id })
|
||||
.returns(assetStub),
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assetStub.id }).returns(assetStub)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import { PostMessageService } from "talk-framework/lib/postMessage";
|
||||
import { RestClient } from "talk-framework/lib/rest";
|
||||
import { createInMemoryStorage } from "talk-framework/lib/storage";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
@@ -38,16 +39,14 @@ beforeEach(() => {
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
comment: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: commentStub.id })
|
||||
.returns(commentStub),
|
||||
asset: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: assetStub.id })
|
||||
.returns(assetStub),
|
||||
comment: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: commentStub.id }).returns(commentStub)
|
||||
),
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assetStub.id }).returns(assetStub)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import { PostMessageService } from "talk-framework/lib/postMessage";
|
||||
import { RestClient } from "talk-framework/lib/rest";
|
||||
import { createInMemoryStorage } from "talk-framework/lib/storage";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
@@ -39,11 +40,10 @@ beforeEach(() => {
|
||||
const resolvers = {
|
||||
Query: {
|
||||
comment: () => null,
|
||||
asset: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: assetStub.id })
|
||||
.returns(assetStub),
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assetStub.id }).returns(assetStub)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import React from "react";
|
||||
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
|
||||
import { RecordProxy } from "relay-runtime";
|
||||
import timekeeper from "timekeeper";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import { PostMessageService } from "talk-framework/lib/postMessage";
|
||||
import { RestClient } from "talk-framework/lib/rest";
|
||||
import { createInMemoryStorage } from "talk-framework/lib/storage";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
import createFluentBundle from "./createFluentBundle";
|
||||
import createNodeMock from "./createNodeMock";
|
||||
import { assets, users } from "./fixtures";
|
||||
|
||||
let testRenderer: ReactTestRenderer;
|
||||
beforeEach(() => {
|
||||
const resolvers = {
|
||||
Query: {
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assets[0].id }).returns(assets[0])
|
||||
),
|
||||
me: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { clientAuthRevision: 0 }).returns(users[0])
|
||||
),
|
||||
},
|
||||
Mutation: {
|
||||
createComment: createSinonStub(
|
||||
s => s.throws(),
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, {
|
||||
input: {
|
||||
assetID: assets[0].id,
|
||||
body: "<strong>Hello world!</strong>",
|
||||
clientMutationId: "0",
|
||||
},
|
||||
})
|
||||
.returns({
|
||||
commentEdge: {
|
||||
cursor: "2018-07-06T18:24:00.000Z",
|
||||
node: {
|
||||
id: "comment-x",
|
||||
author: users[0],
|
||||
body: "<strong>Hello world! (from server)</strong>",
|
||||
createdAt: "2018-07-06T18:24:00.000Z",
|
||||
},
|
||||
},
|
||||
clientMutationId: "0",
|
||||
})
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
const environment = createEnvironment({
|
||||
// Set this to true, to see graphql responses.
|
||||
logNetwork: false,
|
||||
resolvers,
|
||||
initLocalState: (localRecord: RecordProxy) => {
|
||||
localRecord.setValue(assets[0].id, "assetID");
|
||||
localRecord.setValue(0, "authRevision");
|
||||
},
|
||||
});
|
||||
|
||||
const context: TalkContext = {
|
||||
relayEnvironment: environment,
|
||||
localeBundles: [createFluentBundle()],
|
||||
localStorage: createInMemoryStorage(),
|
||||
sessionStorage: createInMemoryStorage(),
|
||||
rest: new RestClient("http://localhost/api"),
|
||||
postMessage: new PostMessageService(),
|
||||
};
|
||||
|
||||
testRenderer = TestRenderer.create(
|
||||
<TalkContextProvider value={context}>
|
||||
<AppContainer />
|
||||
</TalkContextProvider>,
|
||||
{ createNodeMock }
|
||||
);
|
||||
});
|
||||
|
||||
it("renders comment stream", async () => {
|
||||
// Wait for loading.
|
||||
await timeout();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("post a comment", async () => {
|
||||
testRenderer.root
|
||||
.findByProps({ inputId: "comments-postCommentForm-field" })
|
||||
.props.onChange({ html: "<strong>Hello world!</strong>" });
|
||||
|
||||
timekeeper.travel(new Date("2018-07-06T18:24:00.000Z"));
|
||||
testRenderer.root
|
||||
.findByProps({ id: "comments-postCommentForm-form" })
|
||||
.props.onSubmit();
|
||||
// Test optimistic response.
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
timekeeper.reset();
|
||||
|
||||
// Wait for loading.
|
||||
await timeout();
|
||||
// Test after server response.
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -1,13 +1,13 @@
|
||||
import React from "react";
|
||||
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
|
||||
import { RecordProxy } from "relay-runtime";
|
||||
import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import { PostMessageService } from "talk-framework/lib/postMessage";
|
||||
import { RestClient } from "talk-framework/lib/rest";
|
||||
import { createInMemoryStorage } from "talk-framework/lib/storage";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
@@ -19,11 +19,13 @@ let testRenderer: ReactTestRenderer;
|
||||
beforeEach(() => {
|
||||
const resolvers = {
|
||||
Query: {
|
||||
asset: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: assetWithReplies.id })
|
||||
.returns(assetWithReplies),
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, { id: assetWithReplies.id })
|
||||
.returns(assetWithReplies)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React from "react";
|
||||
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
|
||||
import { RecordProxy } from "relay-runtime";
|
||||
import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import { PostMessageService } from "talk-framework/lib/postMessage";
|
||||
import { RestClient } from "talk-framework/lib/rest";
|
||||
import { createInMemoryStorage } from "talk-framework/lib/storage";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
@@ -19,11 +19,10 @@ let testRenderer: ReactTestRenderer;
|
||||
beforeEach(() => {
|
||||
const resolvers = {
|
||||
Query: {
|
||||
asset: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: assets[0].id })
|
||||
.returns(assets[0]),
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assets[0].id }).returns(assets[0])
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import { PostMessageService } from "talk-framework/lib/postMessage";
|
||||
import { RestClient } from "talk-framework/lib/rest";
|
||||
import { createInMemoryStorage } from "talk-framework/lib/storage";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
@@ -17,41 +18,43 @@ import { assets, comments } from "./fixtures";
|
||||
|
||||
let testRenderer: ReactTestRenderer;
|
||||
beforeEach(() => {
|
||||
const connectionStub = sinon.stub().throws();
|
||||
connectionStub.withArgs({ first: 5, orderBy: "CREATED_AT_ASC" }).returns({
|
||||
edges: [
|
||||
{
|
||||
node: comments[1],
|
||||
cursor: comments[1].createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: comments[1].createdAt,
|
||||
hasNextPage: true,
|
||||
},
|
||||
});
|
||||
connectionStub
|
||||
.withArgs({
|
||||
first: sinon.match(n => n > 10000),
|
||||
orderBy: "CREATED_AT_ASC",
|
||||
after: comments[1].createdAt,
|
||||
})
|
||||
.returns({
|
||||
edges: [
|
||||
{
|
||||
node: comments[2],
|
||||
cursor: comments[2].createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: comments[2].createdAt,
|
||||
hasNextPage: false,
|
||||
},
|
||||
});
|
||||
|
||||
const commentStub = {
|
||||
...comments[0],
|
||||
replies: connectionStub,
|
||||
replies: createSinonStub(
|
||||
s => s.throws(),
|
||||
s =>
|
||||
s.withArgs({ first: 5, orderBy: "CREATED_AT_ASC" }).returns({
|
||||
edges: [
|
||||
{
|
||||
node: comments[1],
|
||||
cursor: comments[1].createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: comments[1].createdAt,
|
||||
hasNextPage: true,
|
||||
},
|
||||
}),
|
||||
s =>
|
||||
s
|
||||
.withArgs({
|
||||
first: sinon.match(n => n > 10000),
|
||||
orderBy: "CREATED_AT_ASC",
|
||||
after: comments[1].createdAt,
|
||||
})
|
||||
.returns({
|
||||
edges: [
|
||||
{
|
||||
node: comments[2],
|
||||
cursor: comments[2].createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: comments[2].createdAt,
|
||||
hasNextPage: false,
|
||||
},
|
||||
})
|
||||
),
|
||||
};
|
||||
|
||||
const assetStub = {
|
||||
@@ -71,16 +74,14 @@ beforeEach(() => {
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
comment: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: commentStub.id })
|
||||
.returns(commentStub),
|
||||
asset: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: assetStub.id })
|
||||
.returns(assetStub),
|
||||
comment: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: commentStub.id }).returns(commentStub)
|
||||
),
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assetStub.id }).returns(assetStub)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,15 @@ declare var global: any;
|
||||
const jsdom = new JSDOM("<!doctype html><html><body></body></html>");
|
||||
const { window } = jsdom;
|
||||
|
||||
// tiny shim for getSelection for the RTE.
|
||||
// tslint:disable:no-empty
|
||||
window.getSelection = () =>
|
||||
({
|
||||
addRange() {},
|
||||
removeAllRanges() {},
|
||||
} as any);
|
||||
// tslint:enable:no-empty
|
||||
|
||||
function copyProps(src: any, target: any) {
|
||||
const props = Object.getOwnPropertyNames(src)
|
||||
.filter(prop => typeof target[prop] === "undefined")
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import { GQLMutationTypeResolver } from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
|
||||
const Mutation: GQLMutationTypeResolver<void> = {
|
||||
createComment: async (source, { input }, ctx) => ({
|
||||
comment: await ctx.mutators.Comment.create(input),
|
||||
clientMutationId: input.clientMutationId,
|
||||
}),
|
||||
createComment: async (source, { input }, ctx) => {
|
||||
const comment = await ctx.mutators.Comment.create(input);
|
||||
// TODO: (cvle) tell wyatt to take a look at this :-)
|
||||
return {
|
||||
commentEdge: {
|
||||
cursor: comment.created_at,
|
||||
node: comment,
|
||||
},
|
||||
clientMutationId: input.clientMutationId,
|
||||
};
|
||||
},
|
||||
updateSettings: async (source, { input }, ctx) => ({
|
||||
settings: await ctx.mutators.Settings.update(input.settings),
|
||||
clientMutationId: input.clientMutationId,
|
||||
|
||||
@@ -577,7 +577,7 @@ type Comment {
|
||||
"""
|
||||
createdAt is the date in which the comment was created.
|
||||
"""
|
||||
createdAt: Time
|
||||
createdAt: Time!
|
||||
|
||||
"""
|
||||
author is the User that authored the Comment.
|
||||
@@ -821,9 +821,9 @@ mutation.
|
||||
"""
|
||||
type CreateCommentPayload {
|
||||
"""
|
||||
comment is the possibly created comment.
|
||||
CommentEdge is the possibly created comment edge.
|
||||
"""
|
||||
comment: Comment
|
||||
commentEdge: CommentEdge
|
||||
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
## Comments Tab
|
||||
|
||||
comments-streamQuery-assetNotFound = Asset not found
|
||||
|
||||
comments-postCommentForm-submit = Submit
|
||||
comments-stream-loadMore = Load more
|
||||
comments-replyList-showAll = Show all
|
||||
|
||||
Reference in New Issue
Block a user