mirror of
https://github.com/wassname/talk.git
synced 2026-08-11 11:27:10 +08:00
Merge branch 'next' into next-respect
This commit is contained in:
@@ -10,6 +10,8 @@ module.exports = {
|
||||
"<rootDir>/src/core/build/polyfills.js",
|
||||
"<rootDir>/src/core/client/test/setup.ts",
|
||||
],
|
||||
setupTestFrameworkScriptFile:
|
||||
"<rootDir>/src/core/client/test/setupTestFramework.ts",
|
||||
testMatch: ["**/*.spec.{js,jsx,mjs,ts,tsx}"],
|
||||
testEnvironment: "node",
|
||||
testURL: "http://localhost",
|
||||
|
||||
Generated
+28
-13
@@ -1086,16 +1086,6 @@
|
||||
"@babel/helper-plugin-utils": "7.0.0-beta.49"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-sticky-regex": {
|
||||
"version": "7.0.0-beta.49",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0-beta.49.tgz",
|
||||
"integrity": "sha1-CMxbZM9qWUKoe92bSkgY1MuhLfM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "7.0.0-beta.49",
|
||||
"@babel/helper-regex": "7.0.0-beta.49"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-template-literals": {
|
||||
"version": "7.0.0-beta.49",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0-beta.49.tgz",
|
||||
@@ -1211,6 +1201,16 @@
|
||||
"@babel/helper-plugin-utils": "7.0.0-beta.49",
|
||||
"@babel/helper-simple-access": "7.0.0-beta.49"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-sticky-regex": {
|
||||
"version": "7.0.0-beta.49",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0-beta.49.tgz",
|
||||
"integrity": "sha1-CMxbZM9qWUKoe92bSkgY1MuhLfM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "7.0.0-beta.49",
|
||||
"@babel/helper-regex": "7.0.0-beta.49"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2162,9 +2162,13 @@
|
||||
}
|
||||
},
|
||||
"@types/recompose": {
|
||||
"version": "github:coralproject/patched#3ca0deec868322739fc0d750398fd97735d27aac",
|
||||
"from": "github:coralproject/patched#types/recompose",
|
||||
"dev": true
|
||||
"version": "0.26.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/recompose/-/recompose-0.26.5.tgz",
|
||||
"integrity": "sha512-Il5stz/Z3pVIMl48pyggl6nnhRLQ8N8YN8hi0Anm0M5UjVh2uMSY0ah2vzwZZKxnca4NzyJArloSjsJ9fL2vWw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/relateurl": {
|
||||
"version": "0.2.28",
|
||||
@@ -14225,6 +14229,12 @@
|
||||
"integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=",
|
||||
"dev": true
|
||||
},
|
||||
"jest-mock-console": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-mock-console/-/jest-mock-console-0.4.0.tgz",
|
||||
"integrity": "sha512-WElCbNvfqQlD7cpfHfTn1ytZ+RjKg1Ftrvr5wEjdWP7a9esXmaiZuEAPeYUSK5fd0Cra+dR1oF8HAjjKKxDQdg==",
|
||||
"dev": true
|
||||
},
|
||||
"jest-regex-util": {
|
||||
"version": "23.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz",
|
||||
@@ -18041,6 +18051,11 @@
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"permit": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/permit/-/permit-0.2.4.tgz",
|
||||
"integrity": "sha512-Mp2XTEMD3mPsZIWq3bp0claE4IxXKa4C6nhSDPZgGri8Q4CLjEjAQrP/xGKq2548a2KFENmA1V7W0Lob8kTuzw=="
|
||||
},
|
||||
"pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
|
||||
+3
-1
@@ -74,6 +74,7 @@
|
||||
"passport-oauth2": "^1.4.0",
|
||||
"passport-strategy": "^1.0.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"permit": "^0.2.4",
|
||||
"subscriptions-transport-ws": "^0.9.12",
|
||||
"tlds": "^1.203.1",
|
||||
"uuid": "^3.3.2"
|
||||
@@ -133,7 +134,7 @@
|
||||
"@types/react-relay": "^1.3.9",
|
||||
"@types/react-responsive": "^3.0.1",
|
||||
"@types/react-test-renderer": "^16.0.1",
|
||||
"@types/recompose": "github:coralproject/patched#types/recompose",
|
||||
"@types/recompose": "^0.26.5",
|
||||
"@types/relay-runtime": "^1.3.6",
|
||||
"@types/sane": "^2.0.0",
|
||||
"@types/sinon": "^5.0.1",
|
||||
@@ -185,6 +186,7 @@
|
||||
"jest": "^23.4.1",
|
||||
"jest-junit": "^5.1.0",
|
||||
"jest-localstorage-mock": "^2.2.0",
|
||||
"jest-mock-console": "^0.4.0",
|
||||
"jsdom": "^11.11.0",
|
||||
"loader-utils": "^1.1.0",
|
||||
"material-design-icons": "^3.0.1",
|
||||
|
||||
@@ -288,6 +288,25 @@ export default function createWebpackConfig({
|
||||
},
|
||||
],
|
||||
},
|
||||
// Makes sure node_modules are transpiled the way we need them to be.
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: /node_modules\//,
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve("babel-loader"),
|
||||
options: {
|
||||
presets: [
|
||||
[
|
||||
"@babel/env",
|
||||
{ targets: "last 2 versions, ie 11", modules: false },
|
||||
],
|
||||
],
|
||||
cacheDirectory: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
||||
// "style" loader turns CSS into JS modules that inject <style> tags.
|
||||
@@ -363,6 +382,22 @@ export default function createWebpackConfig({
|
||||
},
|
||||
};
|
||||
|
||||
const devServerEntries = isProduction
|
||||
? []
|
||||
: [
|
||||
// Include an alternative client for WebpackDevServer. A client's job is to
|
||||
// connect to WebpackDevServer by a socket and get notified about changes.
|
||||
// When you save a file, the client will either apply hot updates (in case
|
||||
// of CSS changes), or refresh the page (in case of JS changes). When you
|
||||
// make a syntax error, this client will display a syntax error overlay.
|
||||
// Note: instead of the default WebpackDevServer client, we use a custom one
|
||||
// to bring better experience for Create React App users. You can replace
|
||||
// the line below with these two lines if you prefer the stock client:
|
||||
// require.resolve('webpack-dev-server/client') + '?/',
|
||||
// require.resolve('webpack/hot/dev-server'),
|
||||
require.resolve("react-dev-utils/webpackHotDevClient"),
|
||||
];
|
||||
|
||||
return [
|
||||
/* Webpack config for our different target, e.g. stream, admin... */
|
||||
{
|
||||
@@ -371,39 +406,16 @@ export default function createWebpackConfig({
|
||||
stream: [
|
||||
// We ship polyfills by default
|
||||
paths.appPolyfill,
|
||||
// Include an alternative client for WebpackDevServer. A client's job is to
|
||||
// connect to WebpackDevServer by a socket and get notified about changes.
|
||||
// When you save a file, the client will either apply hot updates (in case
|
||||
// of CSS changes), or refresh the page (in case of JS changes). When you
|
||||
// make a syntax error, this client will display a syntax error overlay.
|
||||
// Note: instead of the default WebpackDevServer client, we use a custom one
|
||||
// to bring better experience for Create React App users. You can replace
|
||||
// the line below with these two lines if you prefer the stock client:
|
||||
// require.resolve('webpack-dev-server/client') + '?/',
|
||||
// require.resolve('webpack/hot/dev-server'),
|
||||
(isProduction && "") ||
|
||||
require.resolve("react-dev-utils/webpackHotDevClient"),
|
||||
...devServerEntries,
|
||||
paths.appStreamIndex,
|
||||
// Remove deactivated entries.
|
||||
].filter(s => s),
|
||||
],
|
||||
auth: [
|
||||
// We ship polyfills by default
|
||||
paths.appPolyfill,
|
||||
// Include an alternative client for WebpackDevServer. A client's job is to
|
||||
// connect to WebpackDevServer by a socket and get notified about changes.
|
||||
// When you save a file, the client will either apply hot updates (in case
|
||||
// of CSS changes), or refresh the page (in case of JS changes). When you
|
||||
// make a syntax error, this client will display a syntax error overlay.
|
||||
// Note: instead of the default WebpackDevServer client, we use a custom one
|
||||
// to bring better experience for Create React App users. You can replace
|
||||
// the line below with these two lines if you prefer the stock client:
|
||||
// require.resolve('webpack-dev-server/client') + '?/',
|
||||
// require.resolve('webpack/hot/dev-server'),
|
||||
(isProduction && "") ||
|
||||
require.resolve("react-dev-utils/webpackHotDevClient"),
|
||||
...devServerEntries,
|
||||
paths.appAuthIndex,
|
||||
// Remove deactivated entries.
|
||||
].filter(s => s),
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
...baseConfig.plugins!,
|
||||
@@ -440,33 +452,50 @@ export default function createWebpackConfig({
|
||||
{
|
||||
...baseConfig,
|
||||
entry: [
|
||||
// No polyfills for the embed.
|
||||
(isProduction && "") ||
|
||||
require.resolve("react-dev-utils/webpackHotDevClient"),
|
||||
/* Use minimal amount of polyfills (for IE) */
|
||||
"core-js/fn/object/assign",
|
||||
"core-js/fn/symbol",
|
||||
"core-js/fn/symbol/iterator",
|
||||
...devServerEntries,
|
||||
paths.appEmbedIndex,
|
||||
// Remove deactivated entries.
|
||||
].filter(s => s),
|
||||
],
|
||||
output: {
|
||||
...baseConfig.output,
|
||||
library: "Talk",
|
||||
library: "Coral",
|
||||
// don't hash the embed, cache-busting must be completed by the requester
|
||||
// as this lives in a static template on the embed site.
|
||||
filename: "assets/js/embed.js",
|
||||
},
|
||||
plugins: [
|
||||
...baseConfig.plugins!,
|
||||
// Generates an `stream.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "embed.html",
|
||||
template: paths.appEmbedHTML,
|
||||
inject: "head",
|
||||
...htmlWebpackConfig,
|
||||
}),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In development, this will be an empty string.
|
||||
new InterpolateHtmlPlugin(env),
|
||||
...(isProduction
|
||||
? []
|
||||
: [
|
||||
// Generates an `embed.html` file with the <script> injected.
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "embed.html",
|
||||
template: paths.appEmbedHTML,
|
||||
inject: "head",
|
||||
...htmlWebpackConfig,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "article.html",
|
||||
template: paths.appEmbedArticleHTML,
|
||||
inject: "head",
|
||||
...htmlWebpackConfig,
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "articleButton.html",
|
||||
template: paths.appEmbedArticleButtonHTML,
|
||||
inject: "head",
|
||||
...htmlWebpackConfig,
|
||||
}),
|
||||
// Makes some environment variables available in index.html.
|
||||
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
||||
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
// In development, this will be an empty string.
|
||||
new InterpolateHtmlPlugin(env),
|
||||
]),
|
||||
// Generate a manifest file which contains a mapping of all asset filenames
|
||||
// to their corresponding output file so that tools can pick it up without
|
||||
// having to parse `index.html`.
|
||||
|
||||
@@ -95,9 +95,9 @@ function generateTarget(target, context) {
|
||||
`
|
||||
)
|
||||
.join("\n")}
|
||||
contents = contents.concat(suffixes.map(function(suffix) { return require(\`${path
|
||||
contents = contents.concat(suffixes.map(function(suffix) { return require("${path
|
||||
.join(getLocalePath(locale), target)
|
||||
.replace(/\\/g, "/")}\${suffix}\`); }));
|
||||
.replace(/\\/g, "/")}" + suffix); }));
|
||||
ret.bundled[${JSON.stringify(locale)}] = contents.join("\\n");
|
||||
}
|
||||
`
|
||||
@@ -132,9 +132,9 @@ function generateTarget(target, context) {
|
||||
/* webpackChunkName: ${JSON.stringify(
|
||||
`${target}-locale-${locale}`
|
||||
)}, webpackMode: "lazy-once" */
|
||||
\`${path
|
||||
"${path
|
||||
.join(getLocalePath(locale), target)
|
||||
.replace(/\\/g, "/")}\${suffix}\`
|
||||
.replace(/\\/g, "/")}" + suffix
|
||||
)
|
||||
}));
|
||||
return Promise.all(promises).then(function(modules) {
|
||||
|
||||
@@ -31,6 +31,8 @@ export default {
|
||||
|
||||
appEmbedIndex: resolveSrc("core/client/embed/index.ts"),
|
||||
appEmbedHTML: resolveSrc("core/client/embed/index.html"),
|
||||
appEmbedArticleHTML: resolveSrc("core/client/embed/article.html"),
|
||||
appEmbedArticleButtonHTML: resolveSrc("core/client/embed/articleButton.html"),
|
||||
|
||||
appDistStatic: resolveApp("dist/static"),
|
||||
appPublic: resolveApp("public"),
|
||||
|
||||
@@ -2,13 +2,18 @@ import pym from "pym.js";
|
||||
|
||||
import { CleanupCallback, Decorator } from "./decorators";
|
||||
|
||||
interface PymControlConfig {
|
||||
export interface PymControlConfig {
|
||||
id: string;
|
||||
url: string;
|
||||
title: string;
|
||||
decorators?: ReadonlyArray<Decorator>;
|
||||
}
|
||||
|
||||
export type PymControlFactory = (config: PymControlConfig) => PymControl;
|
||||
|
||||
export const defaultPymControlFactory: PymControlFactory = config =>
|
||||
new PymControl(config);
|
||||
|
||||
export default class PymControl {
|
||||
private pym: pym.Parent;
|
||||
private cleanups: CleanupCallback[];
|
||||
@@ -20,6 +25,7 @@ export default class PymControl {
|
||||
title: config.title,
|
||||
id: `${config.id}_iframe`,
|
||||
name: `${config.id}_iframe`,
|
||||
optionalparams: "",
|
||||
});
|
||||
|
||||
this.cleanups = decorators
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import sinon from "sinon";
|
||||
|
||||
import { createStreamInterface } from "./Stream";
|
||||
|
||||
it("should call eventEmitter.on", () => {
|
||||
const control = {};
|
||||
const cb = () => "";
|
||||
const eventEmitter = {
|
||||
on: sinon
|
||||
.mock()
|
||||
.once()
|
||||
.withArgs("eventName", cb),
|
||||
};
|
||||
const stream = createStreamInterface(control as any, eventEmitter as any);
|
||||
stream.on("eventName", cb);
|
||||
eventEmitter.on.verify();
|
||||
});
|
||||
|
||||
it("should call eventEmitter.off", () => {
|
||||
const control = {};
|
||||
const cb = () => "";
|
||||
const eventEmitter = {
|
||||
off: sinon
|
||||
.mock()
|
||||
.once()
|
||||
.withArgs("eventName", cb),
|
||||
};
|
||||
const stream = createStreamInterface(control as any, eventEmitter as any);
|
||||
stream.off("eventName", cb);
|
||||
eventEmitter.off.verify();
|
||||
});
|
||||
|
||||
it("should call control.login", () => {
|
||||
const control = {
|
||||
sendMessage: sinon
|
||||
.mock()
|
||||
.once()
|
||||
.withArgs("login", "token"),
|
||||
};
|
||||
const eventEmitter = {};
|
||||
const stream = createStreamInterface(control as any, eventEmitter as any);
|
||||
stream.login("token");
|
||||
control.sendMessage.verify();
|
||||
});
|
||||
|
||||
it("should call control.logout", () => {
|
||||
const control = {
|
||||
sendMessage: sinon
|
||||
.mock()
|
||||
.once()
|
||||
.withArgs("logout"),
|
||||
};
|
||||
const eventEmitter = {};
|
||||
const stream = createStreamInterface(control as any, eventEmitter as any);
|
||||
stream.logout();
|
||||
control.sendMessage.verify();
|
||||
});
|
||||
|
||||
it("should call control.remove", () => {
|
||||
const control = {
|
||||
remove: sinon
|
||||
.mock()
|
||||
.once()
|
||||
.withArgs(),
|
||||
};
|
||||
const eventEmitter = {};
|
||||
const stream = createStreamInterface(control as any, eventEmitter as any);
|
||||
stream.remove();
|
||||
control.remove.verify();
|
||||
});
|
||||
@@ -1,89 +0,0 @@
|
||||
import { EventEmitter2 } from "eventemitter2";
|
||||
import qs from "query-string";
|
||||
|
||||
import {
|
||||
Decorator,
|
||||
withAutoHeight,
|
||||
withClickEvent,
|
||||
withEventEmitter,
|
||||
withIOSSafariWidthWorkaround,
|
||||
withPymStorage,
|
||||
withSetCommentID,
|
||||
} from "./decorators";
|
||||
import PymControl from "./PymControl";
|
||||
import { ensureEndSlash } from "./utils";
|
||||
|
||||
interface CreatePymControlConfig {
|
||||
assetID?: string;
|
||||
assetURL?: string;
|
||||
commentID?: string;
|
||||
title?: string;
|
||||
eventEmitter: EventEmitter2;
|
||||
id: string;
|
||||
rootURL: string;
|
||||
}
|
||||
|
||||
export function createPymControl(config: CreatePymControlConfig) {
|
||||
const streamDecorators: ReadonlyArray<Decorator> = [
|
||||
withIOSSafariWidthWorkaround,
|
||||
withAutoHeight,
|
||||
withClickEvent,
|
||||
withSetCommentID,
|
||||
withEventEmitter(config.eventEmitter),
|
||||
withPymStorage(localStorage, "localStorage"),
|
||||
withPymStorage(sessionStorage, "sessionStorage"),
|
||||
];
|
||||
|
||||
const query = qs.stringify({
|
||||
assetID: config.assetID,
|
||||
assetURL: config.assetURL,
|
||||
commentID: config.commentID,
|
||||
});
|
||||
const url = `${ensureEndSlash(config.rootURL)}stream.html?${query}`;
|
||||
return new PymControl({
|
||||
id: config.id,
|
||||
title: config.title || "Talk Embed Stream",
|
||||
decorators: streamDecorators,
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
type EventCallback = (data: any) => void;
|
||||
|
||||
export function createStreamInterface(
|
||||
control: PymControl,
|
||||
eventEmitter: EventEmitter2
|
||||
) {
|
||||
return {
|
||||
on(eventName: string, callback: EventCallback) {
|
||||
return eventEmitter.on(eventName, callback);
|
||||
},
|
||||
off(eventName: string, callback: EventCallback) {
|
||||
return eventEmitter.off(eventName, callback);
|
||||
},
|
||||
login(token: string) {
|
||||
control.sendMessage("login", token);
|
||||
},
|
||||
logout() {
|
||||
control.sendMessage("logout");
|
||||
},
|
||||
remove() {
|
||||
return control.remove();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export type StreamInterface = ReturnType<typeof createStreamInterface>;
|
||||
|
||||
export interface CreateConfig {
|
||||
assetID?: string;
|
||||
assetURL?: string;
|
||||
commentID?: string;
|
||||
title?: string;
|
||||
eventEmitter: EventEmitter2;
|
||||
id: string;
|
||||
rootURL: string;
|
||||
}
|
||||
export default function create(config: CreateConfig) {
|
||||
return createStreamInterface(createPymControl(config), config.eventEmitter);
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import { EventEmitter2 } from "eventemitter2";
|
||||
import { omit } from "lodash";
|
||||
import sinon from "sinon";
|
||||
|
||||
import { PymControlConfig } from "./PymControl";
|
||||
import { StreamEmbed, StreamEmbedConfig } from "./StreamEmbed";
|
||||
|
||||
it("should throw when calling pym dependent methods but was not rendered", () => {
|
||||
const config: StreamEmbedConfig = {
|
||||
title: "StreamEmbed",
|
||||
eventEmitter: new EventEmitter2(),
|
||||
id: "container-id",
|
||||
rootURL: "http://localhost/",
|
||||
};
|
||||
const streamEmbed = new StreamEmbed(config);
|
||||
[
|
||||
() => streamEmbed.login("token"),
|
||||
() => streamEmbed.logout(),
|
||||
() => streamEmbed.remove(),
|
||||
].forEach(cb => {
|
||||
expect(cb).toThrow();
|
||||
});
|
||||
});
|
||||
it("should return rendered", () => {
|
||||
const config: StreamEmbedConfig = {
|
||||
title: "StreamEmbed",
|
||||
eventEmitter: new EventEmitter2(),
|
||||
id: "container-id",
|
||||
rootURL: "http://localhost/",
|
||||
};
|
||||
const pymControl = {
|
||||
remove: sinon.stub(),
|
||||
};
|
||||
const fakeFactory: any = () => pymControl;
|
||||
const streamEmbed = new StreamEmbed(config, fakeFactory);
|
||||
expect(streamEmbed.rendered).toBe(false);
|
||||
streamEmbed.render();
|
||||
expect(streamEmbed.rendered).toBe(true);
|
||||
streamEmbed.remove();
|
||||
expect(streamEmbed.rendered).toBe(false);
|
||||
expect(pymControl.remove.called).toBe(true);
|
||||
});
|
||||
|
||||
it("should relay events methods to event emitter", () => {
|
||||
const config: StreamEmbedConfig = {
|
||||
title: "StreamEmbed",
|
||||
eventEmitter: new EventEmitter2(),
|
||||
id: "container-id",
|
||||
rootURL: "http://localhost/",
|
||||
};
|
||||
// tslint:disable-next-line:no-empty
|
||||
const callback = () => {};
|
||||
const fakeFactory: any = () => ({});
|
||||
const emitterMock = sinon.mock(config.eventEmitter);
|
||||
emitterMock
|
||||
.expects("on")
|
||||
.withArgs("event", callback)
|
||||
.once();
|
||||
emitterMock
|
||||
.expects("off")
|
||||
.withArgs("event", callback)
|
||||
.once();
|
||||
const streamEmbed = new StreamEmbed(config, fakeFactory);
|
||||
streamEmbed.on("event", callback);
|
||||
streamEmbed.off("event", callback);
|
||||
});
|
||||
|
||||
it("should send login message to PymControl", () => {
|
||||
const config: StreamEmbedConfig = {
|
||||
title: "StreamEmbed",
|
||||
eventEmitter: new EventEmitter2(),
|
||||
id: "container-id",
|
||||
rootURL: "http://localhost/",
|
||||
};
|
||||
const pymControl = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
sendMessage: () => {},
|
||||
};
|
||||
const pymControlMock = sinon.mock(pymControl);
|
||||
pymControlMock.expects("sendMessage").withArgs("login", "token");
|
||||
const fakeFactory: any = () => pymControl;
|
||||
const streamEmbed = new StreamEmbed(config, fakeFactory);
|
||||
streamEmbed.render();
|
||||
streamEmbed.login("token");
|
||||
pymControlMock.verify();
|
||||
});
|
||||
|
||||
it("should send logout message to PymControl", () => {
|
||||
const config: StreamEmbedConfig = {
|
||||
title: "StreamEmbed",
|
||||
eventEmitter: new EventEmitter2(),
|
||||
id: "container-id",
|
||||
rootURL: "http://localhost/",
|
||||
};
|
||||
const pymControl = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
sendMessage: () => {},
|
||||
};
|
||||
const pymControlMock = sinon.mock(pymControl);
|
||||
pymControlMock.expects("sendMessage").withArgs("logout");
|
||||
const fakeFactory: any = () => pymControl;
|
||||
const streamEmbed = new StreamEmbed(config, fakeFactory);
|
||||
streamEmbed.render();
|
||||
streamEmbed.logout();
|
||||
pymControlMock.verify();
|
||||
});
|
||||
|
||||
it("should pass default values to pymControl", () => {
|
||||
const config: StreamEmbedConfig = {
|
||||
title: "StreamEmbed",
|
||||
eventEmitter: new EventEmitter2(),
|
||||
id: "container-id",
|
||||
rootURL: "http://localhost/",
|
||||
};
|
||||
let pymControlConfig: PymControlConfig | null = null;
|
||||
const fakeFactory: any = (cfg: PymControlConfig) => {
|
||||
pymControlConfig = cfg;
|
||||
return {};
|
||||
};
|
||||
const streamEmbed = new StreamEmbed(config, fakeFactory);
|
||||
streamEmbed.render();
|
||||
expect(omit(pymControlConfig, "decorators")).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should pass correct values to pymControl", () => {
|
||||
const config: StreamEmbedConfig = {
|
||||
title: "StreamEmbed",
|
||||
eventEmitter: new EventEmitter2(),
|
||||
id: "container-id",
|
||||
rootURL: "http://localhost/",
|
||||
commentID: "comment-id",
|
||||
assetID: "asset-id",
|
||||
assetURL: "asset-url",
|
||||
};
|
||||
let pymControlConfig: PymControlConfig | null = null;
|
||||
const fakeFactory: any = (cfg: PymControlConfig) => {
|
||||
pymControlConfig = cfg;
|
||||
return {};
|
||||
};
|
||||
const streamEmbed = new StreamEmbed(config, fakeFactory);
|
||||
streamEmbed.render();
|
||||
expect(omit(pymControlConfig, "decorators")).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should emit showPermalink", () => {
|
||||
jest.useFakeTimers();
|
||||
const config: StreamEmbedConfig = {
|
||||
title: "StreamEmbed",
|
||||
eventEmitter: new EventEmitter2(),
|
||||
id: "container-id",
|
||||
rootURL: "http://localhost/",
|
||||
commentID: "comment-id",
|
||||
};
|
||||
// tslint:disable-next-line:no-empty
|
||||
const fakeFactory: any = () => ({});
|
||||
const emitterMock = sinon.mock(config.eventEmitter);
|
||||
emitterMock
|
||||
.expects("emit")
|
||||
.withArgs("showPermalink")
|
||||
.once();
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
new StreamEmbed(config, fakeFactory);
|
||||
jest.runOnlyPendingTimers();
|
||||
jest.useRealTimers();
|
||||
emitterMock.verify();
|
||||
});
|
||||
@@ -0,0 +1,127 @@
|
||||
import { EventEmitter2 } from "eventemitter2";
|
||||
import qs from "query-string";
|
||||
|
||||
import {
|
||||
Decorator,
|
||||
withAutoHeight,
|
||||
withClickEvent,
|
||||
withEventEmitter,
|
||||
withIOSSafariWidthWorkaround,
|
||||
withPymStorage,
|
||||
withSetCommentID,
|
||||
} from "./decorators";
|
||||
import onIntersect from "./onIntersect";
|
||||
import PymControl, {
|
||||
defaultPymControlFactory,
|
||||
PymControlFactory,
|
||||
} from "./PymControl";
|
||||
import { ensureEndSlash } from "./utils";
|
||||
|
||||
export interface StreamEmbedConfig {
|
||||
assetID?: string;
|
||||
assetURL?: string;
|
||||
commentID?: string;
|
||||
autoRender?: boolean;
|
||||
title: string;
|
||||
eventEmitter: EventEmitter2;
|
||||
id: string;
|
||||
rootURL: string;
|
||||
}
|
||||
|
||||
export class StreamEmbed {
|
||||
private config: StreamEmbedConfig;
|
||||
private pymControl?: PymControl;
|
||||
private pymControlFactory: PymControlFactory;
|
||||
|
||||
constructor(
|
||||
config: StreamEmbedConfig,
|
||||
pymControlFactory = defaultPymControlFactory
|
||||
) {
|
||||
this.config = config;
|
||||
this.pymControlFactory = pymControlFactory;
|
||||
if (config.commentID) {
|
||||
// Delay emit of `showPermalink` event to allow
|
||||
// user enough time to setup event listeners.
|
||||
setTimeout(() => config.eventEmitter.emit("showPermalink"), 0);
|
||||
}
|
||||
if (config.autoRender) {
|
||||
if (config.commentID) {
|
||||
this.render();
|
||||
} else {
|
||||
onIntersect(document.getElementById(config.id)!, () => {
|
||||
if (!this.rendered) {
|
||||
this.render();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private assertRendered() {
|
||||
if (!this.pymControl) {
|
||||
throw new Error("Stream Embed must be rendered first");
|
||||
}
|
||||
}
|
||||
|
||||
public on(eventName: string, callback: (data: any) => void) {
|
||||
return this.config.eventEmitter.on(eventName, callback);
|
||||
}
|
||||
|
||||
public off(eventName: string, callback: (data: any) => void) {
|
||||
return this.config.eventEmitter.off(eventName, callback);
|
||||
}
|
||||
|
||||
public login(token: string) {
|
||||
this.assertRendered();
|
||||
this.pymControl!.sendMessage("login", token);
|
||||
}
|
||||
|
||||
public logout() {
|
||||
this.assertRendered();
|
||||
this.pymControl!.sendMessage("logout");
|
||||
}
|
||||
|
||||
public remove() {
|
||||
this.assertRendered();
|
||||
this.pymControl!.remove();
|
||||
this.pymControl = undefined;
|
||||
}
|
||||
|
||||
get rendered() {
|
||||
return !!this.pymControl;
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.pymControl) {
|
||||
throw new Error("Stream Embed already rendered");
|
||||
}
|
||||
const streamDecorators: ReadonlyArray<Decorator> = [
|
||||
withIOSSafariWidthWorkaround,
|
||||
withAutoHeight,
|
||||
withClickEvent,
|
||||
withSetCommentID,
|
||||
withEventEmitter(this.config.eventEmitter),
|
||||
withPymStorage(localStorage, "localStorage"),
|
||||
withPymStorage(sessionStorage, "sessionStorage"),
|
||||
];
|
||||
|
||||
const query = qs.stringify({
|
||||
assetID: this.config.assetID,
|
||||
assetURL: this.config.assetURL,
|
||||
commentID: this.config.commentID,
|
||||
});
|
||||
const url = `${ensureEndSlash(this.config.rootURL)}stream.html${
|
||||
query ? `?${query}` : ""
|
||||
}`;
|
||||
this.pymControl = this.pymControlFactory({
|
||||
id: this.config.id,
|
||||
title: this.config.title,
|
||||
decorators: streamDecorators,
|
||||
url,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default function createStreamEmbed(config: StreamEmbedConfig) {
|
||||
return new StreamEmbed(config);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { EventEmitter2 } from "eventemitter2";
|
||||
import qs from "query-string";
|
||||
|
||||
import { default as create, StreamEmbed } from "./StreamEmbed";
|
||||
|
||||
export interface Config {
|
||||
assetID?: string;
|
||||
assetURL?: string;
|
||||
commentID?: string;
|
||||
rootURL?: string;
|
||||
id?: string;
|
||||
autoRender?: boolean;
|
||||
events?: (eventEmitter: EventEmitter2) => void;
|
||||
}
|
||||
|
||||
function getLocationOrigin() {
|
||||
return (
|
||||
location.origin ||
|
||||
`${window.location.protocol}//${window.location.hostname}${
|
||||
window.location.port ? `:${window.location.port}` : ""
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
function resolveAssetURL() {
|
||||
const canonical = document.querySelector(
|
||||
'link[rel="canonical"]'
|
||||
) as HTMLLinkElement;
|
||||
if (canonical) {
|
||||
return canonical.href;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-console
|
||||
console.warn(
|
||||
"This page does not include a canonical link tag. Talk has inferred this asset_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages."
|
||||
);
|
||||
|
||||
return getLocationOrigin() + window.location.pathname;
|
||||
}
|
||||
|
||||
export function createStreamEmbed(config: Config): StreamEmbed {
|
||||
// Parse query params
|
||||
const query = qs.parse(location.search);
|
||||
const eventEmitter = new EventEmitter2({ wildcard: true });
|
||||
|
||||
if (config.events) {
|
||||
config.events(eventEmitter);
|
||||
}
|
||||
|
||||
return create({
|
||||
title: "Talk Embed Stream",
|
||||
assetID: config.assetID || query.assetID,
|
||||
assetURL: config.assetURL || resolveAssetURL(),
|
||||
commentID: config.commentID || query.commentID,
|
||||
id: config.id || "talk-embed-stream",
|
||||
rootURL: config.rootURL || getLocationOrigin(),
|
||||
autoRender: config.autoRender,
|
||||
eventEmitter,
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PymControl should create iframe 1`] = `"<iframe src=\\"http://coralproject.net/?initialWidth=0&childId=pymcontrol-test-id&parentTitle=&parentUrl=http%3A%2F%2Flocalhost%2F\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"iFrame title\\" id=\\"pymcontrol-test-id_iframe\\" name=\\"pymcontrol-test-id_iframe\\"></iframe>"`;
|
||||
exports[`PymControl should create iframe 1`] = `"<iframe src=\\"http://coralproject.net/?initialWidth=0&childId=pymcontrol-test-id\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"iFrame title\\" id=\\"pymcontrol-test-id_iframe\\" name=\\"pymcontrol-test-id_iframe\\"></iframe>"`;
|
||||
|
||||
exports[`PymControl should send message 1`] = `"pymxPYMxpymcontrol-test-idxPYMxtestxPYMxhello world"`;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`should pass correct values to pymControl 1`] = `
|
||||
Object {
|
||||
"id": "container-id",
|
||||
"title": "StreamEmbed",
|
||||
"url": "http://localhost/stream.html?assetID=asset-id&assetURL=asset-url&commentID=comment-id",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`should pass default values to pymControl 1`] = `
|
||||
Object {
|
||||
"id": "container-id",
|
||||
"title": "StreamEmbed",
|
||||
"url": "http://localhost/stream.html",
|
||||
}
|
||||
`;
|
||||
@@ -1,3 +1,5 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Basic integration test should render iframe 1`] = `"<iframe src=\\"http://localhost/stream.html?&initialWidth=0&childId=basic-integration-test-id&parentTitle=&parentUrl=http%3A%2F%2Flocalhost%2F\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"Talk Embed Stream\\" id=\\"basic-integration-test-id_iframe\\" name=\\"basic-integration-test-id_iframe\\" style=\\"width: 1px; min-width: 100%;\\"></iframe>"`;
|
||||
exports[`Basic integration test should render iframe 1`] = `"<iframe src=\\"http://localhost/stream.html?assetURL=http%3A%2F%2Flocalhost%2F&initialWidth=0&childId=basic-integration-test-id\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"Talk Embed Stream\\" id=\\"basic-integration-test-id_iframe\\" name=\\"basic-integration-test-id_iframe\\" style=\\"width: 1px; min-width: 100%;\\"></iframe>"`;
|
||||
|
||||
exports[`Basic integration test should use canonical link 1`] = `"<iframe src=\\"http://localhost/stream.html?assetURL=http%3A%2F%2Flocalhost%2Fcanonical&initialWidth=0&childId=basic-integration-test-id\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"Talk Embed Stream\\" name=\\"basic-integration-test-id_iframe\\" style=\\"width: 1px; min-width: 100%;\\"></iframe>"`;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Talk 5.0 – Embed Stream</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0 100px 50px 100px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<a href="/">Default</a> | <a href="/articleButton.html">Article With Button</a>
|
||||
</p>
|
||||
<h1 style="text-align: center">Talk 5.0 – Article</h1>
|
||||
<p>Dismember a mouse and then regurgitate parts of it on the family room floor. Dont wait for the storm to pass,
|
||||
dance in the rain stand in front of the computer screen, so stares at human while pushing stuff off a table chew
|
||||
the plant meow hiss at vacuum cleaner. Terrorize the hundred-and-twenty-pound rottweiler and steal his bed, not
|
||||
sorry chew the plant. Litter kitter kitty litty little kitten big roar roar feed me rub whiskers on bare skin act
|
||||
innocent sleep on keyboard, so give me attention or face the wrath of my claws for demand to be let outside at
|
||||
once, and expect owner to wait for me as i think about it spread kitty litter all over house so nya nya nyan. Catty
|
||||
ipsum massacre a bird in the living room and then look like the cutest and most innocent animal on the planet you
|
||||
have cat to be kitten me right meow. Hiss and stare at nothing then run suddenly away refuse to come home when
|
||||
humans are going to bed; stay out all night then yowl like i am dying at 4am and lick plastic bags. Chase dog then
|
||||
run away purrr purr littel cat, little cat purr purr and step on your keyboard while you're gaming and then turn in
|
||||
a circle . Twitch tail in permanent irritation put butt in owner's face and the dog smells bad yet attempt to leap
|
||||
between furniture but woefully miscalibrate and bellyflop onto the floor; what's your problem? i meant to do that
|
||||
now i shall wash myself intently. Sniff all the things groom forever, stretch tongue and leave it slightly out,
|
||||
blep, but bring your owner a dead bird decide to want nothing to do with my owner today for lay on arms while
|
||||
you're using the keyboard meow meow, i tell my human or scratch. Sleep on my human's head then cats take over the
|
||||
world bleghbleghvomit my furball really tie the room together sleep more napping, more napping all the napping is
|
||||
exhausting. When in doubt, wash drink water out of the faucet, cats are fats i like to pets them they like to meow
|
||||
back and cat dog hate mouse eat string barf pillow no baths hate everything yet swat at dog kitty kitty but you
|
||||
call this cat food. Cough furball into food bowl then scratch owner for a new one flex claws on the human's belly
|
||||
and purr like a lawnmower for has closed eyes but still sees you groom yourself 4 hours - checked, have your beauty
|
||||
sleep 18 hours - checked, be fabulous for the rest of the day - checked. Freak human out make funny noise mow mow
|
||||
mow mow mow mow success now attack human flex claws on the human's belly and purr like a lawnmower or meowwww.
|
||||
Terrorize the hundred-and-twenty-pound rottweiler and steal his bed, not sorry paw at your fat belly so yowling
|
||||
nonstop the whole night small kitty warm kitty little balls of fur or eat owner's food reward the chosen human with
|
||||
a slow blink. Gate keepers of hell plan steps for world domination for more napping, more napping all the napping
|
||||
is exhausting give me some of your food give me some of your food give me some of your food meh, i don't want it so
|
||||
flop over. Make meme, make cute face ears back wide eyed so sit and stare. Dead stare with ears cocked furrier and
|
||||
even more furrier hairball. Stand in front of the computer screen demand to have some of whatever the human is
|
||||
cooking, then sniff the offering and walk away for catasstrophe, kitty scratches couch bad kitty. Wack the mini
|
||||
furry mouse intrigued by the shower, and pooping rainbow while flying in a toasted bread costume in space.
|
||||
Mesmerizing birds love me! shake treat bag, yet lies down where is my slave? I'm getting hungry so lick face hiss
|
||||
at owner, pee a lot, and meow repeatedly scratch at fence purrrrrr eat muffins and poutine until owner comes back.
|
||||
You have cat to be kitten me right meow sniff other cat's butt and hang jaw half open thereafter but run outside as
|
||||
soon as door open so munch on tasty moths or munch on tasty moths, for paw at beetle and eat it before it gets
|
||||
away. Sit on human. Gnaw the corn cob massacre a bird in the living room and then look like the cutest and most
|
||||
innocent animal on the planet for sit on the laptop. Meow scratch leg; meow for can opener to feed me cat fur is
|
||||
the new black but hide when guests come over, and Gate keepers of hell. Refuse to come home when humans are going
|
||||
to bed; stay out all night then yowl like i am dying at 4am cat slap dog in face or eat a rug and furry furry hairs
|
||||
everywhere oh no human coming lie on counter don't get off counter for i like fish sit on human they not getting up
|
||||
ever but meow meow but cuddle no cuddle cuddle love scratch scratch.</p>
|
||||
<p>I show my fluffy belly but it's a trap! if you pet it i will tear up your hand refuse to drink water except out of
|
||||
someone's glass mice, so cough hairball, eat toilet paper or curl into a furry donut lick sellotape but wack the
|
||||
mini furry mouse. When owners are asleep, cry for no apparent reason. Chase imaginary bugs. Stinky cat reward the
|
||||
chosen human with a slow blink, or chase dog then run away. Chew on cable scratch the furniture for you are a
|
||||
captive audience while sitting on the toilet, pet me for i like cats because they are fat and fluffy and spend all
|
||||
night ensuring people don't sleep sleep all day. Scoot butt on the rug need to check on human, have not seen in an
|
||||
hour might be dead oh look, human is alive, hiss at human, feed me, leave fur on owners clothes, so instantly break
|
||||
out into full speed gallop across the house for no reason play riveting piece on synthesizer keyboard and scoot
|
||||
butt on the rug yet meow meow. Attack dog, run away and pretend to be victim annoy the old grumpy cat, start a
|
||||
fight and then retreat to wash when i lose or meow go back to sleep owner brings food and water tries to pet on
|
||||
head, so scratch get sprayed by water because bad cat. Meowwww pelt around the house and up and down stairs chasing
|
||||
phantoms drink water out of the faucet meow meow, i tell my human. Destroy couch.</p>
|
||||
<p>Ask to go outside and ask to come inside and ask to go outside and ask to come inside the dog smells bad. Lick
|
||||
butt and make a weird face. Toilet paper attack claws fluff everywhere meow miao french ciao litterbox. Shake treat
|
||||
bag immediately regret falling into bathtub or white cat sleeps on a black shirt so what a cat-ass-trophy! eat
|
||||
owner's food spit up on light gray carpet instead of adjacent linoleum. Warm up laptop with butt lick butt fart
|
||||
rainbows until owner yells pee in litter box hiss at cats scratch the box so loved it, hated it, loved it, hated it
|
||||
but need to check on human, have not seen in an hour might be dead oh look, human is alive, hiss at human, feed me.
|
||||
</p>
|
||||
<div id="coralStreamEmbed" style="max-width: 640px; margin: 0 auto"></div>
|
||||
<script>
|
||||
const TalkStreamEmbed = Coral.Talk.createStreamEmbed({ id: 'coralStreamEmbed', autoRender: true });
|
||||
window.TalkStreamEmbed = TalkStreamEmbed;
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Talk 5.0 – Embed Stream</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0 100px 50px 100px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p style="text-align: center">
|
||||
<a href="/">Default</a> | <a href="/article.html">Article</a>
|
||||
</p>
|
||||
<h1 style="text-align: center">Talk 5.0 – Article with Button</h1>
|
||||
<p>Dismember a mouse and then regurgitate parts of it on the family room floor. Dont wait for the storm to pass,
|
||||
dance in the rain stand in front of the computer screen, so stares at human while pushing stuff off a table chew
|
||||
the plant meow hiss at vacuum cleaner. Terrorize the hundred-and-twenty-pound rottweiler and steal his bed, not
|
||||
sorry chew the plant. Litter kitter kitty litty little kitten big roar roar feed me rub whiskers on bare skin act
|
||||
innocent sleep on keyboard, so give me attention or face the wrath of my claws for demand to be let outside at
|
||||
once, and expect owner to wait for me as i think about it spread kitty litter all over house so nya nya nyan. Catty
|
||||
ipsum massacre a bird in the living room and then look like the cutest and most innocent animal on the planet you
|
||||
have cat to be kitten me right meow. Hiss and stare at nothing then run suddenly away refuse to come home when
|
||||
humans are going to bed; stay out all night then yowl like i am dying at 4am and lick plastic bags. Chase dog then
|
||||
run away purrr purr littel cat, little cat purr purr and step on your keyboard while you're gaming and then turn in
|
||||
a circle . Twitch tail in permanent irritation put butt in owner's face and the dog smells bad yet attempt to leap
|
||||
between furniture but woefully miscalibrate and bellyflop onto the floor; what's your problem? i meant to do that
|
||||
now i shall wash myself intently. Sniff all the things groom forever, stretch tongue and leave it slightly out,
|
||||
blep, but bring your owner a dead bird decide to want nothing to do with my owner today for lay on arms while
|
||||
you're using the keyboard meow meow, i tell my human or scratch. Sleep on my human's head then cats take over the
|
||||
world bleghbleghvomit my furball really tie the room together sleep more napping, more napping all the napping is
|
||||
exhausting. When in doubt, wash drink water out of the faucet, cats are fats i like to pets them they like to meow
|
||||
back and cat dog hate mouse eat string barf pillow no baths hate everything yet swat at dog kitty kitty but you
|
||||
call this cat food. Cough furball into food bowl then scratch owner for a new one flex claws on the human's belly
|
||||
and purr like a lawnmower for has closed eyes but still sees you groom yourself 4 hours - checked, have your beauty
|
||||
sleep 18 hours - checked, be fabulous for the rest of the day - checked. Freak human out make funny noise mow mow
|
||||
mow mow mow mow success now attack human flex claws on the human's belly and purr like a lawnmower or meowwww.
|
||||
Terrorize the hundred-and-twenty-pound rottweiler and steal his bed, not sorry paw at your fat belly so yowling
|
||||
nonstop the whole night small kitty warm kitty little balls of fur or eat owner's food reward the chosen human with
|
||||
a slow blink. Gate keepers of hell plan steps for world domination for more napping, more napping all the napping
|
||||
is exhausting give me some of your food give me some of your food give me some of your food meh, i don't want it so
|
||||
flop over. Make meme, make cute face ears back wide eyed so sit and stare. Dead stare with ears cocked furrier and
|
||||
even more furrier hairball. Stand in front of the computer screen demand to have some of whatever the human is
|
||||
cooking, then sniff the offering and walk away for catasstrophe, kitty scratches couch bad kitty. Wack the mini
|
||||
furry mouse intrigued by the shower, and pooping rainbow while flying in a toasted bread costume in space.
|
||||
Mesmerizing birds love me! shake treat bag, yet lies down where is my slave? I'm getting hungry so lick face hiss
|
||||
at owner, pee a lot, and meow repeatedly scratch at fence purrrrrr eat muffins and poutine until owner comes back.
|
||||
You have cat to be kitten me right meow sniff other cat's butt and hang jaw half open thereafter but run outside as
|
||||
soon as door open so munch on tasty moths or munch on tasty moths, for paw at beetle and eat it before it gets
|
||||
away. Sit on human. Gnaw the corn cob massacre a bird in the living room and then look like the cutest and most
|
||||
innocent animal on the planet for sit on the laptop. Meow scratch leg; meow for can opener to feed me cat fur is
|
||||
the new black but hide when guests come over, and Gate keepers of hell. Refuse to come home when humans are going
|
||||
to bed; stay out all night then yowl like i am dying at 4am cat slap dog in face or eat a rug and furry furry hairs
|
||||
everywhere oh no human coming lie on counter don't get off counter for i like fish sit on human they not getting up
|
||||
ever but meow meow but cuddle no cuddle cuddle love scratch scratch.</p>
|
||||
<p>I show my fluffy belly but it's a trap! if you pet it i will tear up your hand refuse to drink water except out of
|
||||
someone's glass mice, so cough hairball, eat toilet paper or curl into a furry donut lick sellotape but wack the
|
||||
mini furry mouse. When owners are asleep, cry for no apparent reason. Chase imaginary bugs. Stinky cat reward the
|
||||
chosen human with a slow blink, or chase dog then run away. Chew on cable scratch the furniture for you are a
|
||||
captive audience while sitting on the toilet, pet me for i like cats because they are fat and fluffy and spend all
|
||||
night ensuring people don't sleep sleep all day. Scoot butt on the rug need to check on human, have not seen in an
|
||||
hour might be dead oh look, human is alive, hiss at human, feed me, leave fur on owners clothes, so instantly break
|
||||
out into full speed gallop across the house for no reason play riveting piece on synthesizer keyboard and scoot
|
||||
butt on the rug yet meow meow. Attack dog, run away and pretend to be victim annoy the old grumpy cat, start a
|
||||
fight and then retreat to wash when i lose or meow go back to sleep owner brings food and water tries to pet on
|
||||
head, so scratch get sprayed by water because bad cat. Meowwww pelt around the house and up and down stairs chasing
|
||||
phantoms drink water out of the faucet meow meow, i tell my human. Destroy couch.</p>
|
||||
<p>Ask to go outside and ask to come inside and ask to go outside and ask to come inside the dog smells bad. Lick
|
||||
butt and make a weird face. Toilet paper attack claws fluff everywhere meow miao french ciao litterbox. Shake treat
|
||||
bag immediately regret falling into bathtub or white cat sleeps on a black shirt so what a cat-ass-trophy! eat
|
||||
owner's food spit up on light gray carpet instead of adjacent linoleum. Warm up laptop with butt lick butt fart
|
||||
rainbows until owner yells pee in litter box hiss at cats scratch the box so loved it, hated it, loved it, hated it
|
||||
but need to check on human, have not seen in an hour might be dead oh look, human is alive, hiss at human, feed me.
|
||||
</p>
|
||||
<div id="coralStreamEmbed" style="max-width: 640px; margin: 0 auto"></div>
|
||||
<div style="text-align: center">
|
||||
<button id="showComments">Show Comments</button>
|
||||
</div>
|
||||
<script>
|
||||
const TalkStreamEmbed = Coral.Talk.createStreamEmbed({
|
||||
id: 'coralStreamEmbed',
|
||||
});
|
||||
window.TalkStreamEmbed = TalkStreamEmbed;
|
||||
|
||||
const button = document.getElementById("showComments");
|
||||
|
||||
const showStreamEmbed = () => {
|
||||
TalkStreamEmbed.render();
|
||||
button.parentElement.removeChild(button);
|
||||
};
|
||||
|
||||
button.onclick = showStreamEmbed;
|
||||
TalkStreamEmbed.on("showPermalink", showStreamEmbed);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -9,16 +9,21 @@
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding: 0 0 50px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 style="text-align: center" }>Talk 5.0 – Embed Stream</h1>
|
||||
<p style="text-align: center">
|
||||
<a href="/article.html">Article</a> | <a href="/articleButton.html">Article With Button</a>
|
||||
</p>
|
||||
<h1 style="text-align: center">Talk 5.0 – Embed Stream</h1>
|
||||
<div id="coralStreamEmbed" style="max-width: 640px; margin: 0 auto"></div>
|
||||
<script>
|
||||
window.TalkEmbed = Talk.render(document.getElementById('coralStreamEmbed'));
|
||||
const TalkStreamEmbed = Coral.Talk.createStreamEmbed({ id: 'coralStreamEmbed' });
|
||||
window.TalkStreamEmbed = TalkStreamEmbed;
|
||||
TalkStreamEmbed.render();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import * as Talk from "./";
|
||||
import mockConsole from "jest-mock-console";
|
||||
import * as Coral from "./";
|
||||
|
||||
// tslint:disable:no-console
|
||||
|
||||
describe("Basic integration test", () => {
|
||||
const container: HTMLElement = document.createElement("div");
|
||||
let streamInterface: ReturnType<typeof Talk.render>;
|
||||
beforeAll(() => {
|
||||
container.id = "basic-integration-test-id";
|
||||
document.body.appendChild(container);
|
||||
@@ -11,13 +13,40 @@ describe("Basic integration test", () => {
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
it("should render iframe", () => {
|
||||
streamInterface = Talk.render({
|
||||
mockConsole();
|
||||
const TalkEmbedStream = Coral.Talk.createStreamEmbed({
|
||||
id: "basic-integration-test-id",
|
||||
});
|
||||
TalkEmbedStream.render();
|
||||
expect(container.innerHTML).toMatchSnapshot();
|
||||
expect(console.warn).toHaveBeenCalledTimes(1);
|
||||
expect(console.error).not.toHaveBeenCalled();
|
||||
});
|
||||
it("should use canonical link", () => {
|
||||
mockConsole();
|
||||
const link = document.createElement("link");
|
||||
link.rel = "canonical";
|
||||
link.href = "http://localhost/canonical";
|
||||
document.head.appendChild(link);
|
||||
const TalkEmbedStream = Coral.Talk.createStreamEmbed({
|
||||
id: "basic-integration-test-id",
|
||||
});
|
||||
TalkEmbedStream.render();
|
||||
expect(container.innerHTML).toMatchSnapshot();
|
||||
document.head.removeChild(link);
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
expect(console.error).not.toHaveBeenCalled();
|
||||
});
|
||||
it("should remove iframe", () => {
|
||||
streamInterface.remove();
|
||||
mockConsole();
|
||||
const TalkEmbedStream = Coral.Talk.createStreamEmbed({
|
||||
id: "basic-integration-test-id",
|
||||
});
|
||||
TalkEmbedStream.render();
|
||||
TalkEmbedStream.remove();
|
||||
expect(container.innerHTML).toBe("");
|
||||
// tslint:disable-next-line:no-console
|
||||
expect(console.warn).toHaveBeenCalledTimes(1);
|
||||
expect(console.error).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,32 +1,2 @@
|
||||
import { EventEmitter2 } from "eventemitter2";
|
||||
import qs from "query-string";
|
||||
|
||||
import createStreamInterface from "./Stream";
|
||||
|
||||
export interface Config {
|
||||
assetID?: string;
|
||||
assetURL?: string;
|
||||
commentID?: string;
|
||||
rootURL?: string;
|
||||
id?: string;
|
||||
events?: (eventEmitter: EventEmitter2) => void;
|
||||
}
|
||||
|
||||
export function render(config: Config = {}) {
|
||||
// Parse query params
|
||||
const query = qs.parse(location.search);
|
||||
const eventEmitter = new EventEmitter2({ wildcard: true });
|
||||
|
||||
if (config.events) {
|
||||
config.events(eventEmitter);
|
||||
}
|
||||
|
||||
return createStreamInterface({
|
||||
assetID: config.assetID || query.assetID,
|
||||
assetURL: config.assetURL || query.assetURL,
|
||||
commentID: config.commentID || query.commentID,
|
||||
id: config.id || "talk-embed-stream",
|
||||
rootURL: config.rootURL || location.origin,
|
||||
eventEmitter,
|
||||
});
|
||||
}
|
||||
import * as TalkImport from "./Talk";
|
||||
export const Talk = TalkImport;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
export default function onIntersect(el: HTMLElement, callback: () => void) {
|
||||
if (!IntersectionObserver) {
|
||||
// tslint:disable-next-line:no-console
|
||||
console.warn("IntersectionObserver not available");
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
const options = {
|
||||
rootMargin: "100px",
|
||||
threshold: 1.0,
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
if (entries[0].isIntersecting) {
|
||||
observer.disconnect();
|
||||
callback();
|
||||
}
|
||||
}, options);
|
||||
observer.observe(el);
|
||||
}
|
||||
@@ -2,3 +2,4 @@ export { default as buildURL } from "./buildURL";
|
||||
export { default as ensureEndSlash } from "./ensureEndSlash";
|
||||
export { default as startsWith } from "./startsWith";
|
||||
export { default as prefixStorage } from "./prefixStorage";
|
||||
export { default as parseHashQuery } from "./parseHashQuery";
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import parseHashQuery from "./parseHashQuery";
|
||||
|
||||
it("should parse hash", () => {
|
||||
const testCases: Array<[string, ReturnType<typeof parseHashQuery>]> = [
|
||||
[
|
||||
"#commentID=comment-id",
|
||||
{
|
||||
commentID: "comment-id",
|
||||
},
|
||||
],
|
||||
[
|
||||
"#commentID=comment-id&assetURL=asset-url",
|
||||
{
|
||||
commentID: "comment-id",
|
||||
assetURL: "asset-url",
|
||||
},
|
||||
],
|
||||
["#", {}],
|
||||
["", {}],
|
||||
];
|
||||
testCases.forEach(tc => {
|
||||
expect(parseHashQuery(tc[0])).toEqual(tc[1]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
import qs from "query-string";
|
||||
|
||||
export default function parseQueryHash(hash: string): Record<string, string> {
|
||||
return qs.parse(hash);
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
export { default as buildURL } from "./buildURL";
|
||||
export { default as parseURL } from "./parseURL";
|
||||
export { default as modifyQuery } from "./modifyQuery";
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import modifyQuery from "./modifyQuery";
|
||||
|
||||
it("should modify query", () => {
|
||||
const testCases: Array<[string, Record<string, any>, string]> = [
|
||||
[
|
||||
"http://localhost:8080/?a=b#hash",
|
||||
{
|
||||
c: "d",
|
||||
},
|
||||
"http://localhost:8080/?a=b&c=d#hash",
|
||||
],
|
||||
[
|
||||
"http://localhost:8080/#hash",
|
||||
{
|
||||
a: "b",
|
||||
},
|
||||
"http://localhost:8080/?a=b#hash",
|
||||
],
|
||||
[
|
||||
"http://localhost:8080/?a=b#hash",
|
||||
{
|
||||
a: undefined,
|
||||
},
|
||||
"http://localhost:8080/#hash",
|
||||
],
|
||||
];
|
||||
testCases.forEach(([url, params, expected]) => {
|
||||
expect(modifyQuery(url, params)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import qs from "query-string";
|
||||
|
||||
import buildURL from "./buildURL";
|
||||
import parseURL from "./parseURL";
|
||||
|
||||
export default function modifyQuery(url: string, params: {}) {
|
||||
const parsed = parseURL(url);
|
||||
const query = qs.parse(parsed.search);
|
||||
parsed.search = qs.stringify({ ...query, ...params });
|
||||
return buildURL(parsed);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import parseHashQuery from "./parseHashQuery";
|
||||
|
||||
it("should parse hash", () => {
|
||||
const testCases: Array<[string, ReturnType<typeof parseHashQuery>]> = [
|
||||
[
|
||||
"#commentID=comment-id",
|
||||
{
|
||||
commentID: "comment-id",
|
||||
},
|
||||
],
|
||||
[
|
||||
"#commentID=comment-id&assetURL=asset-url",
|
||||
{
|
||||
commentID: "comment-id",
|
||||
assetURL: "asset-url",
|
||||
},
|
||||
],
|
||||
["#", {}],
|
||||
["", {}],
|
||||
];
|
||||
testCases.forEach(([url, expected]) => {
|
||||
expect(parseHashQuery(url)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
import qs from "query-string";
|
||||
|
||||
export default function parseQueryHash(hash: string): Record<string, string> {
|
||||
return qs.parse(hash);
|
||||
}
|
||||
@@ -42,12 +42,8 @@ export default async function initLocalState(
|
||||
localRecord.setValue(query.assetID, "assetID");
|
||||
}
|
||||
|
||||
// Saving location host for permalink until we get the asset url - the url now points to the tenant
|
||||
if (location && query.assetID) {
|
||||
localRecord.setValue(
|
||||
`${location.origin}/?assetID=${query.assetID}`,
|
||||
"assetURL"
|
||||
);
|
||||
if (query.assetURL) {
|
||||
localRecord.setValue(query.assetURL, "assetURL");
|
||||
}
|
||||
|
||||
if (query.commentID) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import Comment from "./Comment";
|
||||
|
||||
it("renders username and body", () => {
|
||||
const props: PropTypesOf<typeof Comment> = {
|
||||
id: "comment-id",
|
||||
author: {
|
||||
username: "Marvin",
|
||||
},
|
||||
|
||||
@@ -10,6 +10,7 @@ import TopBarLeft from "./TopBarLeft";
|
||||
import Username from "./Username";
|
||||
|
||||
export interface CommentProps {
|
||||
id?: string;
|
||||
className?: string;
|
||||
author: {
|
||||
username: string | null;
|
||||
@@ -28,6 +29,7 @@ const Comment: StatelessComponent<CommentProps> = props => {
|
||||
className={styles.topBar}
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
id={props.id}
|
||||
>
|
||||
<TopBarLeft>
|
||||
{props.author &&
|
||||
|
||||
+1
@@ -8,6 +8,7 @@ exports[`renders username and body 1`] = `
|
||||
<withPropsOnChange(Flex)
|
||||
className="Comment-topBar"
|
||||
direction="row"
|
||||
id="comment-id"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<TopBarLeft>
|
||||
|
||||
@@ -6,6 +6,30 @@
|
||||
border-left: 3px solid var(--palette-grey-darkest);
|
||||
}
|
||||
|
||||
.level2 {
|
||||
padding-left: var(--spacing-unit);
|
||||
margin-left: var(--spacing-unit);
|
||||
border-left: 3px solid var(--palette-grey-dark);
|
||||
}
|
||||
|
||||
.level3 {
|
||||
padding-left: var(--spacing-unit);
|
||||
margin-left: calc(2 * var(--spacing-unit));
|
||||
border-left: 3px solid var(--palette-grey-main);
|
||||
}
|
||||
|
||||
.level4 {
|
||||
padding-left: var(--spacing-unit);
|
||||
margin-left: calc(3 * var(--spacing-unit));
|
||||
border-left: 3px solid var(--palette-grey-light);
|
||||
}
|
||||
|
||||
.level5 {
|
||||
padding-left: var(--spacing-unit);
|
||||
margin-left: calc(4 * var(--spacing-unit));
|
||||
border-left: 3px solid var(--palette-grey-lighter);
|
||||
}
|
||||
|
||||
.noBorder {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@@ -12,13 +12,19 @@ export interface IndentProps {
|
||||
|
||||
const Indent: StatelessComponent<IndentProps> = props => {
|
||||
return (
|
||||
<div
|
||||
className={cn(props.className, styles.root, {
|
||||
[styles.level1]: props.level === 1,
|
||||
[styles.noBorder]: props.noBorder,
|
||||
})}
|
||||
>
|
||||
{props.children}
|
||||
<div className={cn(props.className, styles.root)}>
|
||||
<div
|
||||
className={cn({
|
||||
[styles.level1]: props.level === 1,
|
||||
[styles.level2]: props.level === 2,
|
||||
[styles.level3]: props.level === 3,
|
||||
[styles.level4]: props.level === 4,
|
||||
[styles.level5]: props.level === 5,
|
||||
[styles.noBorder]: props.noBorder,
|
||||
})}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ import PermalinkPopover from "./PermalinkPopover";
|
||||
|
||||
interface PermalinkProps {
|
||||
commentID: string;
|
||||
assetURL: string | null;
|
||||
url: string;
|
||||
}
|
||||
|
||||
class Permalink extends React.Component<PermalinkProps> {
|
||||
@@ -28,7 +28,7 @@ class Permalink extends React.Component<PermalinkProps> {
|
||||
);
|
||||
|
||||
public render() {
|
||||
const { commentID, assetURL } = this.props;
|
||||
const { commentID, url } = this.props;
|
||||
const popoverID = `permalink-popover-${commentID}`;
|
||||
return (
|
||||
<Popover
|
||||
@@ -43,7 +43,7 @@ class Permalink extends React.Component<PermalinkProps> {
|
||||
}
|
||||
>
|
||||
<PermalinkPopover
|
||||
permalinkURL={`${assetURL}&commentID=${commentID}`}
|
||||
permalinkURL={url}
|
||||
toggleVisibility={toggleVisibility}
|
||||
/>
|
||||
</ClickOutside>
|
||||
|
||||
@@ -21,6 +21,17 @@ export interface ReplyListProps {
|
||||
hasMore: boolean;
|
||||
disableShowAll: boolean;
|
||||
indentLevel?: number;
|
||||
ReplyListComponent?: React.ComponentType<any>;
|
||||
}
|
||||
|
||||
function getReplyListElement(
|
||||
{ ReplyListComponent, me, asset }: ReplyListProps,
|
||||
comment: PropTypesOf<typeof CommentContainer>["comment"]
|
||||
) {
|
||||
if (!ReplyListComponent) {
|
||||
return null;
|
||||
}
|
||||
return <ReplyListComponent me={me} comment={comment} asset={asset} />;
|
||||
}
|
||||
|
||||
const ReplyList: StatelessComponent<ReplyListProps> = props => {
|
||||
@@ -30,13 +41,16 @@ const ReplyList: StatelessComponent<ReplyListProps> = props => {
|
||||
role="log"
|
||||
>
|
||||
{props.comments.map(comment => (
|
||||
<CommentContainer
|
||||
key={comment.id}
|
||||
me={props.me}
|
||||
comment={comment}
|
||||
asset={props.asset}
|
||||
indentLevel={props.indentLevel}
|
||||
/>
|
||||
<HorizontalGutter key={comment.id}>
|
||||
<CommentContainer
|
||||
key={comment.id}
|
||||
me={props.me}
|
||||
comment={comment}
|
||||
asset={props.asset}
|
||||
indentLevel={props.indentLevel}
|
||||
/>
|
||||
{getReplyListElement(props, comment)}
|
||||
</HorizontalGutter>
|
||||
))}
|
||||
{props.hasMore && (
|
||||
<Indent level={props.indentLevel} noBorder>
|
||||
|
||||
@@ -4,28 +4,40 @@ exports[`renders level0 1`] = `
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders level1 1`] = `
|
||||
<div
|
||||
className="Indent-root Indent-level1"
|
||||
className="Indent-root"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
<div
|
||||
className="Indent-level1"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders without border 1`] = `
|
||||
<div
|
||||
className="Indent-root Indent-level1 Indent-noBorder"
|
||||
className="Indent-root"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
<div
|
||||
className="Indent-level1 Indent-noBorder"
|
||||
>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
+102
-78
@@ -5,36 +5,44 @@ exports[`renders correctly 1`] = `
|
||||
id="talk-comments-replyList-log--comment-id"
|
||||
role="log"
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
<withPropsOnChange(HorizontalGutter)
|
||||
key="comment-1"
|
||||
me={null}
|
||||
/>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
}
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
indentLevel={1}
|
||||
key="comment-1"
|
||||
me={null}
|
||||
/>
|
||||
</withPropsOnChange(HorizontalGutter)>
|
||||
<withPropsOnChange(HorizontalGutter)
|
||||
key="comment-2"
|
||||
me={null}
|
||||
/>
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
key="comment-2"
|
||||
me={null}
|
||||
/>
|
||||
</withPropsOnChange(HorizontalGutter)>
|
||||
</withPropsOnChange(HorizontalGutter)>
|
||||
`;
|
||||
|
||||
@@ -43,36 +51,44 @@ exports[`when there is more disables load more button 1`] = `
|
||||
id="talk-comments-replyList-log--comment-id"
|
||||
role="log"
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
<withPropsOnChange(HorizontalGutter)
|
||||
key="comment-1"
|
||||
me={null}
|
||||
/>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
}
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
indentLevel={1}
|
||||
key="comment-1"
|
||||
me={null}
|
||||
/>
|
||||
</withPropsOnChange(HorizontalGutter)>
|
||||
<withPropsOnChange(HorizontalGutter)
|
||||
key="comment-2"
|
||||
me={null}
|
||||
/>
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
key="comment-2"
|
||||
me={null}
|
||||
/>
|
||||
</withPropsOnChange(HorizontalGutter)>
|
||||
<Indent
|
||||
level={1}
|
||||
noBorder={true}
|
||||
@@ -100,36 +116,44 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
id="talk-comments-replyList-log--comment-id"
|
||||
role="log"
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
<withPropsOnChange(HorizontalGutter)
|
||||
key="comment-1"
|
||||
me={null}
|
||||
/>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-1",
|
||||
}
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
indentLevel={1}
|
||||
key="comment-1"
|
||||
me={null}
|
||||
/>
|
||||
</withPropsOnChange(HorizontalGutter)>
|
||||
<withPropsOnChange(HorizontalGutter)
|
||||
key="comment-2"
|
||||
me={null}
|
||||
/>
|
||||
>
|
||||
<withContext(createMutationContainer(Relay(CommentContainer)))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
}
|
||||
}
|
||||
comment={
|
||||
Object {
|
||||
"id": "comment-2",
|
||||
}
|
||||
}
|
||||
indentLevel={1}
|
||||
key="comment-2"
|
||||
me={null}
|
||||
/>
|
||||
</withPropsOnChange(HorizontalGutter)>
|
||||
<Indent
|
||||
level={1}
|
||||
noBorder={true}
|
||||
|
||||
@@ -35,7 +35,7 @@ exports[`renders correctly 1`] = `
|
||||
}
|
||||
me={null}
|
||||
/>
|
||||
<Relay(ReplyListContainer)
|
||||
<withProps(Relay(ReplyListContainer))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
@@ -67,7 +67,7 @@ exports[`renders correctly 1`] = `
|
||||
}
|
||||
me={null}
|
||||
/>
|
||||
<Relay(ReplyListContainer)
|
||||
<withProps(Relay(ReplyListContainer))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
@@ -121,7 +121,7 @@ exports[`when there is more disables load more button 1`] = `
|
||||
}
|
||||
me={null}
|
||||
/>
|
||||
<Relay(ReplyListContainer)
|
||||
<withProps(Relay(ReplyListContainer))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
@@ -153,7 +153,7 @@ exports[`when there is more disables load more button 1`] = `
|
||||
}
|
||||
me={null}
|
||||
/>
|
||||
<Relay(ReplyListContainer)
|
||||
<withProps(Relay(ReplyListContainer))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
@@ -221,7 +221,7 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
}
|
||||
me={null}
|
||||
/>
|
||||
<Relay(ReplyListContainer)
|
||||
<withProps(Relay(ReplyListContainer))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
@@ -253,7 +253,7 @@ exports[`when there is more renders a load more button 1`] = `
|
||||
}
|
||||
me={null}
|
||||
/>
|
||||
<Relay(ReplyListContainer)
|
||||
<withProps(Relay(ReplyListContainer))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
@@ -323,7 +323,7 @@ exports[`when use is logged in renders correctly 1`] = `
|
||||
}
|
||||
me={Object {}}
|
||||
/>
|
||||
<Relay(ReplyListContainer)
|
||||
<withProps(Relay(ReplyListContainer))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
@@ -355,7 +355,7 @@ exports[`when use is logged in renders correctly 1`] = `
|
||||
}
|
||||
me={Object {}}
|
||||
/>
|
||||
<Relay(ReplyListContainer)
|
||||
<withProps(Relay(ReplyListContainer))
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
|
||||
@@ -120,6 +120,7 @@ export class CommentContainer extends Component<InnerProps, State> {
|
||||
return (
|
||||
<>
|
||||
<Comment
|
||||
id={`comment-${comment.id}`}
|
||||
indentLevel={indentLevel}
|
||||
author={comment.author}
|
||||
body={comment.body}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { StatelessComponent } from "react";
|
||||
import { graphql } from "react-relay";
|
||||
import { withLocalStateContainer } from "talk-framework/lib/relay";
|
||||
import { modifyQuery } from "talk-framework/utils";
|
||||
import { PermalinkButtonContainerLocal as Local } from "talk-stream/__generated__/PermalinkButtonContainerLocal.graphql";
|
||||
|
||||
import PermalinkButton from "../components/PermalinkButton";
|
||||
@@ -15,7 +16,10 @@ export const PermalinkContainer: StatelessComponent<InnerProps> = ({
|
||||
commentID,
|
||||
}) => {
|
||||
return local.assetURL ? (
|
||||
<PermalinkButton assetURL={local.assetURL} commentID={commentID} />
|
||||
<PermalinkButton
|
||||
commentID={commentID}
|
||||
url={modifyQuery(local.assetURL, { commentID })}
|
||||
/>
|
||||
) : null;
|
||||
};
|
||||
|
||||
|
||||
@@ -40,6 +40,18 @@ class PermalinkViewContainer extends React.Component<
|
||||
// Remove the commentId url param.
|
||||
return buildURL({ ...urlParts, search });
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
if (this.props.pym) {
|
||||
const scrollTo = this.props.comment
|
||||
? document
|
||||
.getElementById(`comment-${this.props.comment.id}`)!
|
||||
.getBoundingClientRect().top + window.pageYOffset
|
||||
: 50;
|
||||
setTimeout(() => this.props.pym!.scrollParentToChildPos(scrollTo), 100);
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { comment, asset, me } = this.props;
|
||||
return (
|
||||
@@ -66,6 +78,7 @@ const enhanced = withContext(ctx => ({
|
||||
`,
|
||||
comment: graphql`
|
||||
fragment PermalinkViewContainer_comment on Comment {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -27,6 +27,8 @@ it("renders correctly", () => {
|
||||
isLoading: noop,
|
||||
} as any,
|
||||
me: null,
|
||||
indentLevel: 1,
|
||||
ReplyListComponent: () => null,
|
||||
};
|
||||
const wrapper = shallow(<ReplyListContainerN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
@@ -46,6 +48,8 @@ it("renders correctly when replies are null", () => {
|
||||
isLoading: noop,
|
||||
} as any,
|
||||
me: null,
|
||||
indentLevel: 1,
|
||||
ReplyListComponent: undefined,
|
||||
};
|
||||
const wrapper = shallow(<ReplyListContainerN {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
@@ -69,6 +73,8 @@ describe("when has more replies", () => {
|
||||
loadMore: (_: any, callback: () => void) => (finishLoading = callback),
|
||||
} as any,
|
||||
me: null,
|
||||
indentLevel: 1,
|
||||
ReplyListComponent: undefined,
|
||||
};
|
||||
|
||||
let wrapper: ShallowWrapper;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import React from "react";
|
||||
import { graphql, RelayPaginationProp } from "react-relay";
|
||||
import { graphql, GraphQLTaggedNode, RelayPaginationProp } from "react-relay";
|
||||
import { withProps } from "recompose";
|
||||
|
||||
import { withPaginationContainer } from "talk-framework/lib/relay";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
import { ReplyListContainer_asset as AssetData } from "talk-stream/__generated__/ReplyListContainer_asset.graphql";
|
||||
import { ReplyListContainer_comment as CommentData } from "talk-stream/__generated__/ReplyListContainer_comment.graphql";
|
||||
import { ReplyListContainer_me as MeData } from "talk-stream/__generated__/ReplyListContainer_me.graphql";
|
||||
import { ReplyListContainer1_asset as AssetData } from "talk-stream/__generated__/ReplyListContainer1_asset.graphql";
|
||||
import { ReplyListContainer1_comment as CommentData } from "talk-stream/__generated__/ReplyListContainer1_comment.graphql";
|
||||
import { ReplyListContainer1_me as MeData } from "talk-stream/__generated__/ReplyListContainer1_me.graphql";
|
||||
import {
|
||||
COMMENT_SORT,
|
||||
ReplyListContainerPaginationQueryVariables,
|
||||
} from "talk-stream/__generated__/ReplyListContainerPaginationQuery.graphql";
|
||||
ReplyListContainer1PaginationQueryVariables,
|
||||
} from "talk-stream/__generated__/ReplyListContainer1PaginationQuery.graphql";
|
||||
|
||||
import ReplyList from "../components/ReplyList";
|
||||
|
||||
@@ -18,8 +18,16 @@ export interface InnerProps {
|
||||
asset: AssetData;
|
||||
comment: CommentData;
|
||||
relay: RelayPaginationProp;
|
||||
indentLevel: number;
|
||||
ReplyListComponent: React.ComponentType<any> | undefined;
|
||||
}
|
||||
|
||||
// TODO: (cvle) This should be autogenerated.
|
||||
interface FragmentVariables {
|
||||
count: number;
|
||||
cursor?: string;
|
||||
orderBy: COMMENT_SORT;
|
||||
}
|
||||
export class ReplyListContainer extends React.Component<InnerProps> {
|
||||
public state = {
|
||||
disableShowAll: false,
|
||||
@@ -42,7 +50,8 @@ export class ReplyListContainer extends React.Component<InnerProps> {
|
||||
onShowAll={this.showAll}
|
||||
hasMore={this.props.relay.hasMore()}
|
||||
disableShowAll={this.state.disableShowAll}
|
||||
indentLevel={1}
|
||||
indentLevel={this.props.indentLevel}
|
||||
ReplyListComponent={this.props.ReplyListComponent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -66,31 +75,61 @@ export class ReplyListContainer extends React.Component<InnerProps> {
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: (cvle) This should be autogenerated.
|
||||
interface FragmentVariables {
|
||||
count: number;
|
||||
cursor?: string;
|
||||
orderBy: COMMENT_SORT;
|
||||
function createReplyListContainer(
|
||||
indentLevel: number,
|
||||
fragments: {
|
||||
me: GraphQLTaggedNode;
|
||||
asset: GraphQLTaggedNode;
|
||||
comment: GraphQLTaggedNode;
|
||||
},
|
||||
query: GraphQLTaggedNode,
|
||||
ReplyListComponent?: React.ComponentType<any>
|
||||
) {
|
||||
return withProps({ indentLevel, ReplyListComponent })(
|
||||
withPaginationContainer<
|
||||
InnerProps,
|
||||
ReplyListContainer1PaginationQueryVariables,
|
||||
FragmentVariables
|
||||
>(fragments, {
|
||||
direction: "forward",
|
||||
getConnectionFromProps(props) {
|
||||
return props.comment && props.comment.replies;
|
||||
},
|
||||
// This is also the default implementation of `getFragmentVariables` if it isn't provided.
|
||||
getFragmentVariables(prevVars, totalCount) {
|
||||
return {
|
||||
...prevVars,
|
||||
count: totalCount,
|
||||
};
|
||||
},
|
||||
getVariables(props, { count, cursor }, fragmentVariables) {
|
||||
return {
|
||||
count,
|
||||
cursor,
|
||||
orderBy: fragmentVariables.orderBy,
|
||||
commentID: props.comment.id,
|
||||
};
|
||||
},
|
||||
query,
|
||||
})(ReplyListContainer)
|
||||
);
|
||||
}
|
||||
|
||||
const enhanced = withPaginationContainer<
|
||||
InnerProps,
|
||||
ReplyListContainerPaginationQueryVariables,
|
||||
FragmentVariables
|
||||
>(
|
||||
const ReplyListContainer5 = createReplyListContainer(
|
||||
5,
|
||||
{
|
||||
me: graphql`
|
||||
fragment ReplyListContainer_me on User {
|
||||
fragment ReplyListContainer5_me on User {
|
||||
...CommentContainer_me
|
||||
}
|
||||
`,
|
||||
asset: graphql`
|
||||
fragment ReplyListContainer_asset on Asset {
|
||||
fragment ReplyListContainer5_asset on Asset {
|
||||
...CommentContainer_asset
|
||||
}
|
||||
`,
|
||||
comment: graphql`
|
||||
fragment ReplyListContainer_comment on Comment
|
||||
fragment ReplyListContainer5_comment on Comment
|
||||
@argumentDefinitions(
|
||||
count: { type: "Int!", defaultValue: 5 }
|
||||
cursor: { type: "Cursor" }
|
||||
@@ -109,43 +148,237 @@ const enhanced = withPaginationContainer<
|
||||
}
|
||||
`,
|
||||
},
|
||||
graphql`
|
||||
# Pagination query to be fetched upon calling 'loadMore'.
|
||||
# Notice that we re-use our fragment, and the shape of this query matches our fragment spec.
|
||||
query ReplyListContainer5PaginationQuery(
|
||||
$count: Int!
|
||||
$cursor: Cursor
|
||||
$orderBy: COMMENT_SORT!
|
||||
$commentID: ID!
|
||||
) {
|
||||
comment(id: $commentID) {
|
||||
...ReplyListContainer5_comment
|
||||
@arguments(count: $count, cursor: $cursor, orderBy: $orderBy)
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
const ReplyListContainer4 = createReplyListContainer(
|
||||
4,
|
||||
{
|
||||
direction: "forward",
|
||||
getConnectionFromProps(props) {
|
||||
return props.comment && props.comment.replies;
|
||||
},
|
||||
// This is also the default implementation of `getFragmentVariables` if it isn't provided.
|
||||
getFragmentVariables(prevVars, totalCount) {
|
||||
return {
|
||||
...prevVars,
|
||||
count: totalCount,
|
||||
};
|
||||
},
|
||||
getVariables(props, { count, cursor }, fragmentVariables) {
|
||||
return {
|
||||
count,
|
||||
cursor,
|
||||
orderBy: fragmentVariables.orderBy,
|
||||
commentID: props.comment.id,
|
||||
};
|
||||
},
|
||||
query: graphql`
|
||||
# Pagination query to be fetched upon calling 'loadMore'.
|
||||
# Notice that we re-use our fragment, and the shape of this query matches our fragment spec.
|
||||
query ReplyListContainerPaginationQuery(
|
||||
$count: Int!
|
||||
$cursor: Cursor
|
||||
$orderBy: COMMENT_SORT!
|
||||
$commentID: ID!
|
||||
) {
|
||||
comment(id: $commentID) {
|
||||
...ReplyListContainer_comment
|
||||
@arguments(count: $count, cursor: $cursor, orderBy: $orderBy)
|
||||
me: graphql`
|
||||
fragment ReplyListContainer4_me on User {
|
||||
...ReplyListContainer5_me
|
||||
...CommentContainer_me
|
||||
}
|
||||
`,
|
||||
asset: graphql`
|
||||
fragment ReplyListContainer4_asset on Asset {
|
||||
...ReplyListContainer5_asset
|
||||
...CommentContainer_asset
|
||||
}
|
||||
`,
|
||||
comment: graphql`
|
||||
fragment ReplyListContainer4_comment on Comment
|
||||
@argumentDefinitions(
|
||||
count: { type: "Int!", defaultValue: 5 }
|
||||
cursor: { type: "Cursor" }
|
||||
orderBy: { type: "COMMENT_SORT!", defaultValue: CREATED_AT_ASC }
|
||||
) {
|
||||
id
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...ReplyListContainer5_comment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
}
|
||||
)(ReplyListContainer);
|
||||
},
|
||||
graphql`
|
||||
# Pagination query to be fetched upon calling 'loadMore'.
|
||||
# Notice that we re-use our fragment, and the shape of this query matches our fragment spec.
|
||||
query ReplyListContainer4PaginationQuery(
|
||||
$count: Int!
|
||||
$cursor: Cursor
|
||||
$orderBy: COMMENT_SORT!
|
||||
$commentID: ID!
|
||||
) {
|
||||
comment(id: $commentID) {
|
||||
...ReplyListContainer4_comment
|
||||
@arguments(count: $count, cursor: $cursor, orderBy: $orderBy)
|
||||
}
|
||||
}
|
||||
`,
|
||||
ReplyListContainer5
|
||||
);
|
||||
|
||||
export type ReplyListContainerProps = PropTypesOf<typeof enhanced>;
|
||||
export default enhanced;
|
||||
const ReplyListContainer3 = createReplyListContainer(
|
||||
3,
|
||||
{
|
||||
me: graphql`
|
||||
fragment ReplyListContainer3_me on User {
|
||||
...ReplyListContainer4_me
|
||||
...CommentContainer_me
|
||||
}
|
||||
`,
|
||||
asset: graphql`
|
||||
fragment ReplyListContainer3_asset on Asset {
|
||||
...ReplyListContainer4_asset
|
||||
...CommentContainer_asset
|
||||
}
|
||||
`,
|
||||
comment: graphql`
|
||||
fragment ReplyListContainer3_comment on Comment
|
||||
@argumentDefinitions(
|
||||
count: { type: "Int!", defaultValue: 5 }
|
||||
cursor: { type: "Cursor" }
|
||||
orderBy: { type: "COMMENT_SORT!", defaultValue: CREATED_AT_ASC }
|
||||
) {
|
||||
id
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...ReplyListContainer4_comment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
graphql`
|
||||
# Pagination query to be fetched upon calling 'loadMore'.
|
||||
# Notice that we re-use our fragment, and the shape of this query matches our fragment spec.
|
||||
query ReplyListContainer3PaginationQuery(
|
||||
$count: Int!
|
||||
$cursor: Cursor
|
||||
$orderBy: COMMENT_SORT!
|
||||
$commentID: ID!
|
||||
) {
|
||||
comment(id: $commentID) {
|
||||
...ReplyListContainer3_comment
|
||||
@arguments(count: $count, cursor: $cursor, orderBy: $orderBy)
|
||||
}
|
||||
}
|
||||
`,
|
||||
ReplyListContainer4
|
||||
);
|
||||
|
||||
const ReplyListContainer2 = createReplyListContainer(
|
||||
2,
|
||||
{
|
||||
me: graphql`
|
||||
fragment ReplyListContainer2_me on User {
|
||||
...ReplyListContainer3_me
|
||||
...CommentContainer_me
|
||||
}
|
||||
`,
|
||||
asset: graphql`
|
||||
fragment ReplyListContainer2_asset on Asset {
|
||||
...ReplyListContainer3_asset
|
||||
...CommentContainer_asset
|
||||
}
|
||||
`,
|
||||
comment: graphql`
|
||||
fragment ReplyListContainer2_comment on Comment
|
||||
@argumentDefinitions(
|
||||
count: { type: "Int!", defaultValue: 5 }
|
||||
cursor: { type: "Cursor" }
|
||||
orderBy: { type: "COMMENT_SORT!", defaultValue: CREATED_AT_ASC }
|
||||
) {
|
||||
id
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...ReplyListContainer3_comment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
graphql`
|
||||
# Pagination query to be fetched upon calling 'loadMore'.
|
||||
# Notice that we re-use our fragment, and the shape of this query matches our fragment spec.
|
||||
query ReplyListContainer2PaginationQuery(
|
||||
$count: Int!
|
||||
$cursor: Cursor
|
||||
$orderBy: COMMENT_SORT!
|
||||
$commentID: ID!
|
||||
) {
|
||||
comment(id: $commentID) {
|
||||
...ReplyListContainer2_comment
|
||||
@arguments(count: $count, cursor: $cursor, orderBy: $orderBy)
|
||||
}
|
||||
}
|
||||
`,
|
||||
ReplyListContainer3
|
||||
);
|
||||
|
||||
const ReplyListContainer1 = createReplyListContainer(
|
||||
1,
|
||||
{
|
||||
me: graphql`
|
||||
fragment ReplyListContainer1_me on User {
|
||||
...ReplyListContainer2_me
|
||||
...CommentContainer_me
|
||||
}
|
||||
`,
|
||||
asset: graphql`
|
||||
fragment ReplyListContainer1_asset on Asset {
|
||||
...ReplyListContainer2_asset
|
||||
...CommentContainer_asset
|
||||
}
|
||||
`,
|
||||
comment: graphql`
|
||||
fragment ReplyListContainer1_comment on Comment
|
||||
@argumentDefinitions(
|
||||
count: { type: "Int!", defaultValue: 5 }
|
||||
cursor: { type: "Cursor" }
|
||||
orderBy: { type: "COMMENT_SORT!", defaultValue: CREATED_AT_ASC }
|
||||
) {
|
||||
id
|
||||
replies(first: $count, after: $cursor, orderBy: $orderBy)
|
||||
@connection(key: "ReplyList_replies") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...ReplyListContainer2_comment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
graphql`
|
||||
# Pagination query to be fetched upon calling 'loadMore'.
|
||||
# Notice that we re-use our fragment, and the shape of this query matches our fragment spec.
|
||||
query ReplyListContainer1PaginationQuery(
|
||||
$count: Int!
|
||||
$cursor: Cursor
|
||||
$orderBy: COMMENT_SORT!
|
||||
$commentID: ID!
|
||||
) {
|
||||
comment(id: $commentID) {
|
||||
...ReplyListContainer1_comment
|
||||
@arguments(count: $count, cursor: $cursor, orderBy: $orderBy)
|
||||
}
|
||||
}
|
||||
`,
|
||||
ReplyListContainer2
|
||||
);
|
||||
|
||||
export default ReplyListContainer1;
|
||||
|
||||
@@ -23,7 +23,7 @@ graphql`
|
||||
fragment StreamContainer_comment on Comment {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...ReplyListContainer_comment
|
||||
...ReplyListContainer1_comment
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -95,12 +95,12 @@ const enhanced = withPaginationContainer<
|
||||
}
|
||||
}
|
||||
...CommentContainer_asset
|
||||
...ReplyListContainer_asset
|
||||
...ReplyListContainer1_asset
|
||||
}
|
||||
`,
|
||||
me: graphql`
|
||||
fragment StreamContainer_me on User {
|
||||
...ReplyListContainer_me
|
||||
...ReplyListContainer1_me
|
||||
...CommentContainer_me
|
||||
...UserBoxContainer_me
|
||||
}
|
||||
@@ -135,7 +135,7 @@ const enhanced = withPaginationContainer<
|
||||
$count: Int!
|
||||
$cursor: Cursor
|
||||
$orderBy: COMMENT_SORT!
|
||||
$assetID: ID!
|
||||
$assetID: ID
|
||||
) {
|
||||
asset(id: $assetID) {
|
||||
...StreamContainer_asset
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ exports[`renders body only 1`] = `
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
id="comment-comment-id"
|
||||
indentLevel={1}
|
||||
showEditedMarker={false}
|
||||
/>
|
||||
@@ -54,6 +55,7 @@ exports[`renders username and body 1`] = `
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
id="comment-comment-id"
|
||||
indentLevel={1}
|
||||
showEditedMarker={false}
|
||||
/>
|
||||
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<ReplyList
|
||||
ReplyListComponent={[Function]}
|
||||
asset={
|
||||
Object {
|
||||
"id": "asset-id",
|
||||
|
||||
@@ -45,15 +45,19 @@ export const render = ({
|
||||
};
|
||||
|
||||
const PermalinkViewQuery: StatelessComponent<InnerProps> = ({
|
||||
local: { commentID, assetID },
|
||||
local: { commentID, assetID, assetURL },
|
||||
}) => (
|
||||
<QueryRenderer<QueryTypes>
|
||||
query={graphql`
|
||||
query PermalinkViewQuery($commentID: ID!, $assetID: ID!) {
|
||||
query PermalinkViewQuery(
|
||||
$commentID: ID!
|
||||
$assetID: ID
|
||||
$assetURL: String
|
||||
) {
|
||||
me {
|
||||
...PermalinkViewContainer_me
|
||||
}
|
||||
asset(id: $assetID) {
|
||||
asset(id: $assetID, url: $assetURL) {
|
||||
...PermalinkViewContainer_asset
|
||||
}
|
||||
comment(id: $commentID) {
|
||||
@@ -62,8 +66,9 @@ const PermalinkViewQuery: StatelessComponent<InnerProps> = ({
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
assetID: assetID!,
|
||||
commentID: commentID!,
|
||||
assetID,
|
||||
assetURL,
|
||||
}}
|
||||
render={render}
|
||||
/>
|
||||
@@ -74,6 +79,7 @@ const enhanced = withLocalStateContainer(
|
||||
fragment PermalinkViewQueryLocal on Local {
|
||||
assetID
|
||||
commentID
|
||||
assetURL
|
||||
}
|
||||
`
|
||||
)(PermalinkViewQuery);
|
||||
|
||||
@@ -38,21 +38,22 @@ export const render = ({
|
||||
};
|
||||
|
||||
const StreamQuery: StatelessComponent<InnerProps> = ({
|
||||
local: { assetID },
|
||||
local: { assetID, assetURL },
|
||||
}) => (
|
||||
<QueryRenderer<QueryTypes>
|
||||
query={graphql`
|
||||
query StreamQuery($assetID: ID!) {
|
||||
query StreamQuery($assetID: ID, $assetURL: String) {
|
||||
me {
|
||||
...StreamContainer_me
|
||||
}
|
||||
asset(id: $assetID) {
|
||||
asset(id: $assetID, url: $assetURL) {
|
||||
...StreamContainer_asset
|
||||
}
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
assetID: assetID!,
|
||||
assetID,
|
||||
assetURL,
|
||||
}}
|
||||
render={render}
|
||||
/>
|
||||
@@ -62,6 +63,7 @@ const enhanced = withLocalStateContainer(
|
||||
graphql`
|
||||
fragment StreamQueryLocal on Local {
|
||||
assetID
|
||||
assetURL
|
||||
}
|
||||
`
|
||||
)(StreamQuery);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -152,60 +152,65 @@ exports[`loads more comments 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -217,60 +222,65 @@ exports[`loads more comments 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-1"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -282,60 +292,65 @@ exports[`loads more comments 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-2"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Isabelle
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:14:00.000Z"
|
||||
title="2018-07-06T18:14:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:14:00.000Z
|
||||
</time>
|
||||
Isabelle
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:14:00.000Z"
|
||||
title="2018-07-06T18:14:00.000Z"
|
||||
>
|
||||
2018-07-06T18:14:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Hey!",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Hey!",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-2"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-2"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -497,60 +512,65 @@ exports[`renders comment stream 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -562,60 +582,65 @@ exports[`renders comment stream 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-1"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -27,60 +27,65 @@ exports[`renders permalink view 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -240,60 +245,65 @@ exports[`show all comments 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+47
-42
@@ -184,60 +184,65 @@ exports[`show all comments 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -185,36 +185,67 @@ exports[`post a comment: optimistic response 1`] = `
|
||||
className="IndentedComment-blur Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-uuid-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
<div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
id="comments-commentContainer-editButton-uuid-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<strong>Hello world!</strong>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
|
||||
id="comments-commentContainer-editButton-uuid-0"
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-uuid-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
@@ -224,37 +255,81 @@ exports[`post a comment: optimistic response 1`] = `
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Edit
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<strong>Hello world!</strong>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-uuid-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,125 +341,65 @@ exports[`post a comment: optimistic response 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-1"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -585,60 +600,65 @@ exports[`post a comment: server response 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-x"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<strong>Hello world! (from server)</strong>",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<strong>Hello world! (from server)</strong>",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-x"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-x"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -650,60 +670,65 @@ exports[`post a comment: server response 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -715,60 +740,65 @@ exports[`post a comment: server response 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-1"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -969,60 +999,65 @@ exports[`renders comment stream 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1034,60 +1069,65 @@ exports[`renders comment stream 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-1"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -152,135 +152,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "I like yoghurt",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-with-replies"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-replyList-log--comment-with-replies"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="Indent-root Indent-level1"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
@@ -288,6 +160,7 @@ exports[`renders comment stream 1`] = `
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
@@ -340,8 +213,16 @@ exports[`renders comment stream 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Indent-root Indent-level1"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
@@ -349,6 +230,7 @@ exports[`renders comment stream 1`] = `
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-with-deep-replies"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
@@ -356,17 +238,17 @@ exports[`renders comment stream 1`] = `
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
@@ -375,7 +257,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
"__html": "I like yoghurt",
|
||||
}
|
||||
}
|
||||
/>
|
||||
@@ -384,7 +266,7 @@ exports[`renders comment stream 1`] = `
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
id="comments-commentContainer-replyButton-comment-with-deep-replies"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
@@ -402,6 +284,298 @@ exports[`renders comment stream 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-replyList-log--comment-with-deep-replies"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Indent-level1"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-with-replies"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "I like yoghurt",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-with-replies"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-replyList-log--comment-with-replies"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Indent-level2"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-3"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Isabelle
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:14:00.000Z"
|
||||
title="2018-07-06T18:14:00.000Z"
|
||||
>
|
||||
2018-07-06T18:14:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Comment Body 3",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-3"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Indent-level2"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-4"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Isabelle
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:14:00.000Z"
|
||||
title="2018-07-06T18:14:00.000Z"
|
||||
>
|
||||
2018-07-06T18:14:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Comment Body 4",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-4"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Indent-level1"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-5"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Isabelle
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:14:00.000Z"
|
||||
title="2018-07-06T18:14:00.000Z"
|
||||
>
|
||||
2018-07-06T18:14:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Comment Body 5",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-5"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -152,60 +152,65 @@ exports[`renders comment stream 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -217,60 +222,65 @@ exports[`renders comment stream 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-1"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -152,70 +152,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-replyList-log--comment-0"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="Indent-root Indent-level1"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
@@ -223,6 +160,7 @@ exports[`renders comment stream 1`] = `
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
@@ -230,17 +168,17 @@ exports[`renders comment stream 1`] = `
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
@@ -249,7 +187,7 @@ exports[`renders comment stream 1`] = `
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
@@ -258,7 +196,7 @@ exports[`renders comment stream 1`] = `
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
@@ -275,25 +213,105 @@ exports[`renders comment stream 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-replyList-log--comment-0"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="Indent-root Indent-level1 Indent-noBorder"
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<button
|
||||
aria-controls="talk-comments-replyList-log--comment-0"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorRegular Button-variantOutlined Button-fullWidth"
|
||||
disabled={false}
|
||||
id="talk-comments-replyList-showAll--comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
Show All
|
||||
</button>
|
||||
<div
|
||||
className="Indent-level1"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-1"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Indent-level1 Indent-noBorder"
|
||||
>
|
||||
<button
|
||||
aria-controls="talk-comments-replyList-log--comment-0"
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorRegular Button-variantOutlined Button-fullWidth"
|
||||
disabled={false}
|
||||
id="talk-comments-replyList-showAll--comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Show All
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -454,60 +472,65 @@ exports[`show all replies 1`] = `
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-0"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
Markus
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-0"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -517,125 +540,143 @@ exports[`show all replies 1`] = `
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="Indent-root Indent-level1"
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Indent-level1"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-1"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<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>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-1"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="Indent-root Indent-level1"
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
className="Indent-root"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
className="Indent-level1"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Isabelle
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
|
||||
id="comment-comment-2"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:14:00.000Z"
|
||||
title="2018-07-06T18:14:00.000Z"
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
2018-07-06T18:14:00.000Z
|
||||
</time>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Isabelle
|
||||
</span>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
|
||||
>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:14:00.000Z"
|
||||
title="2018-07-06T18:14:00.000Z"
|
||||
>
|
||||
2018-07-06T18:14:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Hey!",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-2"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Hey!",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
|
||||
id="comments-commentContainer-replyButton-comment-2"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Reply
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,10 @@ function createTestRenderer() {
|
||||
Query: {
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assets[0].id }).returns(assets[0])
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, { id: assets[0].id, url: null })
|
||||
.returns(assets[0])
|
||||
),
|
||||
me: createSinonStub(
|
||||
s => s.throws(),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ReactTestRenderer } from "react-test-renderer";
|
||||
import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
@@ -55,7 +56,15 @@ beforeEach(() => {
|
||||
Query: {
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assetStub.id }).returns(assetStub)
|
||||
s =>
|
||||
s
|
||||
.withArgs(
|
||||
undefined,
|
||||
sinon
|
||||
.match({ id: assetStub.id, url: null })
|
||||
.or(sinon.match({ id: assetStub.id }))
|
||||
)
|
||||
.returns(assetStub)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -36,7 +36,10 @@ beforeEach(() => {
|
||||
),
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assetStub.id }).returns(assetStub)
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, { id: assetStub.id, url: null })
|
||||
.returns(assetStub)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -33,7 +33,10 @@ beforeEach(() => {
|
||||
comment: () => null,
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assetStub.id }).returns(assetStub)
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, { id: assetStub.id, url: null })
|
||||
.returns(assetStub)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ReactTestRenderer } from "react-test-renderer";
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
|
||||
import { assetWithReplies } from "../fixtures";
|
||||
import { assetWithDeepReplies } from "../fixtures";
|
||||
import create from "./create";
|
||||
|
||||
let testRenderer: ReactTestRenderer;
|
||||
@@ -14,8 +14,8 @@ beforeEach(() => {
|
||||
s => s.throws(),
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, { id: assetWithReplies.id })
|
||||
.returns(assetWithReplies)
|
||||
.withArgs(undefined, { id: assetWithDeepReplies.id, url: null })
|
||||
.returns(assetWithDeepReplies)
|
||||
),
|
||||
},
|
||||
};
|
||||
@@ -25,7 +25,7 @@ beforeEach(() => {
|
||||
logNetwork: false,
|
||||
resolvers,
|
||||
initLocalState: localRecord => {
|
||||
localRecord.setValue(assetWithReplies.id, "assetID");
|
||||
localRecord.setValue(assetWithDeepReplies.id, "assetID");
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -12,7 +12,10 @@ beforeEach(() => {
|
||||
Query: {
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assets[0].id }).returns(assets[0])
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, { id: assets[0].id, url: null })
|
||||
.returns(assets[0])
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -71,7 +71,10 @@ beforeEach(() => {
|
||||
),
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assetStub.id }).returns(assetStub)
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, { id: assetStub.id, url: null })
|
||||
.returns(assetStub)
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -47,6 +47,39 @@ export const comments = [
|
||||
editableUntil: "2018-07-06T18:14:30.000Z",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "comment-3",
|
||||
author: users[2],
|
||||
body: "Comment Body 3",
|
||||
createdAt: "2018-07-06T18:14:00.000Z",
|
||||
replies: { edges: [], pageInfo: { endCursor: null, hasNextPage: false } },
|
||||
editing: {
|
||||
edited: false,
|
||||
editableUntil: "2018-07-06T18:14:30.000Z",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "comment-4",
|
||||
author: users[2],
|
||||
body: "Comment Body 4",
|
||||
createdAt: "2018-07-06T18:14:00.000Z",
|
||||
replies: { edges: [], pageInfo: { endCursor: null, hasNextPage: false } },
|
||||
editing: {
|
||||
edited: false,
|
||||
editableUntil: "2018-07-06T18:14:30.000Z",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "comment-5",
|
||||
author: users[2],
|
||||
body: "Comment Body 5",
|
||||
createdAt: "2018-07-06T18:14:00.000Z",
|
||||
replies: { edges: [], pageInfo: { endCursor: null, hasNextPage: false } },
|
||||
editing: {
|
||||
edited: false,
|
||||
editableUntil: "2018-07-06T18:14:30.000Z",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const assets = [
|
||||
@@ -73,8 +106,28 @@ export const commentWithReplies = {
|
||||
createdAt: "2018-07-06T18:24:00.000Z",
|
||||
replies: {
|
||||
edges: [
|
||||
{ node: comments[0], cursor: comments[0].createdAt },
|
||||
{ node: comments[1], cursor: comments[1].createdAt },
|
||||
{ node: comments[3], cursor: comments[3].createdAt },
|
||||
{ node: comments[4], cursor: comments[4].createdAt },
|
||||
],
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
},
|
||||
},
|
||||
editing: {
|
||||
edited: false,
|
||||
editableUntil: "2018-07-06T18:24:30.000Z",
|
||||
},
|
||||
};
|
||||
|
||||
export const commentWithDeepReplies = {
|
||||
id: "comment-with-deep-replies",
|
||||
author: users[0],
|
||||
body: "I like yoghurt",
|
||||
createdAt: "2018-07-06T18:24:00.000Z",
|
||||
replies: {
|
||||
edges: [
|
||||
{ node: commentWithReplies, cursor: commentWithReplies.createdAt },
|
||||
{ node: comments[5], cursor: comments[5].createdAt },
|
||||
],
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
@@ -100,3 +153,21 @@ export const assetWithReplies = {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const assetWithDeepReplies = {
|
||||
id: "asset-with-deep-replies",
|
||||
url: "http://localhost/assets/asset-with-replies",
|
||||
isClosed: false,
|
||||
comments: {
|
||||
edges: [
|
||||
{ node: comments[0], cursor: comments[0].createdAt },
|
||||
{
|
||||
node: commentWithDeepReplies,
|
||||
cursor: commentWithDeepReplies.createdAt,
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
// Automatically unmock console.
|
||||
import "jest-mock-console/dist/setupTestFramework";
|
||||
@@ -4,65 +4,34 @@ import { Config } from "talk-common/config";
|
||||
import {
|
||||
createJWTSigningConfig,
|
||||
extractJWTFromRequest,
|
||||
parseAuthHeader,
|
||||
} from "talk-server/app/middleware/passport/jwt";
|
||||
import { Request } from "talk-server/types/express";
|
||||
|
||||
describe("parseAuthHeader", () => {
|
||||
it("parses valid headers", () => {
|
||||
const parsed = {
|
||||
scheme: "bearer",
|
||||
value: "token",
|
||||
};
|
||||
|
||||
expect(parseAuthHeader("Bearer token")).toEqual(parsed);
|
||||
|
||||
expect(parseAuthHeader("bearer token")).toEqual(parsed);
|
||||
|
||||
expect(parseAuthHeader("bearer token")).toEqual(parsed);
|
||||
});
|
||||
|
||||
it("parses invalid headers", () => {
|
||||
expect(parseAuthHeader("this-is-a-wrong-header")).toEqual(null);
|
||||
expect(parseAuthHeader("bearerthis-is-a-wrong-header")).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("extractJWTFromRequest", () => {
|
||||
it("extracts the token from header", () => {
|
||||
const req = {
|
||||
get: sinon
|
||||
.stub()
|
||||
.withArgs("authorization")
|
||||
.returns("Bearer token"),
|
||||
headers: {
|
||||
authorization: "Bearer token",
|
||||
},
|
||||
url: "",
|
||||
};
|
||||
|
||||
expect(extractJWTFromRequest((req as any) as Request)).toEqual("token");
|
||||
expect(req.get.calledOnce).toBeTruthy();
|
||||
|
||||
req.get.reset();
|
||||
req.get.returns(null);
|
||||
delete req.headers.authorization;
|
||||
|
||||
expect(extractJWTFromRequest((req as any) as Request)).toEqual(null);
|
||||
expect(req.get.calledOnce).toBeTruthy();
|
||||
});
|
||||
|
||||
it("extracts the token from query string", () => {
|
||||
const req = {
|
||||
get: sinon
|
||||
.stub()
|
||||
.withArgs("authorization")
|
||||
.returns(null),
|
||||
query: { access_token: "token" },
|
||||
url: "",
|
||||
};
|
||||
expect(extractJWTFromRequest((req as any) as Request)).toEqual(null);
|
||||
|
||||
req.url = "https://talk.coralproject.net/api?access_token=token";
|
||||
|
||||
expect(extractJWTFromRequest((req as any) as Request)).toEqual("token");
|
||||
expect(req.get.calledOnce).toBeTruthy();
|
||||
|
||||
delete req.query.access_token;
|
||||
|
||||
req.get.reset();
|
||||
expect(extractJWTFromRequest((req as any) as Request)).toEqual(null);
|
||||
expect(req.get.calledOnce).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -2,41 +2,20 @@ import { Redis } from "ioredis";
|
||||
import jwt, { SignOptions } from "jsonwebtoken";
|
||||
import { Db } from "mongodb";
|
||||
import { Strategy } from "passport-strategy";
|
||||
import { Bearer } from "permit";
|
||||
import uuid from "uuid";
|
||||
|
||||
import { Config } from "talk-common/config";
|
||||
import { retrieveUser, User } from "talk-server/models/user";
|
||||
import { Request } from "talk-server/types/express";
|
||||
|
||||
const authHeaderRegex = /(\S+)\s+(\S+)/;
|
||||
|
||||
export function parseAuthHeader(header: string) {
|
||||
const matches = header.match(authHeaderRegex);
|
||||
if (!matches || matches.length < 3) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
scheme: matches[1].toLowerCase(),
|
||||
value: matches[2],
|
||||
};
|
||||
}
|
||||
|
||||
export function extractJWTFromRequest(req: Request) {
|
||||
const header = req.get("authorization");
|
||||
if (header) {
|
||||
const parts = parseAuthHeader(header);
|
||||
if (parts && parts.scheme === "bearer") {
|
||||
return parts.value;
|
||||
}
|
||||
}
|
||||
const permit = new Bearer({
|
||||
basic: "password",
|
||||
query: "access_token",
|
||||
});
|
||||
|
||||
const token: string | undefined | false = req.query && req.query.access_token;
|
||||
if (token) {
|
||||
return token;
|
||||
}
|
||||
|
||||
return null;
|
||||
return permit.check(req) || null;
|
||||
}
|
||||
|
||||
function generateJTIBlacklistKey(jti: string) {
|
||||
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
// TODO: (wyattjoh) following https://github.com/DefinitelyTyped/DefinitelyTyped/pull/29061 to merge then replace this with @types/permit.
|
||||
declare module "permit" {
|
||||
import { IncomingMessage, ServerResponse } from "http";
|
||||
|
||||
export interface PermitOptions {
|
||||
scheme?: string;
|
||||
proxy?: string;
|
||||
realm?: string;
|
||||
}
|
||||
|
||||
export interface BearerOptions extends PermitOptions {
|
||||
basic?: string;
|
||||
header?: string;
|
||||
query?: string;
|
||||
}
|
||||
|
||||
export class Permit {
|
||||
constructor(options: PermitOptions);
|
||||
check(req: IncomingMessage): void;
|
||||
fail(res: ServerResponse): void;
|
||||
}
|
||||
|
||||
export class Bearer extends Permit {
|
||||
constructor(options: BearerOptions);
|
||||
check(req: IncomingMessage): string;
|
||||
}
|
||||
|
||||
export class Basic extends Permit {
|
||||
check(req: IncomingMessage): [string, string];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user