Implement Timestamp

Merge branch 'next' into timestamp

Fix test and translations

Merge branch 'timestamp' of github.com:coralproject/talk into timestamp

* 'timestamp' of github.com:coralproject/talk:
  Fix test and translations
  Implement Timestamp
This commit is contained in:
Belén Curcio
2018-07-10 13:34:27 -03:00
parent 0784e7dd63
commit 805492931b
42 changed files with 734 additions and 285 deletions
+17
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
node_modules
+3 -5
View File
@@ -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"
}
}
+7 -2
View File
@@ -8,7 +8,7 @@ module.exports = {
setupFiles: ["<rootDir>/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/(.*)$": "<rootDir>/src/core/client/admin/$1",
"^talk-ui/(.*)$": "<rootDir>/src/core/client/ui/$1",
"^talk-stream/(.*)$": "<rootDir>/src/core/client/stream/$1",
"^talk-framework/(.*)$": "<rootDir>/src/core/client/framework/$1",
"^talk-common/(.*)$": "<rootDir>/src/core/common/$1",
"^talk-server/(.*)$": "<rootDir>/src/core/server/$1",
},
moduleFileExtensions: [
"web.js",
+88 -8
View File
@@ -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}`;
},
};
-8
View File
@@ -1,8 +0,0 @@
{
"exec": "npm-run-all compile:relay-stream",
"ext": "ts,tsx,graphql",
"watch": [
"./src/core/client/stream",
"./src/core/**/*.graphql"
]
}
-10
View File
@@ -1,10 +0,0 @@
{
"exec": "npm run start:development",
"ext": "ts,graphql",
"watch": [
"./src"
],
"ignore": [
"./src/client"
]
}
+1 -1
View File
@@ -180,7 +180,7 @@ module.exports = {
// All available locales can be loadable on demand.
// To restrict available locales set:
// availableLocales: ["en-US"]
// availableLocales: ["en-US"],
},
},
],
+133 -178
View File
@@ -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": {
@@ -9820,12 +9824,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",
@@ -10841,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": {
@@ -10871,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",
@@ -10888,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",
@@ -10944,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": {
@@ -11009,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": {
@@ -11062,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"
}
},
@@ -11101,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",
@@ -11120,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": {
@@ -11137,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"
@@ -11179,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",
@@ -11191,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",
@@ -11214,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"
@@ -11252,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",
@@ -12790,50 +12793,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",
@@ -15881,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": {
@@ -15936,15 +15895,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",
@@ -16419,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",
@@ -16519,6 +16475,23 @@
}
}
},
"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"
}
},
"react-timeago": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/react-timeago/-/react-timeago-4.1.9.tgz",
"integrity": "sha512-MKucv9nU65BOPqIrClAFxqvpGCC4RdRpqp0P1YIb7C3yT6TQVdcoOlr0k4TDHvLQhbkwd3nbTxiDQMa3iDlZxg=="
},
"read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@@ -16568,9 +16541,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"
@@ -17814,9 +17787,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": {
@@ -18801,15 +18774,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 +19648,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",
+8 -5
View File
@@ -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",
@@ -44,6 +45,7 @@
"mongodb": "^3.0.10",
"passport": "^0.4.0",
"performance-now": "^2.1.0",
"react-timeago": "^4.1.9",
"subscriptions-transport-ws": "^0.9.11",
"uuid": "^3.2.1"
},
@@ -72,7 +74,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,9 +103,8 @@
"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",
"nodemon": "^1.17.5",
"npm-run-all": "^4.1.3",
"postcss-flexbugs-fixes": "^3.3.1",
"postcss-font-magician": "^2.2.1",
@@ -116,6 +118,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",
@@ -141,4 +144,4 @@
"webpack-hot-client": "^4.0.3",
"webpack-manifest-plugin": "^2.0.3"
}
}
}
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -5,13 +5,13 @@ import { Executor } from "./types";
interface CommandExecutorOptions {
args?: ReadonlyArray<string>;
// 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;
}
+1 -1
View File
@@ -6,7 +6,7 @@ import { Executor } from "./types";
interface LongRunningExecutorOptions {
args?: ReadonlyArray<string>;
// 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;
}
+10 -2
View File
@@ -4,16 +4,24 @@ import program from "commander";
import path from "path";
import watch from "../";
function list(val: string) {
return val.split(",");
}
program
.version("0.1.0")
.usage("<configFile>")
.option("-o, --only <watcher>", "only run the specified watcher", list)
.arguments("<configFile>")
.description("Run watchers defined in <configFile>")
.action(configFile => {
.action((configFile, cmd) => {
const { only = [] } = cmd;
let config: any = require(path.resolve(configFile));
if (config.__esModule) {
config = config.default;
}
watch(config);
watch(config, { only });
})
.parse(process.argv);
+4
View File
@@ -17,6 +17,10 @@ export interface Executor {
execute(filePath: string): void;
}
export interface Options {
only?: string[];
}
export interface Config {
rootDir?: string;
backend?: Watcher;
+15 -2
View File
@@ -2,7 +2,7 @@ import Joi from "joi";
import path from "path";
import ChokidarWatcher from "./ChokidarWatcher";
import { Config, configSchema, WatchConfig, Watcher } from "./types";
import { Config, configSchema, Options, WatchConfig, Watcher } from "./types";
// Polyfill the asyncIterator symbol.
if (Symbol.asyncIterator === undefined) {
@@ -43,9 +43,22 @@ function setupCleanup(config: Config) {
);
}
export default async function watch(config: Config) {
function filterOnly(config: Config, only: string[]) {
for (const key of Object.keys(config.watchers)) {
if (only.indexOf(key) === -1) {
// tslint:disable-next-line:no-console
console.log(`Disabled watcher "${key}"`);
delete config.watchers[key];
}
}
}
export default async function watch(config: Config, options?: Options) {
Joi.assert(config, configSchema);
const watcher = config.backend || new ChokidarWatcher();
if (options && options.only && options.only.length > 0) {
filterOnly(config, options.only);
}
setupCleanup(config);
for (const key of Object.keys(config.watchers)) {
// tslint:disable-next-line:no-console
@@ -1,7 +1,9 @@
import { LocalizationProvider } from "fluent-react/compat";
import { MessageContext } from "fluent/compat";
import React, { StatelessComponent } from "react";
import { Formatter } from "react-timeago";
import { Environment } from "relay-runtime";
import { UIContext } from "talk-ui/components";
export interface TalkContext {
// relayEnvironment for our relay framework.
@@ -9,6 +11,9 @@ export interface TalkContext {
// localMessages for our i18n framework.
localeMessages: MessageContext[];
// formatter for timeago.
timeagoFormatter: Formatter;
}
const { Provider, Consumer } = React.createContext<TalkContext>({} as any);
@@ -27,7 +32,9 @@ export const TalkContextProvider: StatelessComponent<{
}> = ({ value, children }) => (
<Provider value={value}>
<LocalizationProvider messages={value.localeMessages}>
{children}
<UIContext.Provider value={{ timeagoFormatter: value.timeagoFormatter }}>
{children}
</UIContext.Provider>
</LocalizationProvider>
</Provider>
);
@@ -1,4 +1,7 @@
import { Localized } from "fluent-react/compat";
import { noop } from "lodash";
import React from "react";
import { Formatter } from "react-timeago";
import { Environment, Network, RecordSource, Store } from "relay-runtime";
import { generateMessages, LocalesData, negotiateLanguages } from "../i18n";
@@ -16,6 +19,25 @@ interface CreateContextArguments {
init?: ((context: TalkContext) => void | Promise<void>);
}
/**
* timeagoFormatter integrates timeago into our translation
* framework. It gets injected into the UIContext.
*/
export const timeagoFormatter: Formatter = (value, unit, suffix) => {
// We use 'in' instead of 'from now' for language consistency
const ourSuffix = suffix === "from now" ? "in" : suffix;
return (
<Localized
id="framework-timeago"
$value={value}
$unit={unit}
$suffix={ourSuffix}
>
<span>now</span>
</Localized>
);
};
/**
* `createContext` manages the dependencies of our framework
* and returns a `TalkContext` that can be passed to the
@@ -46,6 +68,7 @@ export default async function createContext({
const context = {
relayEnvironment,
localeMessages,
timeagoFormatter,
};
// Run custom initializations.
@@ -0,0 +1,30 @@
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",
createdAt: new Date("December 17, 1995 03:24:00").toISOString(),
};
const renderer = createRenderer();
renderer.render(<Comment {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders with gutterBottom", () => {
const props = {
author: {
username: "Marvin",
},
body: "Woof",
createdAt: new Date("December 17, 1995 03:24:00").toISOString(),
gutterBottom: true,
};
const renderer = createRenderer();
renderer.render(<Comment {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -2,7 +2,7 @@ import cn from "classnames";
import React from "react";
import { StatelessComponent } from "react";
import { Typography } from "talk-ui/components";
import { Timestamp, Typography } from "talk-ui/components";
import * as styles from "./Comment.css";
@@ -12,6 +12,7 @@ export interface CommentProps {
username: string;
} | null;
body: string | null;
createdAt: string;
gutterBottom?: boolean;
}
@@ -24,6 +25,7 @@ const Comment: StatelessComponent<CommentProps> = props => {
<Typography className={styles.author} gutterBottom>
{props.author && props.author.username}
</Typography>
<Timestamp date={props.createdAt} />
<Typography>{props.body}</Typography>
</div>
);
@@ -0,0 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders username and body 1`] = `
<div
className="root"
>
<withPropsOnChange(Typography)
className="author"
gutterBottom={true}
>
Marvin
</withPropsOnChange(Typography)>
<withPropsOnChange(Timestamp)
date="1995-12-17T06:24:00.000Z"
/>
<withPropsOnChange(Typography)>
Woof
</withPropsOnChange(Typography)>
</div>
`;
exports[`renders with gutterBottom 1`] = `
<div
className="root gutterBottom"
>
<withPropsOnChange(Typography)
className="author"
gutterBottom={true}
>
Marvin
</withPropsOnChange(Typography)>
<withPropsOnChange(Timestamp)
date="1995-12-17T06:24:00.000Z"
/>
<withPropsOnChange(Typography)>
Woof
</withPropsOnChange(Typography)>
</div>
`;
@@ -20,6 +20,7 @@ const enhanced = withFragmentContainer<{ data: Data }>(
author {
username
}
createdAt
body
}
`
+10 -33
View File
@@ -5,40 +5,17 @@
"module": "esnext",
"jsx": "preserve",
"allowJs": false,
"lib": [
"dom",
"es7",
"scripthost",
"es2015",
"esnext.asynciterable"
],
"lib": ["dom", "es7", "scripthost", "es2015", "esnext.asynciterable"],
"baseUrl": "./",
"paths": {
"talk-admin/*": [
"./admin/*"
],
"talk-stream/*": [
"./stream/*"
],
"talk-framework/*": [
"./framework/*"
],
"talk-ui/*": [
"./ui/*"
],
"talk-common/*": [
"../common/*"
],
"talk-locales/*": [
"../../locales/*"
]
"talk-admin/*": ["./admin/*"],
"talk-stream/*": ["./stream/*"],
"talk-framework/*": ["./framework/*"],
"talk-ui/*": ["./ui/*"],
"talk-common/*": ["../common/*"],
"talk-locales/*": ["../../locales/*"]
}
},
"include": [
"./**/*",
"../../types/**/*.d.ts"
],
"exclude": [
"node_modules"
]
}
"include": ["./**/*", "../../types/**/*.d.ts"],
"exclude": ["node_modules"]
}
@@ -0,0 +1,4 @@
.root {
composes: body1 from "talk-ui/shared/typography.css";
background-color: transparent;
}
@@ -0,0 +1,15 @@
---
name: Timestamp
menu: UI Kit
---
import { Playground } from 'docz'
import Timestamp from './Timestamp'
# Timestamp
## Basic usage
<Playground>
<Timestamp date={`2018-07-04T12:14:14.564Z`} />
</Playground>
@@ -0,0 +1,30 @@
import React from "react";
import { create } from "react-test-renderer";
import UIContext from "../UIContext";
import Timestamp from "./Timestamp";
it("uses default formatter", () => {
const props = {
date: new Date("December 17, 2108 03:24:00").toISOString(),
};
const tree = create(<Timestamp {...props} />).toJSON();
expect(tree).toMatchSnapshot();
});
it("uses formatter from context", () => {
const context: any = {
timeagoFormatter: () => "My Formatter",
};
const props = {
date: new Date("December 17, 2108 03:24:00").toISOString(),
};
const tree = create(
<UIContext.Provider value={context}>
<Timestamp {...props} />
</UIContext.Provider>
).toJSON();
expect(tree).toMatchSnapshot();
});
@@ -0,0 +1,41 @@
import cn from "classnames";
import React from "react";
import TimeAgo, { Formatter } from "react-timeago";
import { UIContext } from "talk-ui/components";
import { withStyles } from "talk-ui/hocs";
import { PropTypesOf } from "talk-ui/types";
import * as styles from "./Timestamp.css";
interface InnerProps {
date: string;
live?: boolean;
classes: typeof styles;
className?: string;
}
const defaultFormatter: Formatter = (value, unit, suffix, timestamp: string) =>
new Date(timestamp).toISOString();
class Timestamp extends React.Component<InnerProps> {
public render() {
const { date, classes, live, className } = this.props;
return (
<UIContext.Consumer>
{({ timeagoFormatter }) => (
<TimeAgo
date={date}
className={cn(className, classes.root)}
live={live}
formatter={timeagoFormatter || defaultFormatter}
/>
)}
</UIContext.Consumer>
);
}
}
const enhanced = withStyles(styles)(Timestamp);
export type TimestampProps = PropTypesOf<typeof enhanced>;
export default enhanced;
@@ -0,0 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`uses default formatter 1`] = `
<time
className="root"
dateTime="2108-12-17T06:24:00.000Z"
title="2108-12-17T06:24:00.000Z"
>
2108-12-17T06:24:00.000Z
</time>
`;
exports[`uses formatter from context 1`] = `
<time
className="root"
dateTime="2108-12-17T06:24:00.000Z"
title="2108-12-17T06:24:00.000Z"
>
My Formatter
</time>
`;
@@ -0,0 +1,2 @@
export * from "./Timestamp";
export { default } from "./Timestamp";
@@ -0,0 +1,10 @@
import React from "react";
import { Formatter } from "react-timeago";
export interface UIContext {
timeagoFormatter: Formatter;
}
const UIContext = React.createContext<UIContext>({} as any);
export default UIContext;
@@ -0,0 +1 @@
export { default } from "./UIContext";
+2
View File
@@ -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 Timestamp } from "./Timestamp";
export { default as UIContext } from "./UIContext";
+8 -4
View File
@@ -33,11 +33,14 @@
color: $palette-text-primary;
}
.subtitle1 {}
.subtitle1 {
}
.subtitle2 {}
.subtitle2 {
}
.body2 {}
.body2 {
}
.body1 {
font-size: calc(16rem / $rem-base);
@@ -56,4 +59,5 @@
letter-spacing: calc(0.57em / 16);
}
.overline {}
.overline {
}
+1 -1
View File
@@ -43,7 +43,7 @@ async function createTenantRouter(opts: AppOptions) {
async function createAPIRouter(opts: AppOptions) {
// Create a router.
const router = express.Router();
// Configure the tenant routes.
router.use("/tenant", await createTenantRouter(opts));
@@ -2,6 +2,8 @@ import Context from "talk-server/graph/tenant/context";
import { Comment, ConnectionInput } from "talk-server/models/comment";
export default {
createdAt: async (comment: Comment, _: any, ctx: Context) =>
comment.created_at,
author: async (comment: Comment, _: any, ctx: Context) =>
ctx.loaders.Users.user.load(comment.author_id),
replies: async (comment: Comment, input: ConnectionInput, ctx: Context) =>
@@ -202,6 +202,11 @@ type Comment {
"""
body: String
"""
createdAt is the date in which the comment was created.
"""
createdAt: Time
"""
author is the User that authored the Comment.
"""
+38
View File
@@ -3,3 +3,41 @@
### among different targets.
framework-validation-required = Dies ist ein Pflichtpfeld.
framework-timeago =
{ $suffix ->
[ago] vor
[in] in
}
{ $value }
{ $unit ->
[second] { $value ->
[1] Sekunde
*[other] Sekunden
}
[minuto] { $value ->
[1] Minute
*[other] Minuten
}
[hour] { $value ->
[0] Stunde
*[other] Stunden
}
[day] { $value ->
[1] Tag
*[other] Tage
}
[week] { $value ->
[1] Woche
*[other] Wochen
}
[month] { $value ->
[1] Monat
*[other] Monate
}
[year] { $value ->
[1] Jahr
*[other] Jahre
}
*[other] unknown unit
}
+45
View File
@@ -3,3 +3,48 @@
### among different targets.
framework-validation-required = This field is required.
framework-timeago-time =
{ $value }
{ $unit ->
[second] { $value ->
[1] second
*[other] seconds
}
[minute] { $value ->
[1] minute
*[other] minutes
}
[hour] { $value ->
[0] hour
*[other] hours
}
[day] { $value ->
[1] day
*[other] days
}
[week] { $value ->
[1] week
*[other] weeks
}
[month] { $value ->
[1] month
*[other] months
}
[year] { $value ->
[1] year
*[other] years
}
*[other] unknown unit
}
framework-timeago =
{ $value ->
[0] now
*[other]
{ $suffix ->
[ago] {framework-timeago-time} ago
[in] in {framework-timeago-time}
*[other] unknown suffix
}
}
View File
+42
View File
@@ -2,3 +2,45 @@
### All keys must start with `framework` because this file is shared
### among different targets.
framework-timeago =
{ $value ->
[0] ahora
*[other]
{ $suffix ->
[ago] hace
[in] en
*[other] unknown suffix
}
{ $value }
{ $unit ->
[second] { $value ->
[1] segundo
*[other] segundos
}
[minute] { $value ->
[1] minuto
*[other] minutos
}
[hour] { $value ->
[0] hora
*[other] horas
}
[day] { $value ->
[1] dia
*[other] dias
}
[week] { $value ->
[1] semana
*[other] semanas
}
[month] { $value ->
[1] mes
*[other] meses
}
[year] { $value ->
[1] año
*[other] años
}
*[other] unknown unit
}
}
+6 -19
View File
@@ -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"
]
}
"include": ["./**/*"],
"exclude": ["node_modules", "./core/client"]
}
+55
View File
@@ -0,0 +1,55 @@
declare module "react-timeago" {
import React from "react";
export type Formatter = (
value: number,
unit: "second" | "minute" | "hour" | "day" | "week" | "month" | "year",
suffix: "ago" | "from now",
epochMiliseconds: string
) => string | React.ReactElement<any>;
export interface LocaleDefinition {
prefixAgo?: string;
prefixFromNow?: string;
suffixAgo?: string;
suffixFromNow?: string;
second?: string;
seconds?: string;
minute?: string;
minutes?: string;
hour?: string;
hours?: string;
day?: string;
days?: string;
week?: string;
weeks?: string;
month?: string;
months?: string;
year?: string;
years?: string;
wordSeparator?: string;
numbers?: number[];
}
export interface TimeAgoProps {
date: string;
live?: boolean;
className: string;
formatter?: Formatter;
}
const TimeAgo: React.ComponentType<TimeAgoProps>;
export default TimeAgo;
}
declare module "react-timeago/lib/formatters/buildFormatter" {
import { Formatter, LocaleDefinition } from "react-timeago";
function buildFormatter(localeInput: LocaleDefinition): Formatter;
export default buildFormatter;
}
declare module "react-timeago/lib/language-strings/*" {
import { LocaleDefinition } from "react-timeago";
const localeStrings: LocaleDefinition;
export default localeStrings;
}