From ed97f80a00af77bb7f94e0d8c6f08b6b7161b057 Mon Sep 17 00:00:00 2001 From: Kiwi Date: Wed, 4 Jul 2018 14:01:08 -0300 Subject: [PATCH 01/69] Use JSDocs comments (#1727) --- scripts/watcher/CommandExecutor.ts | 6 +++--- scripts/watcher/LongRunningExecutor.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/watcher/CommandExecutor.ts b/scripts/watcher/CommandExecutor.ts index 60cf15e6a..fddba0b8b 100644 --- a/scripts/watcher/CommandExecutor.ts +++ b/scripts/watcher/CommandExecutor.ts @@ -5,13 +5,13 @@ import { Executor } from "./types"; interface CommandExecutorOptions { args?: ReadonlyArray; - // If true, allow spawning multiple processes. + /** If true, allow spawning multiple processes. */ spawnMutiple?: boolean; - // Specify the period in which the process is started at max once. + /** Specify the period in which the process is started at max once. */ debounce?: number | false; - // If true, will run command upon initialization. + /** If true, will run command upon initialization. */ runOnInit?: boolean; } diff --git a/scripts/watcher/LongRunningExecutor.ts b/scripts/watcher/LongRunningExecutor.ts index cffe6f7db..7019c1fb3 100644 --- a/scripts/watcher/LongRunningExecutor.ts +++ b/scripts/watcher/LongRunningExecutor.ts @@ -6,7 +6,7 @@ import { Executor } from "./types"; interface LongRunningExecutorOptions { args?: ReadonlyArray; - // Specify the period in which the process is restarted at max once. + /** Specify the period in which the process is restarted at max once. */ debounce?: number; } From 52594dc02802390c8e68c979014a9095b2b76139 Mon Sep 17 00:00:00 2001 From: Kiwi Date: Wed, 4 Jul 2018 14:12:43 -0300 Subject: [PATCH 02/69] [next] Remove nodemon (#1725) * Remove old nodemon configs * Remove nodemon --- config/nodemon/relay-stream.json | 8 ---- config/nodemon/server.json | 10 ----- package-lock.json | 77 -------------------------------- package.json | 3 +- 4 files changed, 1 insertion(+), 97 deletions(-) delete mode 100644 config/nodemon/relay-stream.json delete mode 100644 config/nodemon/server.json diff --git a/config/nodemon/relay-stream.json b/config/nodemon/relay-stream.json deleted file mode 100644 index dc9556823..000000000 --- a/config/nodemon/relay-stream.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "exec": "npm-run-all compile:relay-stream", - "ext": "ts,tsx,graphql", - "watch": [ - "./src/core/client/stream", - "./src/core/**/*.graphql" - ] -} diff --git a/config/nodemon/server.json b/config/nodemon/server.json deleted file mode 100644 index 08472086e..000000000 --- a/config/nodemon/server.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "exec": "npm run start:development", - "ext": "ts,graphql", - "watch": [ - "./src" - ], - "ignore": [ - "./src/client" - ] -} diff --git a/package-lock.json b/package-lock.json index b3622a48d..6038504da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9820,12 +9820,6 @@ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, "immutable": { "version": "3.7.6", "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", @@ -12790,50 +12784,6 @@ "which": "^1.3.0" } }, - "nodemon": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.17.5.tgz", - "integrity": "sha512-FG2mWJU1Y58a9ktgMJ/RZpsiPz3b7ge77t/okZHEa4NbrlXGKZ8s1A6Q+C7+JPXohAfcPALRwvxcAn8S874pmw==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "debug": "^3.1.0", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.0", - "semver": "^5.5.0", - "supports-color": "^5.2.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.2", - "update-notifier": "^2.3.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "nopt": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", @@ -15936,15 +15886,6 @@ "integrity": "sha512-+AqO1Ae+N/4r7Rvchrdm432afjT9hqJRyBN3DQv9At0tPz4hIFSGKbq64fN9dVoCow4oggIIax5/iONx0r9hZw==", "dev": true }, - "pstree.remy": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.0.tgz", - "integrity": "sha512-q5I5vLRMVtdWa8n/3UEzZX7Lfghzrg9eG2IKk2ENLSofKRCXVqMvMUHxCKgXNaqH/8ebhBxrqftHWnyTFweJ5Q==", - "dev": true, - "requires": { - "ps-tree": "^1.1.0" - } - }, "public-encrypt": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", @@ -18801,15 +18742,6 @@ "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", "dev": true }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "~1.0.10" - } - }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -19684,15 +19616,6 @@ "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==", "dev": true }, - "undefsafe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", - "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", - "dev": true, - "requires": { - "debug": "^2.2.0" - } - }, "unherit": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", diff --git a/package.json b/package.json index 5f615b41f..707d65836 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,6 @@ "html-webpack-plugin": "^3.2.0", "jest": "^23.2.0", "loader-utils": "^1.1.0", - "nodemon": "^1.17.5", "npm-run-all": "^4.1.3", "postcss-flexbugs-fixes": "^3.3.1", "postcss-font-magician": "^2.2.1", @@ -141,4 +140,4 @@ "webpack-hot-client": "^4.0.3", "webpack-manifest-plugin": "^2.0.3" } -} \ No newline at end of file +} From e4c0e16e1b492a1212b5acd0da8873eeb027db20 Mon Sep 17 00:00:00 2001 From: Kiwi Date: Thu, 5 Jul 2018 12:04:38 -0300 Subject: [PATCH 03/69] [next] Jest implementation for React Components (#1733) * Make jest testing work with custom path and css modules * Add first test * feat: added unit tests to ci * fix: updated package-lock.json * Update cssTransform.js * Update cssTransform.js * Fix test in ci --- .circleci/config.yml | 17 ++ config/jest.config.js | 9 +- config/jest/cssTransform.js | 96 +++++++- package-lock.json | 229 ++++++++++-------- package.json | 9 +- scripts/test.js | 2 +- .../client/stream/components/Comment.spec.tsx | 28 +++ .../__snapshots__/Comment.spec.tsx.snap | 33 +++ 8 files changed, 308 insertions(+), 115 deletions(-) create mode 100644 src/core/client/stream/components/Comment.spec.tsx create mode 100644 src/core/client/stream/components/__snapshots__/Comment.spec.tsx.snap diff --git a/.circleci/config.yml b/.circleci/config.yml index 908210e13..bd7493f6b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,6 +43,20 @@ jobs: name: Perform linting command: npm run lint + # unit_tests will run the unit tests. + unit_tests: + <<: *job_defaults + steps: + - checkout + - attach_workspace: + at: ~/coralproject/talk + - run: + name: Compile schemas and types + command: npm run compile + - run: + name: Perform testing + command: npm run test + # build will build the static assets and server typescript files. build: <<: *job_defaults @@ -74,6 +88,9 @@ workflows: - lint: requires: - npm_dependencies + - unit_tests: + requires: + - npm_dependencies - build: requires: - npm_dependencies diff --git a/config/jest.config.js b/config/jest.config.js index 682a2c8a4..ed9b641ae 100644 --- a/config/jest.config.js +++ b/config/jest.config.js @@ -8,7 +8,7 @@ module.exports = { setupFiles: ["/config/polyfills.js"], testMatch: [ "**/__tests__/**/*.{js,jsx,mjs,ts,tsx}", - "**/*.(spec|test).{js,jsx,mjs,ts,tsx}", + "**/*.spec.{js,jsx,mjs,ts,tsx}", ], testEnvironment: "node", testURL: "http://localhost", @@ -22,7 +22,12 @@ module.exports = { "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|ts|tsx)$", ], moduleNameMapper: { - "^react-native$": "react-native-web", + "^talk-admin/(.*)$": "/src/core/client/admin/$1", + "^talk-ui/(.*)$": "/src/core/client/ui/$1", + "^talk-stream/(.*)$": "/src/core/client/stream/$1", + "^talk-framework/(.*)$": "/src/core/client/framework/$1", + "^talk-common/(.*)$": "/src/core/common/$1", + "^talk-server/(.*)$": "/src/core/server/$1", }, moduleFileExtensions: [ "web.js", diff --git a/config/jest/cssTransform.js b/config/jest/cssTransform.js index 606cc276b..90b6bfa63 100644 --- a/config/jest/cssTransform.js +++ b/config/jest/cssTransform.js @@ -1,14 +1,94 @@ "use strict"; -// This is a custom Jest transformer turning style imports into empty objects. -// http://facebook.github.io/jest/docs/en/webpack.html +// Adapted version of https://github.com/Connormiha/jest-css-modules-transform +// Copyright https://github.com/Connormiha/jest-css-modules-transform/graphs/contributors +// This oututs `module.exports = cssObject` instead of `module.exports = { default: cssObject }`; + +const { sep: pathSep, resolve } = require("path"); +const postcss = require("postcss"); +const postcssNested = postcss([require("postcss-nested")]); + +const REG_EXP_NAME_BREAK_CHAR = /[\s,.{/#[:]/; + +const getCSSSelectors = (css, path) => { + const end = css.length; + let i = 0; + let char; + let bracketsCount = 0; + const result = {}; + + while (i < end) { + if (i === -1) { + throw Error(`Parse error ${path}`); + } + if (css.indexOf("/*", i) === i) { + i = css.indexOf("*/", i + 2); + // Unclosed comment. Break to avoid infinity loop + if (i === -1) { + // Don't parse, but save collected result + return result; + } + continue; + } + char = css[i]; + if (char === "{") { + bracketsCount++; + i++; + continue; + } + if (char === "}") { + bracketsCount--; + i++; + continue; + } + if (char === '"' || char === "'") { + do { + i = css.indexOf(char, i + 1); + // Syntax error since this line. Don't parse, but save collected result + if (i === -1) { + return result; + } + } while (css[i - 1] === "\\"); + i++; + continue; + } + if (bracketsCount > 0) { + i++; + continue; + } + if (char === "." || char === "#") { + i++; + const startWord = i; + while (!REG_EXP_NAME_BREAK_CHAR.test(css[i])) { + i++; + } + const word = css.slice(startWord, i); + result[word] = word; + continue; + } + if (css.indexOf("@keyframes", i) === i) { + i += 10; + while (REG_EXP_NAME_BREAK_CHAR.test(css[i])) { + i++; + } + const startWord = i; + while (!REG_EXP_NAME_BREAK_CHAR.test(css[i])) { + i++; + } + const word = css.slice(startWord, i); + result[word] = word; + continue; + } + i++; + } + return result; +}; module.exports = { - process() { - return "module.exports = {};"; - }, - getCacheKey() { - // The output is always the same. - return "cssTransform"; + process(src, path, config) { + const filename = path.slice(path.lastIndexOf(pathSep) + 1); + const textCSS = postcssNested.process(src).css; + const exprt = JSON.stringify(getCSSSelectors(textCSS, path)); + return `module.exports = ${exprt}`; }, }; diff --git a/package-lock.json b/package-lock.json index 6038504da..c6dd91c93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1628,13 +1628,17 @@ } }, "@types/react-relay": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@types/react-relay/-/react-relay-1.3.6.tgz", - "integrity": "sha512-X0qv3nGlE4TStFLLKxgj+6MgHZEExB1N/RDcVcyCauAojV5byD0c6VhuqAluYaTKaL2FBuxdtDL405IhIIjEbQ==", + "version": "github:coralproject/patched#ba4c8d01bb737e5f073534b32d870294e39cc5a8", + "from": "github:coralproject/patched#types/react-relay", + "dev": true + }, + "@types/react-test-renderer": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.0.1.tgz", + "integrity": "sha512-kmNh8g67Ck/y/vp6KX+4JTJXiTGLZBylNhu+R7sm7zcvsrnIGVO6J1zew5inVg428j9f8yHpl68RcYOZXVborQ==", "dev": true, "requires": { - "@types/react": "*", - "@types/relay-runtime": "*" + "@types/react": "*" } }, "@types/recompose": { @@ -7635,17 +7639,17 @@ } }, "expect": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-23.2.0.tgz", - "integrity": "sha1-U6fhNeNv4n51hnsReP8IqqzCsN0=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-23.3.0.tgz", + "integrity": "sha1-7LBRrcvcQKxNtXbBYGfxL9sTzGE=", "dev": true, "requires": { "ansi-styles": "^3.2.0", "jest-diff": "^23.2.0", "jest-get-type": "^22.1.0", "jest-matcher-utils": "^23.2.0", - "jest-message-util": "^23.2.0", - "jest-regex-util": "^23.0.0" + "jest-message-util": "^23.3.0", + "jest-regex-util": "^23.3.0" }, "dependencies": { "ansi-styles": { @@ -10835,13 +10839,13 @@ "dev": true }, "jest": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-23.2.0.tgz", - "integrity": "sha1-govzGgltRdzwaCTR6gMBOve8/CA=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-23.3.0.tgz", + "integrity": "sha1-E1XNeS84zyD7pNoC3dt8oU2UhLU=", "dev": true, "requires": { "import-local": "^1.0.0", - "jest-cli": "^23.2.0" + "jest-cli": "^23.3.0" }, "dependencies": { "ansi-regex": { @@ -10865,9 +10869,9 @@ } }, "jest-cli": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.2.0.tgz", - "integrity": "sha1-O1Q6PaUUXdiTeTEBcoI3n8aWxFs=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.3.0.tgz", + "integrity": "sha1-MH6b53M0Q7eJqCedaUBU0FGp5eI=", "dev": true, "requires": { "ansi-escapes": "^3.0.0", @@ -10882,18 +10886,18 @@ "istanbul-lib-instrument": "^1.10.1", "istanbul-lib-source-maps": "^1.2.4", "jest-changed-files": "^23.2.0", - "jest-config": "^23.2.0", - "jest-environment-jsdom": "^23.2.0", + "jest-config": "^23.3.0", + "jest-environment-jsdom": "^23.3.0", "jest-get-type": "^22.1.0", "jest-haste-map": "^23.2.0", - "jest-message-util": "^23.2.0", - "jest-regex-util": "^23.0.0", - "jest-resolve-dependencies": "^23.2.0", - "jest-runner": "^23.2.0", - "jest-runtime": "^23.2.0", - "jest-snapshot": "^23.2.0", - "jest-util": "^23.2.0", - "jest-validate": "^23.2.0", + "jest-message-util": "^23.3.0", + "jest-regex-util": "^23.3.0", + "jest-resolve-dependencies": "^23.3.0", + "jest-runner": "^23.3.0", + "jest-runtime": "^23.3.0", + "jest-snapshot": "^23.3.0", + "jest-util": "^23.3.0", + "jest-validate": "^23.3.0", "jest-watcher": "^23.2.0", "jest-worker": "^23.2.0", "micromatch": "^3.1.10", @@ -10938,23 +10942,23 @@ } }, "jest-config": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.2.0.tgz", - "integrity": "sha1-0vtVb9WioZw561bROdzKXa0qHIg=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.3.0.tgz", + "integrity": "sha1-u01Ttw+VAPr933GNImq7U7E7gyM=", "dev": true, "requires": { "babel-core": "^6.0.0", "babel-jest": "^23.2.0", "chalk": "^2.0.1", "glob": "^7.1.1", - "jest-environment-jsdom": "^23.2.0", - "jest-environment-node": "^23.2.0", + "jest-environment-jsdom": "^23.3.0", + "jest-environment-node": "^23.3.0", "jest-get-type": "^22.1.0", - "jest-jasmine2": "^23.2.0", - "jest-regex-util": "^23.0.0", + "jest-jasmine2": "^23.3.0", + "jest-regex-util": "^23.3.0", "jest-resolve": "^23.2.0", - "jest-util": "^23.2.0", - "jest-validate": "^23.2.0", + "jest-util": "^23.3.0", + "jest-validate": "^23.3.0", "pretty-format": "^23.2.0" }, "dependencies": { @@ -11003,24 +11007,24 @@ } }, "jest-environment-jsdom": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.2.0.tgz", - "integrity": "sha1-NjRgOgipdbDKimWDIPVqVKjgRVg=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.3.0.tgz", + "integrity": "sha1-GQRX+RyeYVRUxBhgVgZdtu16Tio=", "dev": true, "requires": { "jest-mock": "^23.2.0", - "jest-util": "^23.2.0", + "jest-util": "^23.3.0", "jsdom": "^11.5.1" } }, "jest-environment-node": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.2.0.tgz", - "integrity": "sha1-tv5BNy44IJO7bz2b32wcTsClDxg=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.3.0.tgz", + "integrity": "sha1-Ho3yHIR6pdA7dlc/DcFvzeUDTDI=", "dev": true, "requires": { "jest-mock": "^23.2.0", - "jest-util": "^23.2.0" + "jest-util": "^23.3.0" } }, "jest-get-type": { @@ -11056,21 +11060,21 @@ } }, "jest-jasmine2": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.2.0.tgz", - "integrity": "sha1-qmcM2x5NX47HdMlN2l4QX+M9i7Q=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.3.0.tgz", + "integrity": "sha1-qHBrqsI8ihMNWqjvVGSp1JCW0bU=", "dev": true, "requires": { "chalk": "^2.0.1", "co": "^4.6.0", - "expect": "^23.2.0", + "expect": "^23.3.0", "is-generator-fn": "^1.0.0", "jest-diff": "^23.2.0", "jest-each": "^23.2.0", "jest-matcher-utils": "^23.2.0", - "jest-message-util": "^23.2.0", - "jest-snapshot": "^23.2.0", - "jest-util": "^23.2.0", + "jest-message-util": "^23.3.0", + "jest-snapshot": "^23.3.0", + "jest-util": "^23.3.0", "pretty-format": "^23.2.0" } }, @@ -11095,9 +11099,9 @@ } }, "jest-message-util": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.2.0.tgz", - "integrity": "sha1-WR6BSP/2nPibBBSAnHIXVuvv50Q=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.3.0.tgz", + "integrity": "sha1-vAexHOxpcftd2d4t+2DrwiFQwWA=", "dev": true, "requires": { "@babel/code-frame": "^7.0.0-beta.35", @@ -11114,9 +11118,9 @@ "dev": true }, "jest-regex-util": { - "version": "23.0.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.0.0.tgz", - "integrity": "sha1-3Vwf3gxG9DcTFM8Q96dRoj9Oj3Y=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz", + "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=", "dev": true }, "jest-resolve": { @@ -11131,31 +11135,31 @@ } }, "jest-resolve-dependencies": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.2.0.tgz", - "integrity": "sha1-bfjVcJxkBmOc0H9Uv/B04BtcBFg=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.3.0.tgz", + "integrity": "sha1-hETTsLEoi4CGTYgB/1C0Sk1pXR0=", "dev": true, "requires": { - "jest-regex-util": "^23.0.0", - "jest-snapshot": "^23.2.0" + "jest-regex-util": "^23.3.0", + "jest-snapshot": "^23.3.0" } }, "jest-runner": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.2.0.tgz", - "integrity": "sha1-DZGWfqgvcrDHBZEJJghtIFXOda8=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.3.0.tgz", + "integrity": "sha1-BMfkWKYXUBpIddsNf/vg48vUO/s=", "dev": true, "requires": { "exit": "^0.1.2", "graceful-fs": "^4.1.11", - "jest-config": "^23.2.0", + "jest-config": "^23.3.0", "jest-docblock": "^23.2.0", "jest-haste-map": "^23.2.0", - "jest-jasmine2": "^23.2.0", + "jest-jasmine2": "^23.3.0", "jest-leak-detector": "^23.2.0", - "jest-message-util": "^23.2.0", - "jest-runtime": "^23.2.0", - "jest-util": "^23.2.0", + "jest-message-util": "^23.3.0", + "jest-runtime": "^23.3.0", + "jest-util": "^23.3.0", "jest-worker": "^23.2.0", "source-map-support": "^0.5.6", "throat": "^4.0.0" @@ -11173,9 +11177,9 @@ } }, "jest-runtime": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.2.0.tgz", - "integrity": "sha1-YtywF2ahxMZGltwJAgnnbOGq3Lw=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.3.0.tgz", + "integrity": "sha1-SGWqtM7/gvnOxjNf164UIswd598=", "dev": true, "requires": { "babel-core": "^6.0.0", @@ -11185,14 +11189,14 @@ "exit": "^0.1.2", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.1.11", - "jest-config": "^23.2.0", + "jest-config": "^23.3.0", "jest-haste-map": "^23.2.0", - "jest-message-util": "^23.2.0", - "jest-regex-util": "^23.0.0", + "jest-message-util": "^23.3.0", + "jest-regex-util": "^23.3.0", "jest-resolve": "^23.2.0", - "jest-snapshot": "^23.2.0", - "jest-util": "^23.2.0", - "jest-validate": "^23.2.0", + "jest-snapshot": "^23.3.0", + "jest-util": "^23.3.0", + "jest-validate": "^23.3.0", "micromatch": "^3.1.10", "realpath-native": "^1.0.0", "slash": "^1.0.0", @@ -11208,30 +11212,35 @@ "dev": true }, "jest-snapshot": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.2.0.tgz", - "integrity": "sha1-x6PQFxd7utYMillYac+QqHguan4=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.3.0.tgz", + "integrity": "sha1-/E6fgeRUMtEFB+J/ULzmD0TYFCQ=", "dev": true, "requires": { + "babel-traverse": "^6.0.0", + "babel-types": "^6.0.0", "chalk": "^2.0.1", "jest-diff": "^23.2.0", "jest-matcher-utils": "^23.2.0", + "jest-message-util": "^23.3.0", + "jest-resolve": "^23.2.0", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "pretty-format": "^23.2.0" + "pretty-format": "^23.2.0", + "semver": "^5.5.0" } }, "jest-util": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.2.0.tgz", - "integrity": "sha1-YrdwdXaW2W4JSgS48cNzylClqy4=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.3.0.tgz", + "integrity": "sha1-efNbsMMBAO9hHZY+5riPjthzqB0=", "dev": true, "requires": { "callsites": "^2.0.0", "chalk": "^2.0.1", "graceful-fs": "^4.1.11", "is-ci": "^1.0.10", - "jest-message-util": "^23.2.0", + "jest-message-util": "^23.3.0", "mkdirp": "^0.5.1", "slash": "^1.0.0", "source-map": "^0.6.0" @@ -11246,9 +11255,9 @@ } }, "jest-validate": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.2.0.tgz", - "integrity": "sha1-Z8i5CeEa8XAXZSOIlMZ6wykbGV4=", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.3.0.tgz", + "integrity": "sha1-1Jvqaq2YwwrNLLtUJDR5igzBP3Y=", "dev": true, "requires": { "chalk": "^2.0.1", @@ -15831,13 +15840,13 @@ "dev": true }, "prompts": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.9.tgz", - "integrity": "sha512-RMRvwAUDVUMhP/z3YfDW6igMwT0UnL+w3XCUUNxxHjgwJnVEdHWYJVjM7hQMPub8HCk12xZYAqWlbgLBnqebwg==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.10.tgz", + "integrity": "sha512-/MPwms6+g/m6fvXZlQyOL4m4ziDim2+Wc6CdWVjp+nVCkzEkK2N4rR74m/bbGf+dkta+/SBpo1FfES8Wgrk/Fw==", "dev": true, "requires": { - "clorox": "^1.0.1", - "sisteransi": "^0.1.0" + "clorox": "^1.0.3", + "sisteransi": "^0.1.1" } }, "prop-types": { @@ -16360,6 +16369,12 @@ "shallowequal": "^1.0.2" } }, + "react-is": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.1.tgz", + "integrity": "sha512-xpb0PpALlFWNw/q13A+1aHeyJyLYCg0/cCHPUA43zYluZuIPHaHL3k8OBsTgQtxqW0FhyDEMvi8fZ/+7+r4OSQ==", + "dev": true + }, "react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -16460,6 +16475,18 @@ } } }, + "react-test-renderer": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.4.1.tgz", + "integrity": "sha512-wyyiPxRZOTpKnNIgUBOB6xPLTpIzwcQMIURhZvzUqZzezvHjaGNsDPBhMac5fIY3Jf5NuKxoGvV64zDSOECPPQ==", + "dev": true, + "requires": { + "fbjs": "^0.8.16", + "object-assign": "^4.1.1", + "prop-types": "^15.6.0", + "react-is": "^16.4.1" + } + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -16509,9 +16536,9 @@ } }, "realpath-native": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.0.tgz", - "integrity": "sha512-XJtlRJ9jf0E1H1SLeJyQ9PGzQD7S65h1pRXEcAeK48doKOnKxcgPeNohJvD5u/2sI9J1oke6E8bZHS/fmW1UiQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.1.tgz", + "integrity": "sha512-W14EcXuqUvKP8dkWkD7B95iMy77lpMnlFXbbk409bQtNCbeu0kvRE5reo+yIZ3JXxg6frbGsz2DLQ39lrCB40g==", "dev": true, "requires": { "util.promisify": "^1.0.0" @@ -17755,9 +17782,9 @@ } }, "sisteransi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.0.tgz", - "integrity": "sha512-kHXcIr0Z9FM6d7pwFDDIMQKGndIEtIF1oBSMXWtItpx4mrH1jhANVNT35GVekBekXl6J+5i7lJMIGq3Gm7pIdA==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz", + "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==", "dev": true }, "slash": { diff --git a/package.json b/package.json index 707d65836..820605d35 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,11 @@ "scripts": { "start": "node dist/index.js", "test": "node scripts/test.js --env=jsdom", - "build": "npm-run-all --parallel compile:* && npm-run-all --parallel build:*", + "build": "npm-run-all compile --parallel build:*", "build:client": "node ./scripts/build.js", "build:server": "tsc -p ./src/tsconfig.json", "watch": "NODE_ENV=development ts-node ./scripts/watcher/bin/watcher.ts ./config/watcher.ts", + "compile": "npm-run-all --parallel compile:*", "compile:css-types": "tcm src/core/client/", "compile:relay-stream": "relay-compiler --src ./src/core/client/stream --schema $(ts-node ./scripts/schemaPath.ts tenant) --language typescript --artifactDirectory ./src/core/client/stream/__generated__ --no-watchman", "start:development": "NODE_ENV=development ts-node --project ./src/tsconfig.json -r tsconfig-paths/register ./src/index.ts", @@ -72,7 +73,8 @@ "@types/passport": "^0.4.5", "@types/query-string": "^6.1.0", "@types/react-dom": "^16.0.6", - "@types/react-relay": "^1.3.6", + "@types/react-relay": "github:coralproject/patched#types/react-relay", + "@types/react-test-renderer": "^16.0.1", "@types/recompose": "^0.26.1", "@types/relay-runtime": "github:coralproject/patched#types/relay-runtime", "@types/uuid": "^3.4.3", @@ -100,7 +102,7 @@ "fluent-react": "^0.7.0", "graphql-playground-middleware-express": "^1.7.0", "html-webpack-plugin": "^3.2.0", - "jest": "^23.2.0", + "jest": "^23.3.0", "loader-utils": "^1.1.0", "npm-run-all": "^4.1.3", "postcss-flexbugs-fixes": "^3.3.1", @@ -115,6 +117,7 @@ "react-dom": "^16.4.0", "react-final-form": "^3.6.0", "react-relay": "github:coralproject/patched#react-relay", + "react-test-renderer": "^16.4.1", "recompose": "^0.27.1", "relay-compiler": "github:coralproject/patched#relay-compiler", "relay-compiler-language-typescript": "github:coralproject/patched#relay-compiler-language-typescript", diff --git a/scripts/test.js b/scripts/test.js index 1ac08fd2e..f08b18de6 100644 --- a/scripts/test.js +++ b/scripts/test.js @@ -19,11 +19,11 @@ const paths = require("../config/paths"); const jest = require("jest"); let argv = process.argv.slice(2); +argv.push("--config", paths.appJestConfig); // Watch unless on CI or in coverage mode if (!process.env.CI && argv.indexOf("--coverage") < 0) { argv.push("--watch"); - argv.push("--config", paths.appJestConfig); } jest.run(argv); diff --git a/src/core/client/stream/components/Comment.spec.tsx b/src/core/client/stream/components/Comment.spec.tsx new file mode 100644 index 000000000..6008bfc3b --- /dev/null +++ b/src/core/client/stream/components/Comment.spec.tsx @@ -0,0 +1,28 @@ +import React from "react"; +import { createRenderer } from "react-test-renderer/shallow"; +import Comment from "./Comment"; + +it("renders username and body", () => { + const props = { + author: { + username: "Marvin", + }, + body: "Woof", + }; + const renderer = createRenderer(); + renderer.render(); + expect(renderer.getRenderOutput()).toMatchSnapshot(); +}); + +it("renders with gutterBottom", () => { + const props = { + author: { + username: "Marvin", + }, + body: "Woof", + gutterBottom: true, + }; + const renderer = createRenderer(); + renderer.render(); + expect(renderer.getRenderOutput()).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/components/__snapshots__/Comment.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/Comment.spec.tsx.snap new file mode 100644 index 000000000..4b009e257 --- /dev/null +++ b/src/core/client/stream/components/__snapshots__/Comment.spec.tsx.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders username and body 1`] = ` +
+ + Marvin + + + Woof + +
+`; + +exports[`renders with gutterBottom 1`] = ` +
+ + Marvin + + + Woof + +
+`; From 01e14cc110bbe4cc8a44c7c012277ecfb42edbc6 Mon Sep 17 00:00:00 2001 From: Kiwi Date: Fri, 6 Jul 2018 16:08:10 -0300 Subject: [PATCH 04/69] Adapt files.exclude (#1736) --- .prettierignore | 1 + .vscode/settings.json | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +node_modules diff --git a/.vscode/settings.json b/.vscode/settings.json index 195b73de5..4dd5d1b72 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,12 +9,10 @@ "**/.hg": true, "**/CVS": true, "**/.DS_Store": true, - "node_modules": true, - "dist": true, - ".vscode": true, - "package-lock.json": true + ".vs": true }, + "tslint.exclude": "**/node_modules/**", "tslint.autoFixOnSave": true, "tslint.jsEnable": true, "typescript.tsdk": "node_modules/typescript/lib" -} \ No newline at end of file +} From 89c697b18fd50ee74df6cafd7b2e591986fd7270 Mon Sep 17 00:00:00 2001 From: okbel Date: Fri, 6 Jul 2018 23:44:29 -0300 Subject: [PATCH 05/69] Permalink ui --- package-lock.json | 161 ++++++++++++++++-- package.json | 3 + src/core/client/stream/components/Comment.css | 10 +- src/core/client/stream/components/Comment.tsx | 18 +- .../client/stream/components/Permalink.tsx | 0 src/core/client/ui/components/Input/Input.css | 11 ++ src/core/client/ui/components/Input/Input.tsx | 14 ++ src/core/client/ui/components/Input/index.ts | 2 + .../client/ui/components/Tooltip/Tooltip.css | 14 ++ .../client/ui/components/Tooltip/Tooltip.tsx | 11 ++ .../client/ui/components/Tooltip/index.ts | 2 + src/core/client/ui/components/index.ts | 2 + 12 files changed, 230 insertions(+), 18 deletions(-) create mode 100644 src/core/client/stream/components/Permalink.tsx create mode 100644 src/core/client/ui/components/Input/Input.css create mode 100644 src/core/client/ui/components/Input/Input.tsx create mode 100644 src/core/client/ui/components/Input/index.ts create mode 100644 src/core/client/ui/components/Tooltip/Tooltip.css create mode 100644 src/core/client/ui/components/Tooltip/Tooltip.tsx create mode 100644 src/core/client/ui/components/Tooltip/index.ts diff --git a/package-lock.json b/package-lock.json index c6dd91c93..c8a6caf98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1612,7 +1612,6 @@ "version": "16.4.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.2.tgz", "integrity": "sha512-oVcVteCDNiVc/fkDjowRfAZQDEOR76j3CJ3FvwXNvfV6zJguhghy1lMgpAzYox+9AZsWch+JPV6Imml3wvIUeg==", - "dev": true, "requires": { "csstype": "^2.2.0" } @@ -1641,6 +1640,14 @@ "@types/react": "*" } }, + "@types/react-tooltip": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/react-tooltip/-/react-tooltip-3.3.5.tgz", + "integrity": "sha512-wpWzjtMWBPymIoYjqZTeWX1v5dJe4V1akmcTM6iZwSS/cL8jdi6dFt4BoLXDOxgL5tEe/9yVBlQD+MAYvexBfw==", + "requires": { + "@types/react": "*" + } + }, "@types/recompose": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/@types/recompose/-/recompose-0.26.1.tgz", @@ -2050,6 +2057,14 @@ "acorn": "^5.0.0" } }, + "add-dom-event-listener": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.0.2.tgz", + "integrity": "sha1-j67SxBAIchzxEdodMNmVuFvkK+0=", + "requires": { + "object-assign": "4.x" + } + }, "address": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz", @@ -4166,7 +4181,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, "requires": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" @@ -5076,8 +5090,7 @@ "classnames": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==", - "dev": true + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, "clean-css": { "version": "4.1.11", @@ -5369,12 +5382,25 @@ "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==", "dev": true }, + "component-classes": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz", + "integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=", + "requires": { + "component-indexof": "0.0.3" + } + }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, + "component-indexof": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz", + "integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ=" + }, "compressible": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz", @@ -5881,6 +5907,15 @@ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, + "css-animation": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.4.1.tgz", + "integrity": "sha1-W4gTEl3g+7uwu+G0cq6EIhRpt6g=", + "requires": { + "babel-runtime": "6.x", + "component-classes": "^1.2.5" + } + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -6248,8 +6283,7 @@ "csstype": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.5.tgz", - "integrity": "sha512-EGMjeoiN3aqEX5u/cyH5mSdGBDGdLcCQvcEcBWNGFSPXKd9uOTIeVG91YQ22OxI44DKpvI+4C7VUSmEpsHWJaA==", - "dev": true + "integrity": "sha512-EGMjeoiN3aqEX5u/cyH5mSdGBDGdLcCQvcEcBWNGFSPXKd9uOTIeVG91YQ22OxI44DKpvI+4C7VUSmEpsHWJaA==" }, "currently-unhandled": { "version": "0.4.1", @@ -7019,6 +7053,11 @@ "webfontloader": "^1.6.28" } }, + "dom-align": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.8.0.tgz", + "integrity": "sha512-B85D4ef2Gj5lw0rK0KM2+D5/pH7yqNxg2mB+E8uzFaolpm7RQmsxEfjyEuNiF8UBBkffumYDeKRzTzc3LePP+w==" + }, "dom-converter": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", @@ -11305,8 +11344,7 @@ "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { "version": "3.12.0", @@ -11829,6 +11867,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -11899,6 +11942,16 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, "lodash.isempty": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", @@ -12050,7 +12103,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, "requires": { "js-tokens": "^3.0.0" } @@ -12939,8 +12991,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -15853,7 +15904,6 @@ "version": "15.6.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", - "dev": true, "requires": { "loose-envify": "^1.3.1", "object-assign": "^4.1.1" @@ -16082,6 +16132,81 @@ "strip-json-comments": "~2.0.1" } }, + "rc-align": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.3.tgz", + "integrity": "sha512-h5KgyB5IXYR7iKpYFcMr54cuQ2eozPCZ11kbXPG5+6CWvmyJ+c0R/yjndVndiNk2G3MKcTMbJNdDv5DIckLAxQ==", + "requires": { + "babel-runtime": "^6.26.0", + "dom-align": "^1.7.0", + "prop-types": "^15.5.8", + "rc-util": "^4.0.4" + } + }, + "rc-animate": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.4.4.tgz", + "integrity": "sha512-DjJLTUQj7XKKcuS8cczN0uOLfuSmgrVXFGieP1SZc87xUUTFGh8B/KjNmEtlfvxkSrSuVfb2rrEPER4SqKUtEA==", + "requires": { + "babel-runtime": "6.x", + "css-animation": "^1.3.2", + "prop-types": "15.x" + } + }, + "rc-tooltip": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.2.tgz", + "integrity": "sha512-vsF29ohlfgr7lEP12aJ5j4U/4hzqSBYjWQo8I09re+q95v1o4nDjH1q/B3qFkf9aml2FbgdkJw9KYz/zXUgApA==", + "requires": { + "babel-runtime": "6.x", + "prop-types": "^15.5.8", + "rc-trigger": "^2.2.2" + } + }, + "rc-trigger": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.5.4.tgz", + "integrity": "sha512-clgXOdazDW2qg4vTZSAExpvOuojPNuMoamG+SxAm5Ih+rpVcrtEiDlDZWY4yUHyfEWJZBzgbrr4np/z2FK6RfA==", + "requires": { + "babel-runtime": "6.x", + "classnames": "^2.2.6", + "prop-types": "15.x", + "rc-align": "^2.4.0", + "rc-animate": "2.x", + "rc-util": "^4.4.0" + } + }, + "rc-util": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.5.1.tgz", + "integrity": "sha512-PdCmHyBBodZdw6Oaikt0l+/R79IcRXpYkTrqD/Rbl4ZdoOi61t5TtEe40Q+A7rkWG5U1xjcN+h8j9H6GdtnICw==", + "requires": { + "add-dom-event-listener": "1.x", + "babel-runtime": "6.x", + "prop-types": "^15.5.10", + "shallowequal": "^0.2.2" + }, + "dependencies": { + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "shallowequal": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-0.2.2.tgz", + "integrity": "sha1-HjL9W8q2rWiKSBLLDMBO/HXHAU4=", + "requires": { + "lodash.keys": "^3.1.2" + } + } + } + }, "react": { "version": "16.4.1", "resolved": "https://registry.npmjs.org/react/-/react-16.4.1.tgz", @@ -16487,6 +16612,15 @@ "react-is": "^16.4.1" } }, + "react-tooltip": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-3.6.1.tgz", + "integrity": "sha512-4NVjHNIx1ZazFYBNP044DHW0cr95Qaq0DSwWbrEQ7VyE8AxemHDjp0DoYvV8wilK9vR9jMlSwDW6ebRgbk3aHw==", + "requires": { + "classnames": "^2.2.5", + "prop-types": "^15.6.0" + } + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -16673,8 +16807,7 @@ "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { "version": "0.12.4", diff --git a/package.json b/package.json index 820605d35..e8082799a 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "author": "", "license": "Apache-2.0", "dependencies": { + "@types/react-tooltip": "^3.3.5", "apollo-server-express": "^1.3.6", "bunyan": "^1.8.12", "convict": "^4.3.0", @@ -45,6 +46,8 @@ "mongodb": "^3.0.10", "passport": "^0.4.0", "performance-now": "^2.1.0", + "rc-tooltip": "^3.7.2", + "react-tooltip": "^3.6.1", "subscriptions-transport-ws": "^0.9.11", "uuid": "^3.2.1" }, diff --git a/src/core/client/stream/components/Comment.css b/src/core/client/stream/components/Comment.css index d43780d8f..8e5301ecd 100644 --- a/src/core/client/stream/components/Comment.css +++ b/src/core/client/stream/components/Comment.css @@ -3,9 +3,17 @@ } .gutterBottom { - margin-bottom: calc(2px * $spacing-unit); + margin-bottom: calc(2 px * $spacing-unit); } .author { font-weight: $font-weight-medium; } + +.shareButton { + padding: 10px 0; +} + +.input { + margin-right: 5px; +} diff --git a/src/core/client/stream/components/Comment.tsx b/src/core/client/stream/components/Comment.tsx index c1b3f9303..1f4e11b1c 100644 --- a/src/core/client/stream/components/Comment.tsx +++ b/src/core/client/stream/components/Comment.tsx @@ -1,9 +1,7 @@ import cn from "classnames"; import React from "react"; import { StatelessComponent } from "react"; - -import { Typography } from "talk-ui/components"; - +import { Button, Input, Tooltip, Typography } from "talk-ui/components"; import * as styles from "./Comment.css"; export interface CommentProps { @@ -25,6 +23,20 @@ const Comment: StatelessComponent = props => { {props.author && props.author.username} {props.body} +
+ + + + + +
); }; diff --git a/src/core/client/stream/components/Permalink.tsx b/src/core/client/stream/components/Permalink.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/core/client/ui/components/Input/Input.css b/src/core/client/ui/components/Input/Input.css new file mode 100644 index 000000000..4d2e9e88a --- /dev/null +++ b/src/core/client/ui/components/Input/Input.css @@ -0,0 +1,11 @@ +.root { + font-family: "Source Sans Pro"; + font-weight: 400; + font-size: 16px; + letter-spacing: calc(0.57em / 16); + background: #ffffff; + border: 1px solid #979797; + box-sizing: border-box; + border-radius: 1px; + padding: 5px 20px; +} diff --git a/src/core/client/ui/components/Input/Input.tsx b/src/core/client/ui/components/Input/Input.tsx new file mode 100644 index 000000000..261b3b1af --- /dev/null +++ b/src/core/client/ui/components/Input/Input.tsx @@ -0,0 +1,14 @@ +import cn from "classnames"; +import React, { InputHTMLAttributes, StatelessComponent } from "react"; + +import * as styles from "./Input.css"; + +interface InnerProps extends InputHTMLAttributes { + classes?: typeof styles; +} + +const Input: StatelessComponent = ({ className, ...rest }) => { + return ; +}; + +export default Input; diff --git a/src/core/client/ui/components/Input/index.ts b/src/core/client/ui/components/Input/index.ts new file mode 100644 index 000000000..ae0d7a775 --- /dev/null +++ b/src/core/client/ui/components/Input/index.ts @@ -0,0 +1,2 @@ +export * from "./Input"; +export { default } from "./Input"; diff --git a/src/core/client/ui/components/Tooltip/Tooltip.css b/src/core/client/ui/components/Tooltip/Tooltip.css new file mode 100644 index 000000000..e3de3d8fe --- /dev/null +++ b/src/core/client/ui/components/Tooltip/Tooltip.css @@ -0,0 +1,14 @@ +.root { + background: #ffffff !important; + border: 1px solid #c9cacb; + box-sizing: border-box; + box-shadow: 1px 0px 4px rgba(0, 0, 0, 0.25); + border-radius: 1px; + color: #222 !important; + display: flex !important; + + &:after, + &::before { + border-top-color: transparent !important; + } +} diff --git a/src/core/client/ui/components/Tooltip/Tooltip.tsx b/src/core/client/ui/components/Tooltip/Tooltip.tsx new file mode 100644 index 000000000..dffda088a --- /dev/null +++ b/src/core/client/ui/components/Tooltip/Tooltip.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import ReactTooltip from "react-tooltip"; +import * as styles from "./Tooltip.css"; + +class Tooltip extends React.Component { + public render() { + return ; + } +} + +export default Tooltip; diff --git a/src/core/client/ui/components/Tooltip/index.ts b/src/core/client/ui/components/Tooltip/index.ts new file mode 100644 index 000000000..9474b3888 --- /dev/null +++ b/src/core/client/ui/components/Tooltip/index.ts @@ -0,0 +1,2 @@ +export * from "./Tooltip"; +export { default } from "./Tooltip"; diff --git a/src/core/client/ui/components/index.ts b/src/core/client/ui/components/index.ts index 54643cb2a..6e1fcd8a6 100644 --- a/src/core/client/ui/components/index.ts +++ b/src/core/client/ui/components/index.ts @@ -2,3 +2,5 @@ export { default as BaseButton } from "./BaseButton"; export { default as Button } from "./Button"; export { default as Center } from "./Center"; export { default as Typography } from "./Typography"; +export { default as Tooltip } from "./Tooltip"; +export { default as Input } from "./Input"; From b77f9b8eaf14f021918276e388a0856b674a6419 Mon Sep 17 00:00:00 2001 From: okbel Date: Fri, 6 Jul 2018 23:44:29 -0300 Subject: [PATCH 06/69] Permalink ui --- package-lock.json | 161 ++++++++++++++++-- package.json | 3 + src/core/client/stream/components/Comment.css | 10 +- src/core/client/stream/components/Comment.tsx | 18 +- .../client/stream/components/Permalink.tsx | 0 src/core/client/ui/components/Input/Input.css | 11 ++ src/core/client/ui/components/Input/Input.tsx | 14 ++ src/core/client/ui/components/Input/index.ts | 2 + .../client/ui/components/Tooltip/Tooltip.css | 14 ++ .../client/ui/components/Tooltip/Tooltip.tsx | 11 ++ .../client/ui/components/Tooltip/index.ts | 2 + src/core/client/ui/components/index.ts | 2 + 12 files changed, 230 insertions(+), 18 deletions(-) create mode 100644 src/core/client/stream/components/Permalink.tsx create mode 100644 src/core/client/ui/components/Input/Input.css create mode 100644 src/core/client/ui/components/Input/Input.tsx create mode 100644 src/core/client/ui/components/Input/index.ts create mode 100644 src/core/client/ui/components/Tooltip/Tooltip.css create mode 100644 src/core/client/ui/components/Tooltip/Tooltip.tsx create mode 100644 src/core/client/ui/components/Tooltip/index.ts diff --git a/package-lock.json b/package-lock.json index c6dd91c93..c8a6caf98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1612,7 +1612,6 @@ "version": "16.4.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.2.tgz", "integrity": "sha512-oVcVteCDNiVc/fkDjowRfAZQDEOR76j3CJ3FvwXNvfV6zJguhghy1lMgpAzYox+9AZsWch+JPV6Imml3wvIUeg==", - "dev": true, "requires": { "csstype": "^2.2.0" } @@ -1641,6 +1640,14 @@ "@types/react": "*" } }, + "@types/react-tooltip": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/react-tooltip/-/react-tooltip-3.3.5.tgz", + "integrity": "sha512-wpWzjtMWBPymIoYjqZTeWX1v5dJe4V1akmcTM6iZwSS/cL8jdi6dFt4BoLXDOxgL5tEe/9yVBlQD+MAYvexBfw==", + "requires": { + "@types/react": "*" + } + }, "@types/recompose": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/@types/recompose/-/recompose-0.26.1.tgz", @@ -2050,6 +2057,14 @@ "acorn": "^5.0.0" } }, + "add-dom-event-listener": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.0.2.tgz", + "integrity": "sha1-j67SxBAIchzxEdodMNmVuFvkK+0=", + "requires": { + "object-assign": "4.x" + } + }, "address": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz", @@ -4166,7 +4181,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, "requires": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" @@ -5076,8 +5090,7 @@ "classnames": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==", - "dev": true + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, "clean-css": { "version": "4.1.11", @@ -5369,12 +5382,25 @@ "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==", "dev": true }, + "component-classes": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz", + "integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=", + "requires": { + "component-indexof": "0.0.3" + } + }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, + "component-indexof": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz", + "integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ=" + }, "compressible": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz", @@ -5881,6 +5907,15 @@ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, + "css-animation": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.4.1.tgz", + "integrity": "sha1-W4gTEl3g+7uwu+G0cq6EIhRpt6g=", + "requires": { + "babel-runtime": "6.x", + "component-classes": "^1.2.5" + } + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -6248,8 +6283,7 @@ "csstype": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.5.tgz", - "integrity": "sha512-EGMjeoiN3aqEX5u/cyH5mSdGBDGdLcCQvcEcBWNGFSPXKd9uOTIeVG91YQ22OxI44DKpvI+4C7VUSmEpsHWJaA==", - "dev": true + "integrity": "sha512-EGMjeoiN3aqEX5u/cyH5mSdGBDGdLcCQvcEcBWNGFSPXKd9uOTIeVG91YQ22OxI44DKpvI+4C7VUSmEpsHWJaA==" }, "currently-unhandled": { "version": "0.4.1", @@ -7019,6 +7053,11 @@ "webfontloader": "^1.6.28" } }, + "dom-align": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.8.0.tgz", + "integrity": "sha512-B85D4ef2Gj5lw0rK0KM2+D5/pH7yqNxg2mB+E8uzFaolpm7RQmsxEfjyEuNiF8UBBkffumYDeKRzTzc3LePP+w==" + }, "dom-converter": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", @@ -11305,8 +11344,7 @@ "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { "version": "3.12.0", @@ -11829,6 +11867,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", @@ -11899,6 +11942,16 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, "lodash.isempty": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", @@ -12050,7 +12103,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, "requires": { "js-tokens": "^3.0.0" } @@ -12939,8 +12991,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -15853,7 +15904,6 @@ "version": "15.6.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", - "dev": true, "requires": { "loose-envify": "^1.3.1", "object-assign": "^4.1.1" @@ -16082,6 +16132,81 @@ "strip-json-comments": "~2.0.1" } }, + "rc-align": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.3.tgz", + "integrity": "sha512-h5KgyB5IXYR7iKpYFcMr54cuQ2eozPCZ11kbXPG5+6CWvmyJ+c0R/yjndVndiNk2G3MKcTMbJNdDv5DIckLAxQ==", + "requires": { + "babel-runtime": "^6.26.0", + "dom-align": "^1.7.0", + "prop-types": "^15.5.8", + "rc-util": "^4.0.4" + } + }, + "rc-animate": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.4.4.tgz", + "integrity": "sha512-DjJLTUQj7XKKcuS8cczN0uOLfuSmgrVXFGieP1SZc87xUUTFGh8B/KjNmEtlfvxkSrSuVfb2rrEPER4SqKUtEA==", + "requires": { + "babel-runtime": "6.x", + "css-animation": "^1.3.2", + "prop-types": "15.x" + } + }, + "rc-tooltip": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.2.tgz", + "integrity": "sha512-vsF29ohlfgr7lEP12aJ5j4U/4hzqSBYjWQo8I09re+q95v1o4nDjH1q/B3qFkf9aml2FbgdkJw9KYz/zXUgApA==", + "requires": { + "babel-runtime": "6.x", + "prop-types": "^15.5.8", + "rc-trigger": "^2.2.2" + } + }, + "rc-trigger": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.5.4.tgz", + "integrity": "sha512-clgXOdazDW2qg4vTZSAExpvOuojPNuMoamG+SxAm5Ih+rpVcrtEiDlDZWY4yUHyfEWJZBzgbrr4np/z2FK6RfA==", + "requires": { + "babel-runtime": "6.x", + "classnames": "^2.2.6", + "prop-types": "15.x", + "rc-align": "^2.4.0", + "rc-animate": "2.x", + "rc-util": "^4.4.0" + } + }, + "rc-util": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.5.1.tgz", + "integrity": "sha512-PdCmHyBBodZdw6Oaikt0l+/R79IcRXpYkTrqD/Rbl4ZdoOi61t5TtEe40Q+A7rkWG5U1xjcN+h8j9H6GdtnICw==", + "requires": { + "add-dom-event-listener": "1.x", + "babel-runtime": "6.x", + "prop-types": "^15.5.10", + "shallowequal": "^0.2.2" + }, + "dependencies": { + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "shallowequal": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-0.2.2.tgz", + "integrity": "sha1-HjL9W8q2rWiKSBLLDMBO/HXHAU4=", + "requires": { + "lodash.keys": "^3.1.2" + } + } + } + }, "react": { "version": "16.4.1", "resolved": "https://registry.npmjs.org/react/-/react-16.4.1.tgz", @@ -16487,6 +16612,15 @@ "react-is": "^16.4.1" } }, + "react-tooltip": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-3.6.1.tgz", + "integrity": "sha512-4NVjHNIx1ZazFYBNP044DHW0cr95Qaq0DSwWbrEQ7VyE8AxemHDjp0DoYvV8wilK9vR9jMlSwDW6ebRgbk3aHw==", + "requires": { + "classnames": "^2.2.5", + "prop-types": "^15.6.0" + } + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -16673,8 +16807,7 @@ "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { "version": "0.12.4", diff --git a/package.json b/package.json index 820605d35..e8082799a 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "author": "", "license": "Apache-2.0", "dependencies": { + "@types/react-tooltip": "^3.3.5", "apollo-server-express": "^1.3.6", "bunyan": "^1.8.12", "convict": "^4.3.0", @@ -45,6 +46,8 @@ "mongodb": "^3.0.10", "passport": "^0.4.0", "performance-now": "^2.1.0", + "rc-tooltip": "^3.7.2", + "react-tooltip": "^3.6.1", "subscriptions-transport-ws": "^0.9.11", "uuid": "^3.2.1" }, diff --git a/src/core/client/stream/components/Comment.css b/src/core/client/stream/components/Comment.css index d43780d8f..8e5301ecd 100644 --- a/src/core/client/stream/components/Comment.css +++ b/src/core/client/stream/components/Comment.css @@ -3,9 +3,17 @@ } .gutterBottom { - margin-bottom: calc(2px * $spacing-unit); + margin-bottom: calc(2 px * $spacing-unit); } .author { font-weight: $font-weight-medium; } + +.shareButton { + padding: 10px 0; +} + +.input { + margin-right: 5px; +} diff --git a/src/core/client/stream/components/Comment.tsx b/src/core/client/stream/components/Comment.tsx index c1b3f9303..1f4e11b1c 100644 --- a/src/core/client/stream/components/Comment.tsx +++ b/src/core/client/stream/components/Comment.tsx @@ -1,9 +1,7 @@ import cn from "classnames"; import React from "react"; import { StatelessComponent } from "react"; - -import { Typography } from "talk-ui/components"; - +import { Button, Input, Tooltip, Typography } from "talk-ui/components"; import * as styles from "./Comment.css"; export interface CommentProps { @@ -25,6 +23,20 @@ const Comment: StatelessComponent = props => { {props.author && props.author.username} {props.body} +
+ + + + + +
); }; diff --git a/src/core/client/stream/components/Permalink.tsx b/src/core/client/stream/components/Permalink.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/core/client/ui/components/Input/Input.css b/src/core/client/ui/components/Input/Input.css new file mode 100644 index 000000000..4d2e9e88a --- /dev/null +++ b/src/core/client/ui/components/Input/Input.css @@ -0,0 +1,11 @@ +.root { + font-family: "Source Sans Pro"; + font-weight: 400; + font-size: 16px; + letter-spacing: calc(0.57em / 16); + background: #ffffff; + border: 1px solid #979797; + box-sizing: border-box; + border-radius: 1px; + padding: 5px 20px; +} diff --git a/src/core/client/ui/components/Input/Input.tsx b/src/core/client/ui/components/Input/Input.tsx new file mode 100644 index 000000000..261b3b1af --- /dev/null +++ b/src/core/client/ui/components/Input/Input.tsx @@ -0,0 +1,14 @@ +import cn from "classnames"; +import React, { InputHTMLAttributes, StatelessComponent } from "react"; + +import * as styles from "./Input.css"; + +interface InnerProps extends InputHTMLAttributes { + classes?: typeof styles; +} + +const Input: StatelessComponent = ({ className, ...rest }) => { + return ; +}; + +export default Input; diff --git a/src/core/client/ui/components/Input/index.ts b/src/core/client/ui/components/Input/index.ts new file mode 100644 index 000000000..ae0d7a775 --- /dev/null +++ b/src/core/client/ui/components/Input/index.ts @@ -0,0 +1,2 @@ +export * from "./Input"; +export { default } from "./Input"; diff --git a/src/core/client/ui/components/Tooltip/Tooltip.css b/src/core/client/ui/components/Tooltip/Tooltip.css new file mode 100644 index 000000000..e3de3d8fe --- /dev/null +++ b/src/core/client/ui/components/Tooltip/Tooltip.css @@ -0,0 +1,14 @@ +.root { + background: #ffffff !important; + border: 1px solid #c9cacb; + box-sizing: border-box; + box-shadow: 1px 0px 4px rgba(0, 0, 0, 0.25); + border-radius: 1px; + color: #222 !important; + display: flex !important; + + &:after, + &::before { + border-top-color: transparent !important; + } +} diff --git a/src/core/client/ui/components/Tooltip/Tooltip.tsx b/src/core/client/ui/components/Tooltip/Tooltip.tsx new file mode 100644 index 000000000..dffda088a --- /dev/null +++ b/src/core/client/ui/components/Tooltip/Tooltip.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import ReactTooltip from "react-tooltip"; +import * as styles from "./Tooltip.css"; + +class Tooltip extends React.Component { + public render() { + return ; + } +} + +export default Tooltip; diff --git a/src/core/client/ui/components/Tooltip/index.ts b/src/core/client/ui/components/Tooltip/index.ts new file mode 100644 index 000000000..9474b3888 --- /dev/null +++ b/src/core/client/ui/components/Tooltip/index.ts @@ -0,0 +1,2 @@ +export * from "./Tooltip"; +export { default } from "./Tooltip"; diff --git a/src/core/client/ui/components/index.ts b/src/core/client/ui/components/index.ts index 54643cb2a..6e1fcd8a6 100644 --- a/src/core/client/ui/components/index.ts +++ b/src/core/client/ui/components/index.ts @@ -2,3 +2,5 @@ export { default as BaseButton } from "./BaseButton"; export { default as Button } from "./Button"; export { default as Center } from "./Center"; export { default as Typography } from "./Typography"; +export { default as Tooltip } from "./Tooltip"; +export { default as Input } from "./Input"; From 205ef6b4a445cad84985538d527ff477b10a50ee Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 9 Jul 2018 11:04:16 -0300 Subject: [PATCH 07/69] Adding Copy to clipboard functionality --- package-lock.json | 30 +++++++++++++++++++ package.json | 2 ++ .../client/stream/components/Comment.spec.tsx | 2 ++ src/core/client/stream/components/Comment.tsx | 16 ++++++++-- .../stream/containers/CommentContainer.tsx | 1 + .../client/ui/components/Tooltip/Tooltip.css | 5 ++++ .../client/ui/components/Tooltip/Tooltip.tsx | 15 ++++++++-- 7 files changed, 66 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c8a6caf98..9f3848257 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1616,6 +1616,14 @@ "csstype": "^2.2.0" } }, + "@types/react-copy-to-clipboard": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-4.2.5.tgz", + "integrity": "sha512-5LggaWWlMcgehfeDmr4FZmK8MXntzxLYERFdrXk72ye6QwpoZpyYFGgUM+xGVVtIP2WXlor8twZTXK1xckEDYw==", + "requires": { + "@types/react": "*" + } + }, "@types/react-dom": { "version": "16.0.6", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.0.6.tgz", @@ -5591,6 +5599,14 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "copy-to-clipboard": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz", + "integrity": "sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw==", + "requires": { + "toggle-selection": "^1.0.3" + } + }, "copy-webpack-plugin": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.2.tgz", @@ -16219,6 +16235,15 @@ "prop-types": "^15.6.0" } }, + "react-copy-to-clipboard": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz", + "integrity": "sha512-ELKq31/E3zjFs5rDWNCfFL4NvNFQvGRoJdAKReD/rUPA+xxiLPQmZBZBvy2vgH7V0GE9isIQpT9WXbwIVErYdA==", + "requires": { + "copy-to-clipboard": "^3", + "prop-types": "^15.5.8" + } + }, "react-dev-utils": { "version": "6.0.0-next.3e165448", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-6.0.0-next.3e165448.tgz", @@ -18888,6 +18913,11 @@ } } }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" + }, "topo": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.0.tgz", diff --git a/package.json b/package.json index e8082799a..d2defed61 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "author": "", "license": "Apache-2.0", "dependencies": { + "@types/react-copy-to-clipboard": "^4.2.5", "@types/react-tooltip": "^3.3.5", "apollo-server-express": "^1.3.6", "bunyan": "^1.8.12", @@ -47,6 +48,7 @@ "passport": "^0.4.0", "performance-now": "^2.1.0", "rc-tooltip": "^3.7.2", + "react-copy-to-clipboard": "^5.0.1", "react-tooltip": "^3.6.1", "subscriptions-transport-ws": "^0.9.11", "uuid": "^3.2.1" diff --git a/src/core/client/stream/components/Comment.spec.tsx b/src/core/client/stream/components/Comment.spec.tsx index 6008bfc3b..4f7448a93 100644 --- a/src/core/client/stream/components/Comment.spec.tsx +++ b/src/core/client/stream/components/Comment.spec.tsx @@ -4,6 +4,7 @@ import Comment from "./Comment"; it("renders username and body", () => { const props = { + id: "id", author: { username: "Marvin", }, @@ -16,6 +17,7 @@ it("renders username and body", () => { it("renders with gutterBottom", () => { const props = { + id: "id", author: { username: "Marvin", }, diff --git a/src/core/client/stream/components/Comment.tsx b/src/core/client/stream/components/Comment.tsx index 1f4e11b1c..b594cf27d 100644 --- a/src/core/client/stream/components/Comment.tsx +++ b/src/core/client/stream/components/Comment.tsx @@ -1,10 +1,12 @@ import cn from "classnames"; import React from "react"; import { StatelessComponent } from "react"; +import CopyToClipboard from "react-copy-to-clipboard"; import { Button, Input, Tooltip, Typography } from "talk-ui/components"; import * as styles from "./Comment.css"; export interface CommentProps { + id: string; className?: string; author: { username: string; @@ -32,9 +34,17 @@ const Comment: StatelessComponent = props => { > Share - - - + + + + { + console.log("ey"); + }} + > + + diff --git a/src/core/client/stream/containers/CommentContainer.tsx b/src/core/client/stream/containers/CommentContainer.tsx index 9a4d03cd8..3d7956dc6 100644 --- a/src/core/client/stream/containers/CommentContainer.tsx +++ b/src/core/client/stream/containers/CommentContainer.tsx @@ -17,6 +17,7 @@ const CommentContainer: StatelessComponent = props => { const enhanced = withFragmentContainer<{ data: Data }>( graphql` fragment CommentContainer on Comment { + id author { username } diff --git a/src/core/client/ui/components/Tooltip/Tooltip.css b/src/core/client/ui/components/Tooltip/Tooltip.css index e3de3d8fe..1a1553256 100644 --- a/src/core/client/ui/components/Tooltip/Tooltip.css +++ b/src/core/client/ui/components/Tooltip/Tooltip.css @@ -1,4 +1,5 @@ .root { + padding: 6px 10px; background: #ffffff !important; border: 1px solid #c9cacb; box-sizing: border-box; @@ -12,3 +13,7 @@ border-top-color: transparent !important; } } + +.clickable { + pointer-events: all; +} diff --git a/src/core/client/ui/components/Tooltip/Tooltip.tsx b/src/core/client/ui/components/Tooltip/Tooltip.tsx index dffda088a..f6e1a9cf0 100644 --- a/src/core/client/ui/components/Tooltip/Tooltip.tsx +++ b/src/core/client/ui/components/Tooltip/Tooltip.tsx @@ -1,10 +1,21 @@ +import cn from "classnames"; import React from "react"; import ReactTooltip from "react-tooltip"; import * as styles from "./Tooltip.css"; -class Tooltip extends React.Component { +interface InnerProps extends ReactTooltip.Props { + clickable: boolean; +} + +class Tooltip extends React.Component { public render() { - return ; + const { clickable } = this.props; + return ( + + ); } } From 50de9a7f84366481a9a16d3b4dc7895860e717f0 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 9 Jul 2018 11:37:08 -0300 Subject: [PATCH 08/69] WIP --- src/core/client/stream/components/App.tsx | 5 +++++ .../client/stream/containers/AppContainer.tsx | 5 +++++ src/core/client/stream/local/local.graphql | 1 + src/core/client/stream/queries/AppQuery.tsx | 18 ++++++++++++++++-- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/core/client/stream/components/App.tsx b/src/core/client/stream/components/App.tsx index dde8e386c..56bdf54a2 100644 --- a/src/core/client/stream/components/App.tsx +++ b/src/core/client/stream/components/App.tsx @@ -15,9 +15,14 @@ export interface AppProps { isClosed: boolean; comments: any | null; } | null; + comment?: any | null; } const App: StatelessComponent = props => { + console.log(props); + if (props.comment) { + return
Comment
; + } if (props.assets) { return ; } diff --git a/src/core/client/stream/containers/AppContainer.tsx b/src/core/client/stream/containers/AppContainer.tsx index 02abbf314..07ee8b105 100644 --- a/src/core/client/stream/containers/AppContainer.tsx +++ b/src/core/client/stream/containers/AppContainer.tsx @@ -20,8 +20,13 @@ const enhanced = withFragmentContainer<{ data: Data }>( fragment AppContainer on Query @argumentDefinitions( assetID: { type: "ID!" } + commentID: { type: "ID" } showAssetList: { type: "Boolean!" } + showPermalink: { type: "Boolean!" } ) { + comment(id: $commentID) @include(if: $showPermalink) { + id + } assets @include(if: $showAssetList) { ...AssetListContainer_assets } diff --git a/src/core/client/stream/local/local.graphql b/src/core/client/stream/local/local.graphql index 3359458d0..59c829490 100644 --- a/src/core/client/stream/local/local.graphql +++ b/src/core/client/stream/local/local.graphql @@ -6,6 +6,7 @@ type Network { type Local { network: Network! assetID: String + commentID: String } extend type Query { diff --git a/src/core/client/stream/queries/AppQuery.tsx b/src/core/client/stream/queries/AppQuery.tsx index 4dc61115c..86cbb69ff 100644 --- a/src/core/client/stream/queries/AppQuery.tsx +++ b/src/core/client/stream/queries/AppQuery.tsx @@ -33,9 +33,19 @@ const AppQuery: StatelessComponent = props => { return ( query={graphql` - query AppQuery($showAssetList: Boolean!, $assetID: ID!) { + query AppQuery( + $assetID: ID! + $commentID: ID + $showAssetList: Boolean! + $showPermalink: Boolean! + ) { ...AppContainer - @arguments(showAssetList: $showAssetList, assetID: $assetID) + @arguments( + assetID: $assetID + commentID: $commentID + showAssetList: $showAssetList + showPermalink: $showPermalink + ) } `} variables={{ @@ -43,6 +53,9 @@ const AppQuery: StatelessComponent = props => { assetID: props.local.assetID || (null as any), // TODO: This is set to false, as server does not support querying assets yet. showAssetList: !props.local.assetID && false, + + commentID: props.local.commentID || (null as any), + showPermalink: false, }} render={render} /> @@ -53,6 +66,7 @@ const enhanced = withLocalStateContainer( graphql` fragment AppQueryLocal on Local { assetID + commentID } ` )(AppQuery); From 6210ae60778e1c633364088979bec781c78a8ccb Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 9 Jul 2018 11:44:52 -0300 Subject: [PATCH 09/69] clean request --- .../client/stream/containers/AppContainer.tsx | 5 ----- src/core/client/stream/local/local.graphql | 1 - src/core/client/stream/queries/AppQuery.tsx | 18 ++---------------- 3 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/core/client/stream/containers/AppContainer.tsx b/src/core/client/stream/containers/AppContainer.tsx index 07ee8b105..02abbf314 100644 --- a/src/core/client/stream/containers/AppContainer.tsx +++ b/src/core/client/stream/containers/AppContainer.tsx @@ -20,13 +20,8 @@ const enhanced = withFragmentContainer<{ data: Data }>( fragment AppContainer on Query @argumentDefinitions( assetID: { type: "ID!" } - commentID: { type: "ID" } showAssetList: { type: "Boolean!" } - showPermalink: { type: "Boolean!" } ) { - comment(id: $commentID) @include(if: $showPermalink) { - id - } assets @include(if: $showAssetList) { ...AssetListContainer_assets } diff --git a/src/core/client/stream/local/local.graphql b/src/core/client/stream/local/local.graphql index 59c829490..3359458d0 100644 --- a/src/core/client/stream/local/local.graphql +++ b/src/core/client/stream/local/local.graphql @@ -6,7 +6,6 @@ type Network { type Local { network: Network! assetID: String - commentID: String } extend type Query { diff --git a/src/core/client/stream/queries/AppQuery.tsx b/src/core/client/stream/queries/AppQuery.tsx index 86cbb69ff..d1256d249 100644 --- a/src/core/client/stream/queries/AppQuery.tsx +++ b/src/core/client/stream/queries/AppQuery.tsx @@ -33,19 +33,9 @@ const AppQuery: StatelessComponent = props => { return ( query={graphql` - query AppQuery( - $assetID: ID! - $commentID: ID - $showAssetList: Boolean! - $showPermalink: Boolean! - ) { + query AppQuery($assetID: ID!, $showAssetList: Boolean!) { ...AppContainer - @arguments( - assetID: $assetID - commentID: $commentID - showAssetList: $showAssetList - showPermalink: $showPermalink - ) + @arguments(assetID: $assetID, showAssetList: $showAssetList) } `} variables={{ @@ -53,9 +43,6 @@ const AppQuery: StatelessComponent = props => { assetID: props.local.assetID || (null as any), // TODO: This is set to false, as server does not support querying assets yet. showAssetList: !props.local.assetID && false, - - commentID: props.local.commentID || (null as any), - showPermalink: false, }} render={render} /> @@ -66,7 +53,6 @@ const enhanced = withLocalStateContainer( graphql` fragment AppQueryLocal on Local { assetID - commentID } ` )(AppQuery); From b15ea811e5265a0cfaa80a5db5af5f184f74724e Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 9 Jul 2018 14:33:28 -0300 Subject: [PATCH 10/69] wip --- src/core/client/stream/components/Comment.tsx | 34 ++++++++----------- src/core/client/tslint.json | 19 ++++------- .../Tooltip.css => Popover/Popover.css} | 0 .../client/ui/components/Popover/Popover.tsx | 32 +++++++++++++++++ .../client/ui/components/Popover/index.ts | 2 ++ .../ui/components/TextField/TextField.css | 11 ++++++ .../ui/components/TextField/TextField.d.ts | 1 + .../ui/components/TextField/TextField.tsx | 14 ++++++++ .../client/ui/components/TextField/index.ts | 2 ++ .../client/ui/components/Tooltip/Tooltip.tsx | 22 ------------ .../client/ui/components/Tooltip/index.ts | 2 -- src/core/client/ui/components/index.ts | 2 +- src/tsconfig.json | 25 ++++---------- tslint.json | 11 ++---- 14 files changed, 92 insertions(+), 85 deletions(-) rename src/core/client/ui/components/{Tooltip/Tooltip.css => Popover/Popover.css} (100%) create mode 100644 src/core/client/ui/components/Popover/Popover.tsx create mode 100644 src/core/client/ui/components/Popover/index.ts create mode 100644 src/core/client/ui/components/TextField/TextField.css create mode 100644 src/core/client/ui/components/TextField/TextField.d.ts create mode 100644 src/core/client/ui/components/TextField/TextField.tsx create mode 100644 src/core/client/ui/components/TextField/index.ts delete mode 100644 src/core/client/ui/components/Tooltip/Tooltip.tsx delete mode 100644 src/core/client/ui/components/Tooltip/index.ts diff --git a/src/core/client/stream/components/Comment.tsx b/src/core/client/stream/components/Comment.tsx index b594cf27d..cc13ae115 100644 --- a/src/core/client/stream/components/Comment.tsx +++ b/src/core/client/stream/components/Comment.tsx @@ -2,7 +2,7 @@ import cn from "classnames"; import React from "react"; import { StatelessComponent } from "react"; import CopyToClipboard from "react-copy-to-clipboard"; -import { Button, Input, Tooltip, Typography } from "talk-ui/components"; +import { Button, Input, Popover, Typography } from "talk-ui/components"; import * as styles from "./Comment.css"; export interface CommentProps { @@ -15,6 +15,8 @@ export interface CommentProps { gutterBottom?: boolean; } +// make a permalink popover + const Comment: StatelessComponent = props => { const rootClassName = cn(styles.root, props.className, { [styles.gutterBottom]: props.gutterBottom, @@ -26,26 +28,18 @@ const Comment: StatelessComponent = props => { {props.body}
- + +
+ } > - Share - - - - - { - console.log("ey"); - }} - > - - - + + ); diff --git a/src/core/client/tslint.json b/src/core/client/tslint.json index 9abc9b921..0079a6de1 100644 --- a/src/core/client/tslint.json +++ b/src/core/client/tslint.json @@ -1,20 +1,13 @@ { - "extends": [ - "../../../tslint.json", - "tslint-react" - ], + "extends": ["../../../tslint.json", "tslint-react"], "rules": { + "jsx-curly-spacing": false, "jsx-no-multiline-js": false, - "jsx-boolean-value": [ - true, - "never" - ] + "jsx-boolean-value": [true, "never"] }, "jsRules": { + "jsx-curly-spacing": false, "jsx-no-multiline-js": false, - "jsx-boolean-value": [ - true, - "never" - ] + "jsx-boolean-value": [true, "never"] } -} \ No newline at end of file +} diff --git a/src/core/client/ui/components/Tooltip/Tooltip.css b/src/core/client/ui/components/Popover/Popover.css similarity index 100% rename from src/core/client/ui/components/Tooltip/Tooltip.css rename to src/core/client/ui/components/Popover/Popover.css diff --git a/src/core/client/ui/components/Popover/Popover.tsx b/src/core/client/ui/components/Popover/Popover.tsx new file mode 100644 index 000000000..a3c2b9b4b --- /dev/null +++ b/src/core/client/ui/components/Popover/Popover.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import { Manager, Popper, Reference } from "react-popper"; +// import * as styles from "./Popover.css"; + +interface InnerProps { + body: React.ReactElement; + children: React.ReactElement; +} + +class Popover extends React.Component { + public render() { + const { children, body } = this.props; + return ( + + + {({ ref }) => React.cloneElement(children, { ref })} + + + {({ ref, style, placement, arrowProps }) => + React.cloneElement(body, { + ref, + style, + "data-placement": placement, + }) + } + + + ); + } +} + +export default Popover; diff --git a/src/core/client/ui/components/Popover/index.ts b/src/core/client/ui/components/Popover/index.ts new file mode 100644 index 000000000..7e46e3708 --- /dev/null +++ b/src/core/client/ui/components/Popover/index.ts @@ -0,0 +1,2 @@ +export * from "./Popover"; +export { default } from "./Popover"; diff --git a/src/core/client/ui/components/TextField/TextField.css b/src/core/client/ui/components/TextField/TextField.css new file mode 100644 index 000000000..4d2e9e88a --- /dev/null +++ b/src/core/client/ui/components/TextField/TextField.css @@ -0,0 +1,11 @@ +.root { + font-family: "Source Sans Pro"; + font-weight: 400; + font-size: 16px; + letter-spacing: calc(0.57em / 16); + background: #ffffff; + border: 1px solid #979797; + box-sizing: border-box; + border-radius: 1px; + padding: 5px 20px; +} diff --git a/src/core/client/ui/components/TextField/TextField.d.ts b/src/core/client/ui/components/TextField/TextField.d.ts new file mode 100644 index 000000000..f99662ba2 --- /dev/null +++ b/src/core/client/ui/components/TextField/TextField.d.ts @@ -0,0 +1 @@ +export const root: string; diff --git a/src/core/client/ui/components/TextField/TextField.tsx b/src/core/client/ui/components/TextField/TextField.tsx new file mode 100644 index 000000000..d1a623662 --- /dev/null +++ b/src/core/client/ui/components/TextField/TextField.tsx @@ -0,0 +1,14 @@ +import cn from "classnames"; +import React, { InputHTMLAttributes, StatelessComponent } from "react"; + +import * as styles from "./TextField"; + +interface InnerProps extends InputHTMLAttributes { + classes?: typeof styles; +} + +const Input: StatelessComponent = ({ className, ...rest }) => { + return ; +}; + +export default Input; diff --git a/src/core/client/ui/components/TextField/index.ts b/src/core/client/ui/components/TextField/index.ts new file mode 100644 index 000000000..e38acd4ea --- /dev/null +++ b/src/core/client/ui/components/TextField/index.ts @@ -0,0 +1,2 @@ +export * from "./TextField"; +export { default } from "./TextField"; diff --git a/src/core/client/ui/components/Tooltip/Tooltip.tsx b/src/core/client/ui/components/Tooltip/Tooltip.tsx deleted file mode 100644 index f6e1a9cf0..000000000 --- a/src/core/client/ui/components/Tooltip/Tooltip.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import cn from "classnames"; -import React from "react"; -import ReactTooltip from "react-tooltip"; -import * as styles from "./Tooltip.css"; - -interface InnerProps extends ReactTooltip.Props { - clickable: boolean; -} - -class Tooltip extends React.Component { - public render() { - const { clickable } = this.props; - return ( - - ); - } -} - -export default Tooltip; diff --git a/src/core/client/ui/components/Tooltip/index.ts b/src/core/client/ui/components/Tooltip/index.ts deleted file mode 100644 index 9474b3888..000000000 --- a/src/core/client/ui/components/Tooltip/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./Tooltip"; -export { default } from "./Tooltip"; diff --git a/src/core/client/ui/components/index.ts b/src/core/client/ui/components/index.ts index 6e1fcd8a6..9f16ee536 100644 --- a/src/core/client/ui/components/index.ts +++ b/src/core/client/ui/components/index.ts @@ -2,5 +2,5 @@ export { default as BaseButton } from "./BaseButton"; export { default as Button } from "./Button"; export { default as Center } from "./Center"; export { default as Typography } from "./Typography"; -export { default as Tooltip } from "./Tooltip"; +export { default as Popover } from "./Popover"; export { default as Input } from "./Input"; diff --git a/src/tsconfig.json b/src/tsconfig.json index eddf98d29..857892f4d 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -9,26 +9,13 @@ "outDir": "../dist", // See https://github.com/prismagraphql/graphql-request/issues/26 for why we // have to include "dom" here. - "lib": [ - "es6", - "esnext.asynciterable", - "dom" - ], + "lib": ["es6", "esnext.asynciterable", "dom"], "baseUrl": "./", "paths": { - "talk-server/*": [ - "./core/server/*" - ], - "talk-common/*": [ - "./core/common/*" - ] + "talk-server/*": ["./core/server/*"], + "talk-common/*": ["./core/common/*"] } }, - "include": [ - "./**/*" - ], - "exclude": [ - "node_modules", - "./core/client" - ] -} \ No newline at end of file + "include": ["./**/*"], + "exclude": ["node_modules", "./core/client"] +} diff --git a/tslint.json b/tslint.json index 68001f8c6..853208eb0 100644 --- a/tslint.json +++ b/tslint.json @@ -7,10 +7,7 @@ "rules": { "prettier": true, "object-literal-sort-keys": false, - "interface-name": [ - true, - "never-prefix" - ], + "interface-name": [true, "never-prefix"], "no-switch-case-fall-through": true, "member-ordering": false, "variable-name": [ @@ -35,8 +32,6 @@ ] }, "linterOptions": { - "exclude": [ - "**/node_modules/**/*" - ] + "exclude": ["**/node_modules/**/*"] } -} \ No newline at end of file +} From 155b8c731673f3f63dcacefe0de81387ff8f232e Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 9 Jul 2018 16:39:04 -0300 Subject: [PATCH 11/69] progress --- package-lock.json | 67 ++++++++++++++----- package.json | 1 + src/core/client/stream/components/Comment.tsx | 22 ++++++ .../client/ui/components/Popover/Popover.tsx | 9 ++- .../ui/components/TextField/TextField.tsx | 2 +- 5 files changed, 83 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9f3848257..2321cd2cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2390,8 +2390,7 @@ "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, "asn1": { "version": "0.2.3", @@ -5876,6 +5875,15 @@ "sha.js": "^2.4.8" } }, + "create-react-context": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.2.tgz", + "integrity": "sha512-KkpaLARMhsTsgp0d2NA/R94F/eDLbhXERdIq3LvX2biCAXcDvHYoOqHfWCHf1+OLj+HKBotLG3KqaOOf+C1C+A==", + "requires": { + "fbjs": "^0.8.0", + "gud": "^1.0.0" + } + }, "cross-fetch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.0.0.tgz", @@ -7288,7 +7296,6 @@ "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "dev": true, "requires": { "iconv-lite": "~0.4.13" } @@ -7958,7 +7965,6 @@ "version": "0.8.17", "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", - "dev": true, "requires": { "core-js": "^1.0.0", "isomorphic-fetch": "^2.1.1", @@ -7972,8 +7978,7 @@ "core-js": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "dev": true + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" } } }, @@ -9278,6 +9283,11 @@ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "dev": true }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" + }, "gzip-size": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", @@ -10604,8 +10614,7 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-svg": { "version": "2.1.0", @@ -10715,7 +10724,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "dev": true, "requires": { "node-fetch": "^1.0.1", "whatwg-fetch": ">=0.10.0" @@ -10725,7 +10733,6 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, "requires": { "encoding": "^0.1.11", "is-stream": "^1.0.1" @@ -13542,6 +13549,11 @@ "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", "dev": true }, + "popper.js": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.3.tgz", + "integrity": "sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU=" + }, "portfinder": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", @@ -15895,7 +15907,6 @@ "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dev": true, "requires": { "asap": "~2.0.3" } @@ -16537,6 +16548,29 @@ "integrity": "sha512-OQvgdiPfWbAjudT8Q+V2aWsySCJW0aQ3wNjfOw1ooamydEQkDxRfWqfnEhCYLneCz67d+r3kBYoZlpAx5S+VWA==", "dev": true }, + "react-popper": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.0.0.tgz", + "integrity": "sha1-uZRSFE6P5KzHf6PZWajHngemUIQ=", + "requires": { + "babel-runtime": "6.x.x", + "create-react-context": "^0.2.1", + "popper.js": "^1.14.1", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.5", + "warning": "^3.0.0" + }, + "dependencies": { + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, "react-powerplug": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/react-powerplug/-/react-powerplug-0.1.6.tgz", @@ -17842,8 +17876,7 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "setprototypeof": { "version": "1.1.0", @@ -19711,6 +19744,11 @@ } } }, + "typed-styles": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.5.tgz", + "integrity": "sha512-ht+rEe5UsdEBAa3gr64+QjUOqjOLJfWLvl5HZR5Ev9uo/OnD3p43wPeFSB1hNFc13GXQF/JU1Bn0YHLUqBRIlw==" + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -19726,8 +19764,7 @@ "ua-parser-js": { "version": "0.7.18", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", - "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==", - "dev": true + "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==" }, "uglify-js": { "version": "3.4.2", diff --git a/package.json b/package.json index d2defed61..49b0d6ea4 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "performance-now": "^2.1.0", "rc-tooltip": "^3.7.2", "react-copy-to-clipboard": "^5.0.1", + "react-popper": "^1.14.3", "react-tooltip": "^3.6.1", "subscriptions-transport-ws": "^0.9.11", "uuid": "^3.2.1" diff --git a/src/core/client/stream/components/Comment.tsx b/src/core/client/stream/components/Comment.tsx index cc13ae115..7bb017b42 100644 --- a/src/core/client/stream/components/Comment.tsx +++ b/src/core/client/stream/components/Comment.tsx @@ -2,6 +2,7 @@ import cn from "classnames"; import React from "react"; import { StatelessComponent } from "react"; import CopyToClipboard from "react-copy-to-clipboard"; +import { Manager, Popper, Reference } from "react-popper"; import { Button, Input, Popover, Typography } from "talk-ui/components"; import * as styles from "./Comment.css"; @@ -27,6 +28,27 @@ const Comment: StatelessComponent = props => { {props.author && props.author.username} {props.body} + + + {({ ref }) => ( + + )} + + + {({ ref, style, placement, arrowProps }) => ( +
+ Popper element +
+ )} +
+
{ {({ ref }) => React.cloneElement(children, { ref })} - - {({ ref, style, placement, arrowProps }) => + + {({ ref, placement, style }) => React.cloneElement(body, { ref, style, diff --git a/src/core/client/ui/components/TextField/TextField.tsx b/src/core/client/ui/components/TextField/TextField.tsx index d1a623662..ac980b102 100644 --- a/src/core/client/ui/components/TextField/TextField.tsx +++ b/src/core/client/ui/components/TextField/TextField.tsx @@ -1,7 +1,7 @@ import cn from "classnames"; import React, { InputHTMLAttributes, StatelessComponent } from "react"; -import * as styles from "./TextField"; +import * as styles from "./TextField.css"; interface InnerProps extends InputHTMLAttributes { classes?: typeof styles; From 7ee9f235421697e7b0bf3cf0e731fb9511345875 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 9 Jul 2018 18:37:46 -0300 Subject: [PATCH 12/69] work in progress --- package-lock.json | 6 +-- package.json | 2 +- src/core/client/stream/components/Comment.tsx | 39 ++----------------- .../stream/components/PermalinkPopover.tsx | 25 ++++++++++++ .../client/ui/components/Button/Button.tsx | 1 + .../client/ui/components/Popover/Popover.tsx | 23 +++++++++-- src/core/client/ui/hocs/withFowardedRefs.tsx | 9 +++++ 7 files changed, 61 insertions(+), 44 deletions(-) create mode 100644 src/core/client/stream/components/PermalinkPopover.tsx create mode 100644 src/core/client/ui/hocs/withFowardedRefs.tsx diff --git a/package-lock.json b/package-lock.json index 2321cd2cf..a0c6f82dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16549,9 +16549,9 @@ "dev": true }, "react-popper": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.0.0.tgz", - "integrity": "sha1-uZRSFE6P5KzHf6PZWajHngemUIQ=", + "version": "1.0.0-beta.6", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.0.0-beta.6.tgz", + "integrity": "sha1-yyeirFatzLr1+cQTI4cokGkkCDQ=", "requires": { "babel-runtime": "6.x.x", "create-react-context": "^0.2.1", diff --git a/package.json b/package.json index 49b0d6ea4..8dc74e5d8 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "performance-now": "^2.1.0", "rc-tooltip": "^3.7.2", "react-copy-to-clipboard": "^5.0.1", - "react-popper": "^1.14.3", + "react-popper": "^1.0.0-beta.6", "react-tooltip": "^3.6.1", "subscriptions-transport-ws": "^0.9.11", "uuid": "^3.2.1" diff --git a/src/core/client/stream/components/Comment.tsx b/src/core/client/stream/components/Comment.tsx index 7bb017b42..014989a51 100644 --- a/src/core/client/stream/components/Comment.tsx +++ b/src/core/client/stream/components/Comment.tsx @@ -1,10 +1,9 @@ import cn from "classnames"; import React from "react"; import { StatelessComponent } from "react"; -import CopyToClipboard from "react-copy-to-clipboard"; -import { Manager, Popper, Reference } from "react-popper"; -import { Button, Input, Popover, Typography } from "talk-ui/components"; +import { Typography } from "talk-ui/components"; import * as styles from "./Comment.css"; +import PermalinkPopover from "./PermalinkPopover"; export interface CommentProps { id: string; @@ -28,40 +27,8 @@ const Comment: StatelessComponent = props => { {props.author && props.author.username} {props.body} - - - {({ ref }) => ( - - )} - - - {({ ref, style, placement, arrowProps }) => ( -
- Popper element -
- )} -
-
- - - - - -
- } - > - -
+
); diff --git a/src/core/client/stream/components/PermalinkPopover.tsx b/src/core/client/stream/components/PermalinkPopover.tsx new file mode 100644 index 000000000..cd110dfe3 --- /dev/null +++ b/src/core/client/stream/components/PermalinkPopover.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import CopyToClipboard from "react-copy-to-clipboard"; +import { Button, Input, Popover } from "talk-ui/components"; + +class PermalinkPopover extends React.Component { + public render() { + const props = this.props; + return ( + + + + + + + } + > + + + ); + } +} + +export default PermalinkPopover; diff --git a/src/core/client/ui/components/Button/Button.tsx b/src/core/client/ui/components/Button/Button.tsx index dadb7a35d..127d16c2e 100644 --- a/src/core/client/ui/components/Button/Button.tsx +++ b/src/core/client/ui/components/Button/Button.tsx @@ -49,6 +49,7 @@ class Button extends React.Component { [classes.secondary]: secondary, }); + console.log(this.props); return ( ; children: React.ReactElement; + placement?: + | "auto-start" + | "auto" + | "auto-end" + | "top-start" + | "top" + | "top-end" + | "right-start" + | "right" + | "right-end" + | "bottom-end" + | "bottom" + | "bottom-start" + | "left-end" + | "left" + | "left-start"; } class Popover extends React.Component { public render() { - const { children, body } = this.props; + const { children, body, placement = "top" } = this.props; return ( {({ ref }) => React.cloneElement(children, { ref })} - {({ ref, placement, style }) => + {({ ref, style }) => React.cloneElement(body, { ref, style, - "data-placement": placement, }) } diff --git a/src/core/client/ui/hocs/withFowardedRefs.tsx b/src/core/client/ui/hocs/withFowardedRefs.tsx new file mode 100644 index 000000000..6fe7a726c --- /dev/null +++ b/src/core/client/ui/hocs/withFowardedRefs.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +export function forwardRef( + WrappedComponent: React.ComponentType +): React.RefForwardingComponent { + return React.forwardRef((props, ref) => { + return ; + }); +} From 37fb9ece668cb6ec21df4f978f5096aeb8804ca4 Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 9 Jul 2018 18:57:41 -0300 Subject: [PATCH 13/69] wip --- src/core/client/stream/components/Comment.css | 8 -------- src/core/client/stream/components/Comment.tsx | 2 +- .../stream/components/PermalinkPopover.css | 13 +++++++++++++ .../stream/components/PermalinkPopover.tsx | 19 ++++++++++++------- src/core/client/ui/components/Input/Input.css | 11 ----------- src/core/client/ui/components/Input/Input.tsx | 14 -------------- src/core/client/ui/components/Input/index.ts | 2 -- src/core/client/ui/components/index.ts | 2 +- src/core/client/ui/hocs/withFowardedRefs.tsx | 9 --------- 9 files changed, 27 insertions(+), 53 deletions(-) create mode 100644 src/core/client/stream/components/PermalinkPopover.css delete mode 100644 src/core/client/ui/components/Input/Input.css delete mode 100644 src/core/client/ui/components/Input/Input.tsx delete mode 100644 src/core/client/ui/components/Input/index.ts delete mode 100644 src/core/client/ui/hocs/withFowardedRefs.tsx diff --git a/src/core/client/stream/components/Comment.css b/src/core/client/stream/components/Comment.css index 8e5301ecd..4e23b2d02 100644 --- a/src/core/client/stream/components/Comment.css +++ b/src/core/client/stream/components/Comment.css @@ -9,11 +9,3 @@ .author { font-weight: $font-weight-medium; } - -.shareButton { - padding: 10px 0; -} - -.input { - margin-right: 5px; -} diff --git a/src/core/client/stream/components/Comment.tsx b/src/core/client/stream/components/Comment.tsx index 014989a51..a332b42a3 100644 --- a/src/core/client/stream/components/Comment.tsx +++ b/src/core/client/stream/components/Comment.tsx @@ -28,7 +28,7 @@ const Comment: StatelessComponent = props => { {props.body}
- +
); diff --git a/src/core/client/stream/components/PermalinkPopover.css b/src/core/client/stream/components/PermalinkPopover.css new file mode 100644 index 000000000..ffc0a1b6c --- /dev/null +++ b/src/core/client/stream/components/PermalinkPopover.css @@ -0,0 +1,13 @@ +.shareButton { + composes: button from "talk-ui/shared/typography.css"; + composes: buttonReset from "talk-ui/shared/buttonReset.css"; + padding: 10px 0; +} + +.textField { + margin-right: 5px; +} + +.root { + background-color: #fff; +} diff --git a/src/core/client/stream/components/PermalinkPopover.tsx b/src/core/client/stream/components/PermalinkPopover.tsx index cd110dfe3..7d9bf8ade 100644 --- a/src/core/client/stream/components/PermalinkPopover.tsx +++ b/src/core/client/stream/components/PermalinkPopover.tsx @@ -1,22 +1,27 @@ import React from "react"; import CopyToClipboard from "react-copy-to-clipboard"; -import { Button, Input, Popover } from "talk-ui/components"; +import { Button, Popover, TextField } from "talk-ui/components"; +import * as styles from "./PermalinkPopover.css"; -class PermalinkPopover extends React.Component { +interface InnerProps { + commentId: string; +} + +class PermalinkPopover extends React.Component { public render() { - const props = this.props; + const { commentId } = this.props; return ( - - +
+ +
} > - +
); } diff --git a/src/core/client/ui/components/Input/Input.css b/src/core/client/ui/components/Input/Input.css deleted file mode 100644 index 4d2e9e88a..000000000 --- a/src/core/client/ui/components/Input/Input.css +++ /dev/null @@ -1,11 +0,0 @@ -.root { - font-family: "Source Sans Pro"; - font-weight: 400; - font-size: 16px; - letter-spacing: calc(0.57em / 16); - background: #ffffff; - border: 1px solid #979797; - box-sizing: border-box; - border-radius: 1px; - padding: 5px 20px; -} diff --git a/src/core/client/ui/components/Input/Input.tsx b/src/core/client/ui/components/Input/Input.tsx deleted file mode 100644 index 261b3b1af..000000000 --- a/src/core/client/ui/components/Input/Input.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import cn from "classnames"; -import React, { InputHTMLAttributes, StatelessComponent } from "react"; - -import * as styles from "./Input.css"; - -interface InnerProps extends InputHTMLAttributes { - classes?: typeof styles; -} - -const Input: StatelessComponent = ({ className, ...rest }) => { - return ; -}; - -export default Input; diff --git a/src/core/client/ui/components/Input/index.ts b/src/core/client/ui/components/Input/index.ts deleted file mode 100644 index ae0d7a775..000000000 --- a/src/core/client/ui/components/Input/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./Input"; -export { default } from "./Input"; diff --git a/src/core/client/ui/components/index.ts b/src/core/client/ui/components/index.ts index 9f16ee536..66ed5bee4 100644 --- a/src/core/client/ui/components/index.ts +++ b/src/core/client/ui/components/index.ts @@ -3,4 +3,4 @@ export { default as Button } from "./Button"; export { default as Center } from "./Center"; export { default as Typography } from "./Typography"; export { default as Popover } from "./Popover"; -export { default as Input } from "./Input"; +export { default as TextField } from "./TextField"; diff --git a/src/core/client/ui/hocs/withFowardedRefs.tsx b/src/core/client/ui/hocs/withFowardedRefs.tsx deleted file mode 100644 index 6fe7a726c..000000000 --- a/src/core/client/ui/hocs/withFowardedRefs.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from "react"; - -export function forwardRef( - WrappedComponent: React.ComponentType -): React.RefForwardingComponent { - return React.forwardRef((props, ref) => { - return ; - }); -} From 50fdabc0c04f23e018c621c1e220346990bc75aa Mon Sep 17 00:00:00 2001 From: okbel Date: Mon, 9 Jul 2018 19:42:24 -0300 Subject: [PATCH 14/69] ui functionality --- .../stream/components/PermalinkPopover.tsx | 41 +++++++++++++++++-- .../client/ui/components/Popover/Popover.css | 4 -- .../client/ui/components/Popover/Popover.tsx | 34 ++++++++------- 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/core/client/stream/components/PermalinkPopover.tsx b/src/core/client/stream/components/PermalinkPopover.tsx index 7d9bf8ade..776edbccf 100644 --- a/src/core/client/stream/components/PermalinkPopover.tsx +++ b/src/core/client/stream/components/PermalinkPopover.tsx @@ -7,21 +7,56 @@ interface InnerProps { commentId: string; } +interface State { + copied: boolean; + showBody: boolean; +} + class PermalinkPopover extends React.Component { + public state: State = { + copied: false, + showBody: false, + }; + + public onCopy = async () => { + await this.toggleCopied(); + setTimeout(() => { + this.toggleCopied(); + }, 800); + }; + + public onClick = () => this.toggleShow(); + + public toggleShow = () => { + this.setState((state: State) => ({ + showBody: !state.showBody, + })); + }; + + public toggleCopied = () => { + this.setState((state: State) => ({ + copied: !state.copied, + })); + }; + public render() { const { commentId } = this.props; + const { copied, showBody } = this.state; return ( - - + + } > - + ); } diff --git a/src/core/client/ui/components/Popover/Popover.css b/src/core/client/ui/components/Popover/Popover.css index 1a1553256..708964cdb 100644 --- a/src/core/client/ui/components/Popover/Popover.css +++ b/src/core/client/ui/components/Popover/Popover.css @@ -13,7 +13,3 @@ border-top-color: transparent !important; } } - -.clickable { - pointer-events: all; -} diff --git a/src/core/client/ui/components/Popover/Popover.tsx b/src/core/client/ui/components/Popover/Popover.tsx index 8b55931c2..84be78c8f 100644 --- a/src/core/client/ui/components/Popover/Popover.tsx +++ b/src/core/client/ui/components/Popover/Popover.tsx @@ -1,10 +1,11 @@ import React from "react"; import { Manager, Popper, Reference } from "react-popper"; -// import * as styles from "./Popover.css"; +import * as styles from "./Popover.css"; interface InnerProps { body: React.ReactElement; children: React.ReactElement; + showBody: boolean; placement?: | "auto-start" | "auto" @@ -25,25 +26,28 @@ interface InnerProps { class Popover extends React.Component { public render() { - const { children, body, placement = "top" } = this.props; + const { children, body, placement = "top", showBody = true } = this.props; return ( {({ ref }) => React.cloneElement(children, { ref })} - - {({ ref, style }) => - React.cloneElement(body, { - ref, - style, - }) - } - + {showBody && ( + + {({ ref, style }) => + React.cloneElement(body, { + ref, + style, + className: styles.root, + }) + } + + )} ); } From 6298a50bbe0a0fdcd7cf4c8d3419f2da0d39299a Mon Sep 17 00:00:00 2001 From: okbel Date: Tue, 10 Jul 2018 12:33:31 -0300 Subject: [PATCH 15/69] Translations :/ --- .../stream/components/PermalinkPopover.tsx | 17 +++++++++++++++-- src/core/client/ui/components/Button/Button.tsx | 1 - src/locales/en-US/stream.ftl | 3 +++ src/locales/es/stream.ftl | 3 +++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/core/client/stream/components/PermalinkPopover.tsx b/src/core/client/stream/components/PermalinkPopover.tsx index 776edbccf..eaa3368fd 100644 --- a/src/core/client/stream/components/PermalinkPopover.tsx +++ b/src/core/client/stream/components/PermalinkPopover.tsx @@ -1,3 +1,4 @@ +import { Localized as L } from "fluent-react/compat"; import React from "react"; import CopyToClipboard from "react-copy-to-clipboard"; import { Button, Popover, TextField } from "talk-ui/components"; @@ -49,13 +50,25 @@ class PermalinkPopover extends React.Component {
- +
} > ); diff --git a/src/core/client/ui/components/Button/Button.tsx b/src/core/client/ui/components/Button/Button.tsx index 127d16c2e..dadb7a35d 100644 --- a/src/core/client/ui/components/Button/Button.tsx +++ b/src/core/client/ui/components/Button/Button.tsx @@ -49,7 +49,6 @@ class Button extends React.Component { [classes.secondary]: secondary, }); - console.log(this.props); return ( Date: Wed, 11 Jul 2018 16:14:36 -0300 Subject: [PATCH 16/69] wip --- .../stream/components/PermalinkPopover.tsx | 38 ++++++++++--------- .../client/ui/components/Popover/Popover.tsx | 36 +++++++++--------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/core/client/stream/components/PermalinkPopover.tsx b/src/core/client/stream/components/PermalinkPopover.tsx index eaa3368fd..282030d20 100644 --- a/src/core/client/stream/components/PermalinkPopover.tsx +++ b/src/core/client/stream/components/PermalinkPopover.tsx @@ -45,24 +45,28 @@ class PermalinkPopover extends React.Component { const { copied, showBody } = this.state; return ( - - - - - + showBody ? ( +
+ + + + +
+ ) : null } > diff --git a/src/core/client/stream/containers/CommentContainer.tsx b/src/core/client/stream/containers/CommentContainer.tsx index 0196f6b2e..0316112d1 100644 --- a/src/core/client/stream/containers/CommentContainer.tsx +++ b/src/core/client/stream/containers/CommentContainer.tsx @@ -2,16 +2,19 @@ import React, { StatelessComponent } from "react"; import { graphql } from "react-relay"; import withFragmentContainer from "talk-framework/lib/relay/withFragmentContainer"; -import { Omit, PropTypesOf } from "talk-framework/types"; +import { PropTypesOf } from "talk-framework/types"; import { CommentContainer as Data } from "talk-stream/__generated__/CommentContainer.graphql"; -import Comment, { CommentProps } from "../components/Comment"; +import Comment from "../components/Comment"; -type InnerProps = { data: Data } & Omit; +interface InnerProps { + data: Data; +} // tslint:disable-next-line:no-unused-expression graphql` fragment CommentContainer_comment on Comment { + id author { username } diff --git a/src/core/client/ui/hocs/withForwardRef.ts b/src/core/client/ui/hocs/withForwardRef.tsx similarity index 94% rename from src/core/client/ui/hocs/withForwardRef.ts rename to src/core/client/ui/hocs/withForwardRef.tsx index 66b9660e9..e3eb9fe10 100644 --- a/src/core/client/ui/hocs/withForwardRef.ts +++ b/src/core/client/ui/hocs/withForwardRef.tsx @@ -1,3 +1,4 @@ +import React from "react"; import { InferableComponentEnhancerWithProps, withPropsOnChange, diff --git a/src/locales/en-US/stream.ftl b/src/locales/en-US/stream.ftl index 758f49f22..08a397cc1 100644 --- a/src/locales/en-US/stream.ftl +++ b/src/locales/en-US/stream.ftl @@ -1,9 +1,3 @@ -<<<<<<< HEAD -postCommentForm-submit = Post -share = Share -copy = Copy -copied = Copied -======= ### Localization for Embed Stream ## Comments Tab @@ -11,4 +5,7 @@ copied = Copied comments-postCommentForm-post = Post comments-stream-loadMore = Load more comments-replyList-showAll = Show all ->>>>>>> cac0afa61e79b19ddcae873f543a6910b83c92e7 + +comments-permalink-share = Share +comments-permalink-copy = Copy +comments-permalink-copied = Copied From 7c88c251ea961b551574ae6b89340d31ddfab58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Mon, 16 Jul 2018 16:14:56 -0300 Subject: [PATCH 18/69] progress --- .../components/Comment/Comment.spec.tsx | 2 +- .../stream/components/Comment/Comment.tsx | 13 +++- .../stream/components/PermalinkPopover.tsx | 71 +++++++------------ .../ui/components/Attachment/Attachment.tsx | 6 +- .../client/ui/components/Popover/Popover.tsx | 32 +++++++-- src/core/client/ui/hocs/withForwardRef.tsx | 6 +- 6 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/core/client/stream/components/Comment/Comment.spec.tsx b/src/core/client/stream/components/Comment/Comment.spec.tsx index a6183e7ac..8b409adeb 100644 --- a/src/core/client/stream/components/Comment/Comment.spec.tsx +++ b/src/core/client/stream/components/Comment/Comment.spec.tsx @@ -7,7 +7,7 @@ import Comment from "./Comment"; it("renders username and body", () => { const props: PropTypesOf = { - id: "comment-ID", + id: "comment-id", author: { username: "Marvin", }, diff --git a/src/core/client/stream/components/Comment/Comment.tsx b/src/core/client/stream/components/Comment/Comment.tsx index a3f763c08..0765a2a79 100644 --- a/src/core/client/stream/components/Comment/Comment.tsx +++ b/src/core/client/stream/components/Comment/Comment.tsx @@ -1,6 +1,7 @@ +import { Localized } from "fluent-react/compat"; import React from "react"; import { StatelessComponent } from "react"; -import { Typography } from "talk-ui/components"; +import { Popover, Typography } from "talk-ui/components"; import PermalinkPopover from "../PermalinkPopover"; import Timestamp from "./Timestamp"; import TopBar from "./TopBar"; @@ -25,7 +26,15 @@ const Comment: StatelessComponent = props => { {props.body}
- + }> + {({ toggleShow }) => ( + + )} +
); diff --git a/src/core/client/stream/components/PermalinkPopover.tsx b/src/core/client/stream/components/PermalinkPopover.tsx index 0f7e19ba7..85e3bdd06 100644 --- a/src/core/client/stream/components/PermalinkPopover.tsx +++ b/src/core/client/stream/components/PermalinkPopover.tsx @@ -1,22 +1,22 @@ -import { Localized as L } from "fluent-react/compat"; -import React from "react"; +import { Localized } from "fluent-react/compat"; +import React, { CSSProperties } from "react"; import CopyToClipboard from "react-copy-to-clipboard"; -import { Button, Popover, TextField } from "talk-ui/components"; +import { Button, TextField } from "talk-ui/components"; import * as styles from "./PermalinkPopover.css"; interface InnerProps { commentId: string; + ref?: any; + style?: CSSProperties; } interface State { copied: boolean; - showBody: boolean; } class PermalinkPopover extends React.Component { public state: State = { copied: false, - showBody: false, }; public onCopy = async () => { @@ -26,14 +26,6 @@ class PermalinkPopover extends React.Component { }, 800); }; - public onClick = () => this.toggleShow(); - - public toggleShow = () => { - this.setState((state: State) => ({ - showBody: !state.showBody, - })); - }; - public toggleCopied = () => { this.setState((state: State) => ({ copied: !state.copied, @@ -41,40 +33,27 @@ class PermalinkPopover extends React.Component { }; public render() { - const { commentId } = this.props; - const { copied, showBody } = this.state; + const { commentId, ref, style } = this.props; + const { copied } = this.state; + + console.log(this.props, "props"); return ( - - - - - - - ) : null - } - > - - +
+ + + + +
); } } diff --git a/src/core/client/ui/components/Attachment/Attachment.tsx b/src/core/client/ui/components/Attachment/Attachment.tsx index 19dbdb2b6..5af459729 100644 --- a/src/core/client/ui/components/Attachment/Attachment.tsx +++ b/src/core/client/ui/components/Attachment/Attachment.tsx @@ -25,13 +25,17 @@ interface InnerProps { | "left-start"; } +interface Props { + ref: any; +} + class Attachment extends React.Component { public render() { const { children, body, placement = "top", className } = this.props; return ( - {({ ref }) => React.cloneElement(children, { ref })} + {(props: Props) => React.cloneElement(children, { ref: props.ref })} void; +} + interface InnerProps { - body: React.ReactElement | null; - children: React.ReactElement; + body: React.ReactElement | null; + children: (props: RenderProps) => React.ReactElement; +} + +interface Props { + ref: any; +} + +interface State { + show: false; } class Popover extends React.Component { + public state: State = { + show: false, + }; + + public toggleShow = () => { + this.setState((state: State) => ({ + show: !state.show, + })); + }; + public render() { - const { body, children: reference } = this.props; + const { body, children } = this.props; + // const { show } = this.state; + console.log(children); return ( - {reference} + {({ ref }) => children({ toggleShow: this.toggleShow, ref })} ); } diff --git a/src/core/client/ui/hocs/withForwardRef.tsx b/src/core/client/ui/hocs/withForwardRef.tsx index e3eb9fe10..6b48b928b 100644 --- a/src/core/client/ui/hocs/withForwardRef.tsx +++ b/src/core/client/ui/hocs/withForwardRef.tsx @@ -9,14 +9,12 @@ import { * the `React.forwardRef` api. */ function withForwardRef(): InferableComponentEnhancerWithProps< - { forwardRef: any }, + { forwardRef: Ref }, {} > { return WrappedComponent => { return React.forwardRef((props, ref) => ( - ref as button={ref} className="FancyButton"> - {props.children} - + )); }; } From 22f9631cb8066a209c1285e428f902563b40bb02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Mon, 16 Jul 2018 16:42:24 -0300 Subject: [PATCH 19/69] Any --- .../stream/components/PermalinkPopover.tsx | 1 - .../ui/components/Attachment/Attachment.tsx | 32 +++++++++---------- .../client/ui/components/Popover/Popover.tsx | 14 ++++---- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/core/client/stream/components/PermalinkPopover.tsx b/src/core/client/stream/components/PermalinkPopover.tsx index 85e3bdd06..6a85ffcad 100644 --- a/src/core/client/stream/components/PermalinkPopover.tsx +++ b/src/core/client/stream/components/PermalinkPopover.tsx @@ -36,7 +36,6 @@ class PermalinkPopover extends React.Component { const { commentId, ref, style } = this.props; const { copied } = this.state; - console.log(this.props, "props"); return (
diff --git a/src/core/client/ui/components/Attachment/Attachment.tsx b/src/core/client/ui/components/Attachment/Attachment.tsx index 5af459729..2a44bcac1 100644 --- a/src/core/client/ui/components/Attachment/Attachment.tsx +++ b/src/core/client/ui/components/Attachment/Attachment.tsx @@ -1,11 +1,14 @@ -import cn from "classnames"; -import React from "react"; -import { Manager, Popper, Reference } from "react-popper"; -import * as styles from "./Attachment.css"; +import React, { CSSProperties } from "react"; +import { Manager, Popper, Reference, RefHandler } from "react-popper"; + +interface RenderProps { + ref: RefHandler; + style?: CSSProperties; +} interface InnerProps { body: React.ReactElement | null; - children: React.ReactElement; + children: (props: RenderProps) => React.ReactElement; className?: string; placement?: | "auto-start" @@ -31,13 +34,10 @@ interface Props { class Attachment extends React.Component { public render() { - const { children, body, placement = "top", className } = this.props; + const { children, body, placement = "top" } = this.props; return ( - - {(props: Props) => React.cloneElement(children, { ref: props.ref })} - - + {(props: Props) => children({ ref: props.ref })} { positionFixed={false} > {({ ref, style }) => - body && - React.cloneElement(body, { - ref, - style, - className: cn(styles.root, className), - }) + body + ? React.cloneElement(body, { + ref, + style, + }) + : null } diff --git a/src/core/client/ui/components/Popover/Popover.tsx b/src/core/client/ui/components/Popover/Popover.tsx index 3605dc3b2..e9f054de3 100644 --- a/src/core/client/ui/components/Popover/Popover.tsx +++ b/src/core/client/ui/components/Popover/Popover.tsx @@ -1,18 +1,16 @@ import React from "react"; +import { RefHandler } from "react-popper"; import Attachment from "../Attachment"; import * as styles from "./Popover.css"; interface RenderProps { - toggleShow: () => void; + toggleShow?: () => void; + ref?: RefHandler; } interface InnerProps { - body: React.ReactElement | null; - children: (props: RenderProps) => React.ReactElement; -} - -interface Props { - ref: any; + body: React.ReactElement | null; + children: (props: RenderProps) => any; } interface State { @@ -33,7 +31,7 @@ class Popover extends React.Component { public render() { const { body, children } = this.props; // const { show } = this.state; - console.log(children); + // console.log(children); return ( {({ ref }) => children({ toggleShow: this.toggleShow, ref })} From 0cc705d71b5fc3317618363eae8f9041e6df33c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Mon, 16 Jul 2018 18:10:57 -0300 Subject: [PATCH 20/69] Working --- src/core/client/stream/components/Comment/Comment.tsx | 4 ++-- src/core/client/stream/components/PermalinkPopover.tsx | 8 ++++---- src/core/client/ui/components/Attachment/Attachment.tsx | 7 ++++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/core/client/stream/components/Comment/Comment.tsx b/src/core/client/stream/components/Comment/Comment.tsx index 0765a2a79..6d4065126 100644 --- a/src/core/client/stream/components/Comment/Comment.tsx +++ b/src/core/client/stream/components/Comment/Comment.tsx @@ -27,8 +27,8 @@ const Comment: StatelessComponent = props => { {props.body}
}> - {({ toggleShow }) => ( - + )}
diff --git a/src/core/client/stream/components/PermalinkPopover.css b/src/core/client/stream/components/PermalinkPopover.css index ffc0a1b6c..ee4ef4d5c 100644 --- a/src/core/client/stream/components/PermalinkPopover.css +++ b/src/core/client/stream/components/PermalinkPopover.css @@ -1,9 +1,3 @@ -.shareButton { - composes: button from "talk-ui/shared/typography.css"; - composes: buttonReset from "talk-ui/shared/buttonReset.css"; - padding: 10px 0; -} - .textField { margin-right: 5px; } diff --git a/src/core/client/ui/components/BaseButton/BaseButton.tsx b/src/core/client/ui/components/BaseButton/BaseButton.tsx index 1d97a9d0c..81819b184 100644 --- a/src/core/client/ui/components/BaseButton/BaseButton.tsx +++ b/src/core/client/ui/components/BaseButton/BaseButton.tsx @@ -19,6 +19,8 @@ interface InnerProps extends ButtonHTMLAttributes { /** This is passed by the `withKeyboardFocus` HOC */ keyboardFocus: boolean; + + innerRef?: React.RefObject | any; } /** @@ -31,6 +33,7 @@ const BaseButton: StatelessComponent = ({ classes, keyboardFocus, type: typeProp, + innerRef, ...rest }) => { let Element = "button"; @@ -53,7 +56,7 @@ const BaseButton: StatelessComponent = ({ [classes.keyboardFocus]: keyboardFocus, }); - return ; + return ; }; const enhanced = withStyles(styles)(withKeyboardFocus(BaseButton)); diff --git a/src/core/client/ui/components/Button/Button.tsx b/src/core/client/ui/components/Button/Button.tsx index dadb7a35d..ded844b87 100644 --- a/src/core/client/ui/components/Button/Button.tsx +++ b/src/core/client/ui/components/Button/Button.tsx @@ -28,6 +28,8 @@ interface InnerProps extends ButtonHTMLAttributes { /** If set renders a button with secondary colors */ secondary?: boolean; + + innerRef?: React.RefObject | any; } class Button extends React.Component { @@ -39,6 +41,7 @@ class Button extends React.Component { invert, primary, secondary, + innerRef, ...rest } = this.props; @@ -53,6 +56,7 @@ class Button extends React.Component { ); From 31113e7ecfa7511fa9c0cf277a5349001515ea1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Curcio?= Date: Mon, 16 Jul 2018 18:23:44 -0300 Subject: [PATCH 22/69] Ready --- src/core/client/stream/components/Comment/Comment.tsx | 6 +----- src/core/client/stream/components/PermalinkPopover.css | 8 +++++++- src/core/client/ui/components/Popover/Popover.tsx | 5 ++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/core/client/stream/components/Comment/Comment.tsx b/src/core/client/stream/components/Comment/Comment.tsx index 9216e8b14..d77b6c4ad 100644 --- a/src/core/client/stream/components/Comment/Comment.tsx +++ b/src/core/client/stream/components/Comment/Comment.tsx @@ -28,11 +28,7 @@ const Comment: StatelessComponent = props => {
}> {({ toggleShow, ref }) => ( - + )} + +
+
+ ); +}; + +export default Comment; diff --git a/src/core/client/stream/components/Comment/Timestamp.css b/src/core/client/stream/components/Comment/Timestamp.css new file mode 100644 index 000000000..f2d263ad4 --- /dev/null +++ b/src/core/client/stream/components/Comment/Timestamp.css @@ -0,0 +1,3 @@ +.root { + composes: timestamp from "talk-ui/shared/typography.css"; +} diff --git a/src/core/client/stream/components/Comment/Timestamp.spec.tsx b/src/core/client/stream/components/Comment/Timestamp.spec.tsx new file mode 100644 index 000000000..4a276b762 --- /dev/null +++ b/src/core/client/stream/components/Comment/Timestamp.spec.tsx @@ -0,0 +1,14 @@ +import { shallow } from "enzyme"; +import React from "react"; + +import { PropTypesOf } from "talk-framework/types"; + +import Timestamp from "./Timestamp"; + +it("renders correctly", () => { + const props: PropTypesOf = { + children: "1995-12-17T03:24:00.000Z", + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/components/Comment/Timestamp.tsx b/src/core/client/stream/components/Comment/Timestamp.tsx new file mode 100644 index 000000000..e6228416f --- /dev/null +++ b/src/core/client/stream/components/Comment/Timestamp.tsx @@ -0,0 +1,16 @@ +import React from "react"; +import { StatelessComponent } from "react"; + +import { RelativeTime } from "talk-ui/components"; + +import * as styles from "./Timestamp.css"; + +export interface TimestampProps { + children: string; +} + +const Timestamp: StatelessComponent = props => ( + +); + +export default Timestamp; diff --git a/src/core/client/stream/components/Comment/TopBar.css b/src/core/client/stream/components/Comment/TopBar.css new file mode 100644 index 000000000..dff9c8a74 --- /dev/null +++ b/src/core/client/stream/components/Comment/TopBar.css @@ -0,0 +1,3 @@ +.root { + margin-bottom: calc(0.5 * var(--spacing-unit)); +} diff --git a/src/core/client/stream/components/Comment/TopBar.spec.tsx b/src/core/client/stream/components/Comment/TopBar.spec.tsx new file mode 100644 index 000000000..5ee691f70 --- /dev/null +++ b/src/core/client/stream/components/Comment/TopBar.spec.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import TestRenderer from "react-test-renderer"; + +import { PropTypesOf } from "talk-framework/types"; +import { UIContext, UIContextProps } from "talk-ui/components"; + +import TopBar from "./TopBar"; + +it("renders correctly on small screens", () => { + const props: PropTypesOf = { + children:
Hello World
, + }; + + const context: UIContextProps = { + mediaQueryValues: { + width: 320, + }, + }; + + const testRenderer = TestRenderer.create( + + + + ); + expect(testRenderer.toJSON()).toMatchSnapshot(); +}); + +it("renders correctly on big screens", () => { + const props: PropTypesOf = { + children:
Hello World
, + }; + + const context: UIContextProps = { + mediaQueryValues: { + width: 1600, + }, + }; + + const testRenderer = TestRenderer.create( + + + + ); + expect(testRenderer.toJSON()).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/components/Comment/TopBar.tsx b/src/core/client/stream/components/Comment/TopBar.tsx new file mode 100644 index 000000000..2dfe6419d --- /dev/null +++ b/src/core/client/stream/components/Comment/TopBar.tsx @@ -0,0 +1,32 @@ +import cn from "classnames"; +import React from "react"; +import { StatelessComponent } from "react"; + +import { Flex, MatchMedia } from "talk-ui/components"; + +import * as styles from "./TopBar.css"; + +export interface TopBarProps { + className?: string; + children: React.ReactNode; +} + +const TopBar: StatelessComponent = props => { + const rootClassName = cn(styles.root, props.className); + return ( + + {matches => ( + + {props.children} + + )} + + ); +}; + +export default TopBar; diff --git a/src/core/client/stream/components/Comment/Username.css b/src/core/client/stream/components/Comment/Username.css new file mode 100644 index 000000000..e2dd79a8e --- /dev/null +++ b/src/core/client/stream/components/Comment/Username.css @@ -0,0 +1,3 @@ +.root { + line-height: 1; +} diff --git a/src/core/client/stream/components/Comment/Username.spec.tsx b/src/core/client/stream/components/Comment/Username.spec.tsx new file mode 100644 index 000000000..1a10e4012 --- /dev/null +++ b/src/core/client/stream/components/Comment/Username.spec.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import TestRenderer from "react-test-renderer"; + +import { PropTypesOf } from "talk-framework/types"; +import { UIContext, UIContextProps } from "talk-ui/components"; + +import Username from "./Username"; + +it("renders correctly on small screens", () => { + const props: PropTypesOf = { + children: "Marvin", + }; + + const context: UIContextProps = { + mediaQueryValues: { + width: 320, + }, + }; + + const testRenderer = TestRenderer.create( + + + + ); + expect(testRenderer.toJSON()).toMatchSnapshot(); +}); + +it("renders correctly on big screens", () => { + const props: PropTypesOf = { + children: "Marvin", + }; + + const context: UIContextProps = { + mediaQueryValues: { + width: 1600, + }, + }; + + const testRenderer = TestRenderer.create( + + + + ); + expect(testRenderer.toJSON()).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/components/Comment/Username.tsx b/src/core/client/stream/components/Comment/Username.tsx new file mode 100644 index 000000000..ada04c8ec --- /dev/null +++ b/src/core/client/stream/components/Comment/Username.tsx @@ -0,0 +1,28 @@ +import React from "react"; +import { StatelessComponent } from "react"; + +import { MatchMedia, Typography } from "talk-ui/components"; + +import * as styles from "./Username.css"; + +export interface UsernameProps { + children: string; +} + +const Username: StatelessComponent = props => { + return ( + + {matches => ( + + {props.children} + + )} + + ); +}; + +export default Username; diff --git a/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap b/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap new file mode 100644 index 000000000..2d047c200 --- /dev/null +++ b/src/core/client/stream/components/Comment/__snapshots__/Comment.spec.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders username and body 1`] = ` +
+ + + Marvin + + + 1995-12-17T03:24:00.000Z + + + + Woof + +
+`; diff --git a/src/core/client/stream/components/Comment/__snapshots__/Timestamp.spec.tsx.snap b/src/core/client/stream/components/Comment/__snapshots__/Timestamp.spec.tsx.snap new file mode 100644 index 000000000..862d6cad7 --- /dev/null +++ b/src/core/client/stream/components/Comment/__snapshots__/Timestamp.spec.tsx.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` + +`; diff --git a/src/core/client/stream/components/Comment/__snapshots__/TopBar.spec.tsx.snap b/src/core/client/stream/components/Comment/__snapshots__/TopBar.spec.tsx.snap new file mode 100644 index 000000000..9253404bd --- /dev/null +++ b/src/core/client/stream/components/Comment/__snapshots__/TopBar.spec.tsx.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly on big screens 1`] = ` +
+
+ Hello World +
+
+`; + +exports[`renders correctly on small screens 1`] = ` +
+
+ Hello World +
+
+`; diff --git a/src/core/client/stream/components/Comment/__snapshots__/Username.spec.tsx.snap b/src/core/client/stream/components/Comment/__snapshots__/Username.spec.tsx.snap new file mode 100644 index 000000000..ab0e141e6 --- /dev/null +++ b/src/core/client/stream/components/Comment/__snapshots__/Username.spec.tsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly on big screens 1`] = ` + + Marvin + +`; + +exports[`renders correctly on small screens 1`] = ` + + Marvin + +`; diff --git a/src/core/client/stream/components/Comment/index.ts b/src/core/client/stream/components/Comment/index.ts new file mode 100644 index 000000000..173033df9 --- /dev/null +++ b/src/core/client/stream/components/Comment/index.ts @@ -0,0 +1 @@ +export { default, default as Comment, CommentProps } from "./Comment"; diff --git a/src/core/client/stream/components/Indent.css b/src/core/client/stream/components/Indent.css new file mode 100644 index 000000000..c675b03a6 --- /dev/null +++ b/src/core/client/stream/components/Indent.css @@ -0,0 +1,8 @@ +.root { + border-left: 3px solid; + padding-left: var(--spacing-unit); +} + +.level0 { + border-color: var(--palette-secondary-darkest); +} diff --git a/src/core/client/stream/components/Indent.spec.tsx b/src/core/client/stream/components/Indent.spec.tsx new file mode 100644 index 000000000..3108ba209 --- /dev/null +++ b/src/core/client/stream/components/Indent.spec.tsx @@ -0,0 +1,14 @@ +import { shallow } from "enzyme"; +import React from "react"; + +import { PropTypesOf } from "talk-framework/types"; + +import Indent from "./Indent"; + +it("renders correctly", () => { + const props: PropTypesOf = { + children:
Hello World
, + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/components/Indent.tsx b/src/core/client/stream/components/Indent.tsx new file mode 100644 index 000000000..7ea8fddf3 --- /dev/null +++ b/src/core/client/stream/components/Indent.tsx @@ -0,0 +1,15 @@ +import cn from "classnames"; +import React, { StatelessComponent } from "react"; + +import * as styles from "./Indent.css"; + +export interface IndentProps { + level?: number; + children: React.ReactNode; +} + +const Indent: StatelessComponent = props => { + return
{props.children}
; +}; + +export default Indent; diff --git a/src/core/client/stream/components/Permalink.tsx b/src/core/client/stream/components/Permalink.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/core/client/stream/components/PermalinkPopover.css b/src/core/client/stream/components/PermalinkPopover.css new file mode 100644 index 000000000..2d5f33fd2 --- /dev/null +++ b/src/core/client/stream/components/PermalinkPopover.css @@ -0,0 +1,13 @@ +.textField { + margin-right: 5px; +} + +.root { + background-color: #ffffff; + border: 1px solid #c9cacb; + box-sizing: border-box; + box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.25); + border-radius: 1px; + padding: 6px 10px; + display: flex; +} diff --git a/src/core/client/stream/components/PermalinkPopover.tsx b/src/core/client/stream/components/PermalinkPopover.tsx new file mode 100644 index 000000000..a4d8feca2 --- /dev/null +++ b/src/core/client/stream/components/PermalinkPopover.tsx @@ -0,0 +1,60 @@ +import { Localized } from "fluent-react/compat"; +import React, { CSSProperties } from "react"; +import CopyToClipboard from "react-copy-to-clipboard"; +import { RefHandler } from "react-popper"; +import { Button, TextField } from "talk-ui/components"; +import * as styles from "./PermalinkPopover.css"; + +interface InnerProps { + commentId: string; + style?: CSSProperties; + innerRef?: RefHandler; +} + +interface State { + copied: boolean; +} + +class PermalinkPopover extends React.Component { + public state: State = { + copied: false, + }; + + public onCopy = async () => { + await this.toggleCopied(); + setTimeout(() => { + this.toggleCopied(); + }, 800); + }; + + public toggleCopied = () => { + this.setState((state: State) => ({ + copied: !state.copied, + })); + }; + + public render() { + const { commentId, style, innerRef } = this.props; + const { copied } = this.state; + return ( +
+ + + + +
+ ); + } +} + +export default PermalinkPopover; diff --git a/src/core/client/stream/components/PostCommentForm.css b/src/core/client/stream/components/PostCommentForm.css index a536dcc8b..df045285d 100644 --- a/src/core/client/stream/components/PostCommentForm.css +++ b/src/core/client/stream/components/PostCommentForm.css @@ -3,10 +3,12 @@ display: block; height: 100px; - width: 400px; - margin-bottom: calc(2px * $spacing-unit); + width: 100%; + box-sizing: border-box; + margin-bottom: var(--spacing-unit); } -.postButton { - float: right; +.postButtonContainer { + display: flex; + justify-content: flex-end; } diff --git a/src/core/client/stream/components/PostCommentForm.tsx b/src/core/client/stream/components/PostCommentForm.tsx index 2187994be..09db70e39 100644 --- a/src/core/client/stream/components/PostCommentForm.tsx +++ b/src/core/client/stream/components/PostCommentForm.tsx @@ -39,11 +39,13 @@ const PostCommentForm: StatelessComponent = props => ( )} - - - +
+ + + +
)} diff --git a/src/core/client/stream/components/ReplyList.spec.tsx b/src/core/client/stream/components/ReplyList.spec.tsx new file mode 100644 index 000000000..093d96049 --- /dev/null +++ b/src/core/client/stream/components/ReplyList.spec.tsx @@ -0,0 +1,42 @@ +import { shallow } from "enzyme"; +import { noop } from "lodash"; +import React from "react"; +import sinon, { SinonSpy } from "sinon"; + +import { PropTypesOf } from "talk-framework/types"; + +import ReplyList from "./ReplyList"; + +it("renders correctly", () => { + const props: PropTypesOf = { + commentID: "comment-id", + comments: [{ id: "comment-1" }, { id: "comment-2" }], + onShowAll: noop, + hasMore: false, + disableShowAll: false, + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); + +describe("when there is more", () => { + const props: PropTypesOf = { + commentID: "comment-id", + comments: [{ id: "comment-1" }, { id: "comment-2" }], + onShowAll: sinon.spy(), + hasMore: true, + disableShowAll: false, + }; + + const wrapper = shallow(); + it("renders a load more button", () => { + expect(wrapper).toMatchSnapshot(); + }); + + it("calls onLoadMore", () => { + wrapper + .find("#talk-comments-replyList-showAll--comment-id") + .simulate("click"); + expect((props.onShowAll as SinonSpy).calledOnce).toBe(true); + }); +}); diff --git a/src/core/client/stream/components/ReplyList.tsx b/src/core/client/stream/components/ReplyList.tsx new file mode 100644 index 000000000..17ad32ed2 --- /dev/null +++ b/src/core/client/stream/components/ReplyList.tsx @@ -0,0 +1,50 @@ +import { Localized } from "fluent-react/compat"; +import * as React from "react"; +import { StatelessComponent } from "react"; + +import { Button, Flex } from "talk-ui/components"; + +import CommentContainer from "../containers/CommentContainer"; +import Indent from "./Indent"; + +export interface ReplyListProps { + commentID: string; + comments: ReadonlyArray<{ id: string }>; + onShowAll: () => void; + hasMore: boolean; + disableShowAll: boolean; +} + +const ReplyList: StatelessComponent = props => { + return ( + + + {props.comments.map(comment => ( + + ))} + {props.hasMore && ( + + + + )} + + + ); +}; + +export default ReplyList; diff --git a/src/core/client/stream/components/Stream.css b/src/core/client/stream/components/Stream.css new file mode 100644 index 000000000..13c90d031 --- /dev/null +++ b/src/core/client/stream/components/Stream.css @@ -0,0 +1,4 @@ +.root { + width: 100%; + max-width: 400px; +} diff --git a/src/core/client/stream/components/Stream.spec.tsx b/src/core/client/stream/components/Stream.spec.tsx new file mode 100644 index 000000000..335f8fe27 --- /dev/null +++ b/src/core/client/stream/components/Stream.spec.tsx @@ -0,0 +1,47 @@ +import { shallow } from "enzyme"; +import { noop } from "lodash"; +import React from "react"; +import sinon, { SinonSpy } from "sinon"; + +import { PropTypesOf } from "talk-framework/types"; + +import Stream from "./Stream"; + +it("renders correctly", () => { + const props: PropTypesOf = { + assetID: "asset-id", + isClosed: false, + comments: [{ id: "comment-1" }, { id: "comment-2" }], + onLoadMore: noop, + disableLoadMore: false, + hasMore: false, + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); + +describe("when there is more", () => { + const props: PropTypesOf = { + assetID: "asset-id", + isClosed: false, + comments: [{ id: "comment-1" }, { id: "comment-2" }], + onLoadMore: sinon.spy(), + disableLoadMore: false, + hasMore: true, + }; + + const wrapper = shallow(); + it("renders a load more button", () => { + expect(wrapper).toMatchSnapshot(); + }); + + it("calls onLoadMore", () => { + wrapper.find("#talk-comments-stream-loadMore").simulate("click"); + expect((props.onLoadMore as SinonSpy).calledOnce).toBe(true); + }); + + const wrapperDisabledButton = shallow(); + it("disables load more button", () => { + expect(wrapperDisabledButton).toMatchSnapshot(); + }); +}); diff --git a/src/core/client/stream/components/Stream.tsx b/src/core/client/stream/components/Stream.tsx index c42bb21b3..da55050f5 100644 --- a/src/core/client/stream/components/Stream.tsx +++ b/src/core/client/stream/components/Stream.tsx @@ -1,18 +1,58 @@ +import { Localized } from "fluent-react/compat"; import * as React from "react"; import { StatelessComponent } from "react"; +import { Button, Flex } from "talk-ui/components"; + import CommentContainer from "../containers/CommentContainer"; +import PostCommentFormContainer from "../containers/PostCommentFormContainer"; +import ReplyListContainer from "../containers/ReplyListContainer"; +import Logo from "./Logo"; +import * as styles from "./Stream.css"; export interface StreamProps { + assetID: string; + isClosed: boolean; comments: ReadonlyArray<{ id: string }>; + onLoadMore: () => void; + hasMore: boolean; + disableLoadMore: boolean; } const Stream: StatelessComponent = props => { return ( -
- {props.comments.map(comment => ( - - ))} +
+ + + + {props.comments.map(comment => ( + + + + + ))} + {props.hasMore && ( + + + + )} +
); }; diff --git a/src/core/client/stream/components/__snapshots__/App.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/App.spec.tsx.snap new file mode 100644 index 000000000..6a12e4e09 --- /dev/null +++ b/src/core/client/stream/components/__snapshots__/App.spec.tsx.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` + + + +`; + +exports[`renders correctly when asset is null 1`] = ` +
+ Asset not found +
+`; diff --git a/src/core/client/stream/components/__snapshots__/Indent.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/Indent.spec.tsx.snap new file mode 100644 index 000000000..910c819b2 --- /dev/null +++ b/src/core/client/stream/components/__snapshots__/Indent.spec.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +
+
+ Hello World +
+
+`; diff --git a/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap new file mode 100644 index 000000000..e48482470 --- /dev/null +++ b/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` + + + + + + +`; + +exports[`when there is more renders a load more button 1`] = ` + + + + + + + Show All Replies + + + + +`; diff --git a/src/core/client/stream/components/__snapshots__/Stream.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/Stream.spec.tsx.snap new file mode 100644 index 000000000..a8210fd99 --- /dev/null +++ b/src/core/client/stream/components/__snapshots__/Stream.spec.tsx.snap @@ -0,0 +1,214 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` +
+ + + + + + + + + + + + +
+`; + +exports[`when there is more disables load more button 1`] = ` +
+ + + + + + + + + + + + + + Load More + + + +
+`; + +exports[`when there is more renders a load more button 1`] = ` +
+ + + + + + + + + + + + + + Load More + + + +
+`; diff --git a/src/core/client/stream/containers/AppContainer.spec.tsx b/src/core/client/stream/containers/AppContainer.spec.tsx new file mode 100644 index 000000000..17a0a676d --- /dev/null +++ b/src/core/client/stream/containers/AppContainer.spec.tsx @@ -0,0 +1,16 @@ +import { shallow } from "enzyme"; +import React from "react"; + +import { PropTypesOf } from "talk-framework/types"; + +import { AppContainer } from "./AppContainer"; + +it("renders correctly", () => { + const props: PropTypesOf = { + data: { + asset: {}, + }, + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/containers/AppContainer.tsx b/src/core/client/stream/containers/AppContainer.tsx index 02abbf314..90eb1e1c6 100644 --- a/src/core/client/stream/containers/AppContainer.tsx +++ b/src/core/client/stream/containers/AppContainer.tsx @@ -11,30 +11,20 @@ interface InnerProps { data: Data; } -const AppContainer: StatelessComponent = props => { +export const AppContainer: StatelessComponent = props => { return ; }; -const enhanced = withFragmentContainer<{ data: Data }>( - graphql` +const enhanced = withFragmentContainer<{ data: Data }>({ + data: graphql` fragment AppContainer on Query - @argumentDefinitions( - assetID: { type: "ID!" } - showAssetList: { type: "Boolean!" } - ) { - assets @include(if: $showAssetList) { - ...AssetListContainer_assets - } - asset(id: $assetID) @skip(if: $showAssetList) { - id - isClosed - comments { - ...StreamContainer_comments - } + @argumentDefinitions(assetID: { type: "ID!" }) { + asset(id: $assetID) { + ...StreamContainer_asset } } - ` -)(AppContainer); + `, +})(AppContainer); export type AppContainerProps = PropTypesOf; export default enhanced; diff --git a/src/core/client/stream/containers/AssetListContainer.tsx b/src/core/client/stream/containers/AssetListContainer.tsx deleted file mode 100644 index 6e441f00e..000000000 --- a/src/core/client/stream/containers/AssetListContainer.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React, { StatelessComponent } from "react"; -import { graphql } from "react-relay"; - -import { withFragmentContainer } from "talk-framework/lib/relay"; -import { PropTypesOf } from "talk-framework/types"; -import { AssetListContainer_assets as Data } from "talk-stream/__generated__/AssetListContainer_assets.graphql"; - -import AssetList from "../components/AssetList"; - -interface InnerProps { - assets: Data; -} - -const AssetListContainer: StatelessComponent = props => { - const assets = props.assets.edges.map(edge => edge.node); - return ; -}; - -const enhanced = withFragmentContainer<{ assets: Data }>( - graphql` - fragment AssetListContainer_assets on AssetsConnection { - edges { - node { - id - title - } - } - } - ` -)(AssetListContainer); - -export type AssetListContainerProps = PropTypesOf; -export default enhanced; diff --git a/src/core/client/stream/containers/CommentContainer.spec.tsx b/src/core/client/stream/containers/CommentContainer.spec.tsx new file mode 100644 index 000000000..98612be38 --- /dev/null +++ b/src/core/client/stream/containers/CommentContainer.spec.tsx @@ -0,0 +1,21 @@ +import { shallow } from "enzyme"; +import React from "react"; + +import { PropTypesOf } from "talk-framework/types"; + +import { CommentContainer } from "./CommentContainer"; + +it("renders username and body", () => { + const props: PropTypesOf = { + data: { + author: { + username: "Marvin", + }, + body: "Woof", + createdAt: "1995-12-17T03:24:00.000Z", + }, + }; + + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/containers/CommentContainer.tsx b/src/core/client/stream/containers/CommentContainer.tsx index 9a4d03cd8..0316112d1 100644 --- a/src/core/client/stream/containers/CommentContainer.tsx +++ b/src/core/client/stream/containers/CommentContainer.tsx @@ -2,28 +2,39 @@ import React, { StatelessComponent } from "react"; import { graphql } from "react-relay"; import withFragmentContainer from "talk-framework/lib/relay/withFragmentContainer"; -import { Omit, PropTypesOf } from "talk-framework/types"; +import { PropTypesOf } from "talk-framework/types"; import { CommentContainer as Data } from "talk-stream/__generated__/CommentContainer.graphql"; -import Comment, { CommentProps } from "../components/Comment"; +import Comment from "../components/Comment"; -type InnerProps = { data: Data } & Omit; +interface InnerProps { + data: Data; +} -const CommentContainer: StatelessComponent = props => { +// tslint:disable-next-line:no-unused-expression +graphql` + fragment CommentContainer_comment on Comment { + id + author { + username + } + body + createdAt + } +`; + +export const CommentContainer: StatelessComponent = props => { const { data, ...rest } = props; return ; }; -const enhanced = withFragmentContainer<{ data: Data }>( - graphql` +const enhanced = withFragmentContainer<{ data: Data }>({ + data: graphql` fragment CommentContainer on Comment { - author { - username - } - body + ...CommentContainer_comment @relay(mask: false) } - ` -)(CommentContainer); + `, +})(CommentContainer); export type CommentContainerProps = PropTypesOf; export default enhanced; diff --git a/src/core/client/stream/containers/PostCommentFormContainer.tsx b/src/core/client/stream/containers/PostCommentFormContainer.tsx index d2da26f64..bf4ab8cf9 100644 --- a/src/core/client/stream/containers/PostCommentFormContainer.tsx +++ b/src/core/client/stream/containers/PostCommentFormContainer.tsx @@ -25,6 +25,8 @@ class PostCommentFormContainer extends Component { if (error instanceof BadUserInputError) { return error.invalidArgsLocalized; } + // tslint:disable-next-line:no-console + console.error(error); } return undefined; }; diff --git a/src/core/client/stream/containers/ReplyListContainer.spec.tsx b/src/core/client/stream/containers/ReplyListContainer.spec.tsx new file mode 100644 index 000000000..3a414dd51 --- /dev/null +++ b/src/core/client/stream/containers/ReplyListContainer.spec.tsx @@ -0,0 +1,86 @@ +import { shallow, ShallowWrapper } from "enzyme"; +import { noop } from "lodash"; +import React from "react"; + +import { PropTypesOf } from "talk-framework/types"; + +import ReplyList from "../components/ReplyList"; +import { ReplyListContainer } from "./ReplyListContainer"; + +it("renders correctly", () => { + const props: PropTypesOf = { + comment: { + id: "comment-id", + replies: { + edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }], + }, + }, + relay: { + hasMore: noop, + isLoading: noop, + } as any, + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); + +it("renders correctly when replies are null", () => { + const props: PropTypesOf = { + comment: { + id: "comment-id", + replies: null, + }, + relay: { + hasMore: noop, + isLoading: noop, + } as any, + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); + +describe("when has more replies", () => { + let finishLoading: ((error?: Error) => void) | null = null; + const props: PropTypesOf = { + comment: { + id: "comment-id", + replies: { + edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }], + }, + }, + relay: { + hasMore: () => true, + isLoading: () => false, + loadMore: (_: any, callback: () => void) => (finishLoading = callback), + } as any, + }; + + let wrapper: ShallowWrapper; + + beforeAll(() => (wrapper = shallow())); + + it("renders hasMore", () => { + expect(wrapper).toMatchSnapshot(); + }); + + describe("when showing all", () => { + beforeAll(() => { + wrapper + .find(ReplyList) + .props() + .onShowAll(); + }); + it("calls relay loadMore", () => { + expect(finishLoading).not.toBeNull(); + }); + it("disables show all button", () => { + wrapper.update(); + expect(wrapper).toMatchSnapshot(); + }); + it("enable show all button after loading is done", () => { + finishLoading!(); + wrapper.update(); + expect(wrapper).toMatchSnapshot(); + }); + }); +}); diff --git a/src/core/client/stream/containers/ReplyListContainer.tsx b/src/core/client/stream/containers/ReplyListContainer.tsx new file mode 100644 index 000000000..48db9645a --- /dev/null +++ b/src/core/client/stream/containers/ReplyListContainer.tsx @@ -0,0 +1,135 @@ +import React from "react"; +import { graphql, RelayPaginationProp } from "react-relay"; + +import { withPaginationContainer } from "talk-framework/lib/relay"; +import { PropTypesOf } from "talk-framework/types"; +import { ReplyListContainer_comment as Data } from "talk-stream/__generated__/ReplyListContainer_comment.graphql"; +import { + COMMENT_SORT, + ReplyListContainerPaginationQueryVariables, +} from "talk-stream/__generated__/ReplyListContainerPaginationQuery.graphql"; + +import ReplyList from "../components/ReplyList"; + +export interface InnerProps { + comment: Data; + relay: RelayPaginationProp; +} + +export class ReplyListContainer extends React.Component { + public state = { + disableShowAll: false, + }; + + public render() { + if ( + this.props.comment.replies === null || + this.props.comment.replies.edges.length === 0 + ) { + return null; + } + const comments = this.props.comment.replies.edges.map(edge => edge.node); + return ( + + ); + } + + private showAll = () => { + if (!this.props.relay.hasMore() || this.props.relay.isLoading()) { + return; + } + + this.setState({ disableShowAll: true }); + this.props.relay.loadMore( + 999999999, // Fetch All Replies + error => { + this.setState({ disableShowAll: false }); + if (error) { + // tslint:disable-next-line:no-console + console.error(error); + } + } + ); + }; +} + +// TODO: (cvle) This should be autogenerated. +interface FragmentVariables { + count: number; + cursor?: string; + orderBy: COMMENT_SORT; +} + +const enhanced = withPaginationContainer< + { comment: Data }, + InnerProps, + FragmentVariables, + ReplyListContainerPaginationQueryVariables +>( + { + comment: graphql` + fragment ReplyListContainer_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 + } + } + } + } + `, + }, + { + 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) + } + } + `, + } +)(ReplyListContainer); + +export type ReplyListContainerProps = PropTypesOf; +export default enhanced; diff --git a/src/core/client/stream/containers/StreamContainer.spec.tsx b/src/core/client/stream/containers/StreamContainer.spec.tsx new file mode 100644 index 000000000..2e19bda86 --- /dev/null +++ b/src/core/client/stream/containers/StreamContainer.spec.tsx @@ -0,0 +1,73 @@ +import { shallow, ShallowWrapper } from "enzyme"; +import { noop } from "lodash"; +import React from "react"; + +import { PropTypesOf } from "talk-framework/types"; + +import Stream from "../components/Stream"; +import { StreamContainer } from "./StreamContainer"; + +it("renders correctly", () => { + const props: PropTypesOf = { + asset: { + id: "asset-id", + isClosed: false, + comments: { + edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }], + }, + }, + relay: { + hasMore: noop, + isLoading: noop, + } as any, + }; + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); +}); + +describe("when has more comments", () => { + let finishLoading: ((error?: Error) => void) | null = null; + const props: PropTypesOf = { + asset: { + id: "asset-id", + isClosed: false, + comments: { + edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }], + }, + }, + relay: { + hasMore: () => true, + isLoading: () => false, + loadMore: (_: any, callback: () => void) => (finishLoading = callback), + } as any, + }; + + let wrapper: ShallowWrapper; + + beforeAll(() => (wrapper = shallow())); + + it("renders hasMore", () => { + expect(wrapper).toMatchSnapshot(); + }); + + describe("when loading more", () => { + beforeAll(() => { + wrapper + .find(Stream) + .props() + .onLoadMore(); + }); + it("calls relay loadMore", () => { + expect(finishLoading).not.toBeNull(); + }); + it("disables load more button", () => { + wrapper.update(); + expect(wrapper).toMatchSnapshot(); + }); + it("enable load more button after loading is done", () => { + finishLoading!(); + wrapper.update(); + expect(wrapper).toMatchSnapshot(); + }); + }); +}); diff --git a/src/core/client/stream/containers/StreamContainer.tsx b/src/core/client/stream/containers/StreamContainer.tsx index 771c25efa..d81319deb 100644 --- a/src/core/client/stream/containers/StreamContainer.tsx +++ b/src/core/client/stream/containers/StreamContainer.tsx @@ -1,32 +1,132 @@ -import React, { StatelessComponent } from "react"; -import { graphql } from "react-relay"; +import React from "react"; +import { graphql, RelayPaginationProp } from "react-relay"; -import { withFragmentContainer } from "talk-framework/lib/relay"; +import { withPaginationContainer } from "talk-framework/lib/relay"; import { PropTypesOf } from "talk-framework/types"; -import { StreamContainer_comments as Data } from "talk-stream/__generated__/StreamContainer_comments.graphql"; +import { StreamContainer_asset as Data } from "talk-stream/__generated__/StreamContainer_asset.graphql"; +import { + COMMENT_SORT, + StreamContainerPaginationQueryVariables, +} from "talk-stream/__generated__/StreamContainerPaginationQuery.graphql"; import Stream from "../components/Stream"; interface InnerProps { - comments: Data; + asset: Data; + relay: RelayPaginationProp; } -const StreamContainer: StatelessComponent = props => { - const comments = props.comments.edges.map(edge => edge.node); - return ; -}; +export class StreamContainer extends React.Component { + public state = { + disableLoadMore: false, + }; -const enhanced = withFragmentContainer<{ comments: Data }>( - graphql` - fragment StreamContainer_comments on CommentsConnection { - edges { - node { - id - ...CommentContainer + public render() { + const comments = this.props.asset.comments.edges.map(edge => edge.node); + return ( + + ); + } + + private loadMore = () => { + if (!this.props.relay.hasMore() || this.props.relay.isLoading()) { + return; + } + this.setState({ disableLoadMore: true }); + this.props.relay.loadMore( + 10, // Fetch the next 10 feed items + error => { + this.setState({ disableLoadMore: false }); + if (error) { + // tslint:disable-next-line:no-console + console.error(error); } } - } - ` + ); + }; +} + +// TODO: (cvle) This should be autogenerated. +interface FragmentVariables { + count: number; + cursor?: string; + orderBy: COMMENT_SORT; +} + +const enhanced = withPaginationContainer< + { asset: Data }, + InnerProps, + FragmentVariables, + StreamContainerPaginationQueryVariables +>( + { + asset: graphql` + fragment StreamContainer_asset on Asset + @argumentDefinitions( + count: { type: "Int!", defaultValue: 5 } + cursor: { type: "Cursor" } + orderBy: { type: "COMMENT_SORT!", defaultValue: CREATED_AT_DESC } + ) { + id + isClosed + comments(first: $count, after: $cursor, orderBy: $orderBy) + @connection(key: "Stream_comments") { + edges { + node { + id + ...CommentContainer + ...ReplyListContainer_comment + } + } + } + } + `, + }, + { + direction: "forward", + getConnectionFromProps(props) { + return props.asset && props.asset.comments; + }, + // 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, + // assetID isn't specified as an @argument for the fragment, but it should be a + // variable available for the fragment under the query root. + assetID: props.asset.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 StreamContainerPaginationQuery( + $count: Int! + $cursor: Cursor + $orderBy: COMMENT_SORT! + $assetID: ID! + ) { + asset(id: $assetID) { + ...StreamContainer_asset + @arguments(count: $count, cursor: $cursor, orderBy: $orderBy) + } + } + `, + } )(StreamContainer); export type StreamContainerProps = PropTypesOf; diff --git a/src/core/client/stream/containers/__snapshots__/AppContainer.spec.tsx.snap b/src/core/client/stream/containers/__snapshots__/AppContainer.spec.tsx.snap new file mode 100644 index 000000000..f9a5c5316 --- /dev/null +++ b/src/core/client/stream/containers/__snapshots__/AppContainer.spec.tsx.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` + +`; diff --git a/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap b/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap new file mode 100644 index 000000000..9e2476f37 --- /dev/null +++ b/src/core/client/stream/containers/__snapshots__/CommentContainer.spec.tsx.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders username and body 1`] = ` + +`; diff --git a/src/core/client/stream/containers/__snapshots__/ReplyListContainer.spec.tsx.snap b/src/core/client/stream/containers/__snapshots__/ReplyListContainer.spec.tsx.snap new file mode 100644 index 000000000..52aa9c57b --- /dev/null +++ b/src/core/client/stream/containers/__snapshots__/ReplyListContainer.spec.tsx.snap @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` + +`; + +exports[`renders correctly when replies are null 1`] = `""`; + +exports[`when has more replies renders hasMore 1`] = ` + +`; + +exports[`when has more replies when showing all disables show all button 1`] = ` + +`; + +exports[`when has more replies when showing all enable show all button after loading is done 1`] = ` + +`; diff --git a/src/core/client/stream/containers/__snapshots__/StreamContainer.spec.tsx.snap b/src/core/client/stream/containers/__snapshots__/StreamContainer.spec.tsx.snap new file mode 100644 index 000000000..e3813397c --- /dev/null +++ b/src/core/client/stream/containers/__snapshots__/StreamContainer.spec.tsx.snap @@ -0,0 +1,80 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` + +`; + +exports[`when has more comments renders hasMore 1`] = ` + +`; + +exports[`when has more comments when loading more disables load more button 1`] = ` + +`; + +exports[`when has more comments when loading more enable load more button after loading is done 1`] = ` + +`; diff --git a/src/core/client/stream/queries/AppQuery.spec.tsx b/src/core/client/stream/queries/AppQuery.spec.tsx new file mode 100644 index 000000000..a301a76b7 --- /dev/null +++ b/src/core/client/stream/queries/AppQuery.spec.tsx @@ -0,0 +1,31 @@ +import { shallow } from "enzyme"; +import React from "react"; + +import { render } from "./AppQuery"; + +it("renders app", () => { + const data = { + props: {} as any, + error: null, + }; + const wrapper = shallow(React.createElement(() => render(data))); + expect(wrapper).toMatchSnapshot(); +}); + +it("renders loading", () => { + const data = { + props: null, + error: null, + }; + const wrapper = shallow(React.createElement(() => render(data))); + expect(wrapper).toMatchSnapshot(); +}); + +it("renders error", () => { + const data = { + props: null, + error: new Error("error"), + }; + const wrapper = shallow(React.createElement(() => render(data))); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/src/core/client/stream/queries/AppQuery.tsx b/src/core/client/stream/queries/AppQuery.tsx index 4dc61115c..3fe95b6d9 100644 --- a/src/core/client/stream/queries/AppQuery.tsx +++ b/src/core/client/stream/queries/AppQuery.tsx @@ -1,10 +1,10 @@ import * as React from "react"; import { StatelessComponent } from "react"; +import { ReadyState } from "react-relay"; import { graphql, QueryRenderer, - ReadyState, withLocalStateContainer, } from "talk-framework/lib/relay"; import { @@ -15,7 +15,7 @@ import { AppQueryLocal as Local } from "talk-stream/__generated__/AppQueryLocal. import AppContainer from "../containers/AppContainer"; -const render = ({ error, props }: ReadyState) => { +export const render = ({ error, props }: ReadyState) => { if (error) { return
{error.message}
; } @@ -33,16 +33,12 @@ const AppQuery: StatelessComponent = props => { return ( query={graphql` - query AppQuery($showAssetList: Boolean!, $assetID: ID!) { - ...AppContainer - @arguments(showAssetList: $showAssetList, assetID: $assetID) + query AppQuery($assetID: ID!) { + ...AppContainer @arguments(assetID: $assetID) } `} variables={{ - // We cast `null` to any due to restrictions of the current graphql syntax. - assetID: props.local.assetID || (null as any), - // TODO: This is set to false, as server does not support querying assets yet. - showAssetList: !props.local.assetID && false, + assetID: props.local.assetID, }} render={render} /> diff --git a/src/core/client/stream/queries/__snapshots__/AppQuery.spec.tsx.snap b/src/core/client/stream/queries/__snapshots__/AppQuery.spec.tsx.snap new file mode 100644 index 000000000..dbd2ad45a --- /dev/null +++ b/src/core/client/stream/queries/__snapshots__/AppQuery.spec.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders app 1`] = ` + +`; + +exports[`renders error 1`] = ` +
+ error +
+`; + +exports[`renders loading 1`] = ` +
+ Loading +
+`; diff --git a/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap b/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap new file mode 100644 index 000000000..b3d193c41 --- /dev/null +++ b/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap @@ -0,0 +1,256 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`loads more comments 1`] = ` +
+
+

+ Talk NEO +

+
+
+