[CORL-878] Upgrade dependencies (#2867)

* chore: upgrade fluent

* chore: upgrade metascraper

* chore: upgrade akismet-api

* chore: upgrade apollo-server-express

* chore: upgrade archiver

* chore: upgrade bull

* chore: upgrade express, cheerio, content-security-policy-builder

* chore: upgrade convict

* chore: upgrade cors, cron

* chore: upgrade csv-stringify

* chore: upgrade dompurify

* chore: upgrade dotenv

* chore: upgrade express-static-gzip

* chore: upgrade fs-extra

* chore: upgrade graphql-js

* chore: upgrade graphql packages

* chore: upgrade html-minifier

* chore: upgrade html-to-text

* chore: upgrade ioredis

* chore: upgrade joi

* chore: upgrade jsdom

* chore: upgrade jsonwebtoken

* chore: upgrade juice

* chore: upgrade jwks-rsa ad linkifyjs

* chore: upgrade lodash

* chore: upgrade luxon

* chore: upgrade metascraper

* chore: upgrade mongodb

* chore: upgrade ms

* chore: upgrade node and node-fetch types

* chore: upgrade nodemailer nunjucks and typescript-eslint

* chore: Upgrade passport

* upgrade: prom-client react-helmet source-map-support stack-utils

* chore: upgrade uuid

* chore: upgrade @babel packages

* chore: upgrade types

* chore: upgrade autoprefixer

* chore: upgrade jest

* chore: upgrade ts-jest

* chore: remove linkify.d.ts

* chore: upgrade bowser

* chore: case-sensitive-paths-webpack-plugin

* chore: upgrade classnames

* chore: upgrade commander

* chore: upgrade comment-json

* chore: upgrade cross-spawn compression-webpack-plugin del

* chore: upgrade build and watch related dependencies

* chore: upgrade css-vars-ponyfill

* chore: upgrade eslint and css-vars-ponyfill

* chore: upgrade enzyme and eventemitter2

* fix: form bug

* chore: upgrade farce

* chore: upgrade final form

* chore: upgrade react-popper

* chore: upgrade flat and fork-ts-checker-webpack-plugin

* chore: upgrade husky and gulp related, intersection observer

* chore: upgrade lint-staged

* chore: upgrade marked, loader-utils, mini-css-extract-plugin

* chore: upgrade postcss-nested, proxy-polyfill, pstree.remy

* chore: upgrade prettier

* chore: fix prettier changes, upgrade react

* chore: mute createFactory deprecated message

* chore: upgrade react-copy-to-clipbard, react-axe, react-dom, react-test-renderer, react-timeago

* chore: upgrade react-transistion-group, react-responsive

* chore: upgrade types

* chore: upgrade react-dev-utils, react-error-overlay regenerator-runtime

* chore: upgrade types, sinon, sockjs-client, strip-ansi

* chore: upgrade types, fonts

* chore: upgrade nunjucks, ts-node, typescript-snapshot-plugin, wait-for-expect

* chore: upgrade eslint packages

* chore: upgrade fluent, types

* chore: upgrade jsdom dep

* chore: upgrade mongo

* chore: upgrade deps

* chore: upgrade typescript, recompose

* chore: upgrade prettier

* chore: remove obsolete prettier config

* chore: upgrade jsdom types

* chore: upgrade typescript-eslint

* chore: upgrad deps

* chore: upgrade deps

* chore: upgrade relay related modules

* chore: upgrade docz WIP

* chore: upgrade docz

* chore: add guard

* chore: remove obsolete line

* chore: comment

* chore: refactors

* fix: hook count change error
This commit is contained in:
Vinh
2020-04-15 18:15:31 +02:00
committed by GitHub
parent e180cf87d7
commit c9a0ab8848
996 changed files with 29216 additions and 18256 deletions
+6 -4
View File
@@ -54,7 +54,7 @@ const typescriptOverrides = {
"@typescript-eslint/indent": "off", "@typescript-eslint/indent": "off",
"@typescript-eslint/interface-name-prefix": "error", "@typescript-eslint/interface-name-prefix": "error",
"@typescript-eslint/member-delimiter-style": "off", "@typescript-eslint/member-delimiter-style": "off",
"@typescript-eslint/no-empty-function": "error", "@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-misused-new": "error",
@@ -77,6 +77,7 @@ const typescriptOverrides = {
"react/display-name": "error", "react/display-name": "error",
"react/prop-types": "off", "react/prop-types": "off",
"react/no-unescaped-entities": "off", "react/no-unescaped-entities": "off",
"no-empty-function": "off",
} }
), ),
}; };
@@ -84,7 +85,7 @@ const typescriptOverrides = {
let typescriptTypeCheckingOverrides = { let typescriptTypeCheckingOverrides = {
files: ["*.ts", "*.tsx"], files: ["*.ts", "*.tsx"],
parserOptions: { parserOptions: {
project: ["tsconfig.json", "./src/tsconfig.json", "./src/core/client/tsconfig.json"], project: ["./tsconfig.json", "./src/tsconfig.json", "./src/core/client/tsconfig.json"],
// TODO: (cvle) this is a workaround, see: https://github.com/typescript-eslint/typescript-eslint/issues/1091. // TODO: (cvle) this is a workaround, see: https://github.com/typescript-eslint/typescript-eslint/issues/1091.
createDefaultProgram: true, createDefaultProgram: true,
}, },
@@ -95,9 +96,10 @@ let typescriptTypeCheckingOverrides = {
"rules": { "rules": {
"ordered-imports": { "ordered-imports": {
"options": { "options": {
"import-sources-order": "case-insensitive", // Legacy sorting until this is fixed: https://github.com/SoominHan/import-sorter/issues/60
"import-sources-order": "case-insensitive-legacy",
"module-source-path": "full", "module-source-path": "full",
"named-imports-order": "case-insensitive", "named-imports-order": "case-insensitive-legacy",
}, },
}, },
}, },
-3
View File
@@ -1,3 +0,0 @@
{
"trailingComma": "es5"
}
+1 -1
View File
@@ -54,5 +54,5 @@
"search.exclude": { "search.exclude": {
"package-lock.json": true "package-lock.json": true
}, },
"debug.node.autoAttach": "on" "debug.node.autoAttach": "off",
} }
+1 -1
View File
@@ -10,7 +10,7 @@ const plugins =
const environment = const environment =
process.env.WEBPACK === "true" process.env.WEBPACK === "true"
? { targets: "IE 11", modules: false } ? { modules: false }
: { targets: { node: "current" }, modules: "commonjs" }; : { targets: { node: "current" }, modules: "commonjs" };
module.exports = { module.exports = {
+3 -5
View File
@@ -40,11 +40,9 @@ module.exports = {
snapshotSerializers: ["enzyme-to-json/serializer"], snapshotSerializers: ["enzyme-to-json/serializer"],
globals: { globals: {
"ts-jest": { "ts-jest": {
useBabelrc: true, babelConfig: true,
tsConfigFile: path.resolve( tsConfig: path.resolve(__dirname, "../../src/core/client/tsconfig.json"),
__dirname,
"../../src/core/client/tsconfig.json"
),
}, },
}, },
preset: "ts-jest/presets/js-with-babel",
}; };
+3 -2
View File
@@ -21,8 +21,9 @@ module.exports = {
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
globals: { globals: {
"ts-jest": { "ts-jest": {
useBabelrc: true, babelConfig: true,
tsConfigFile: path.resolve(__dirname, "../../src/tsconfig.json"), tsConfig: path.resolve(__dirname, "../../src/tsconfig.json"),
}, },
}, },
preset: "ts-jest",
}; };
+3 -98
View File
@@ -1,105 +1,10 @@
// Apply all the configuration provided in the .env file. // Apply all the configuration provided in the .env file.
require("dotenv").config(); require("dotenv").config();
const fs = require("fs");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
const extensions = [".ts", ".tsx", ".js"];
// TODO: There is some weird issue with including paths.ts here
const postCSSConfigPath = "./src/core/build/postcss.config";
const appDirectory = fs.realpathSync(process.cwd());
const styleLoader = {
loader: require.resolve("style-loader"),
options: {
sourceMap: true,
hmr: true,
},
};
module.exports = { module.exports = {
title: "Coral 5.0", title: "Coral 5",
source: "./src", src: "./src",
typescript: true,
host: process.env.HOST || "0.0.0.0", host: process.env.HOST || "0.0.0.0",
port: parseInt(process.env.DOCZ_PORT, 10) || 3030, port: parseInt(process.env.DOCZ_PORT, 10) || 3030,
codeSandbox: false, // Too large to create code sandboxes.. files: "**/*.mdx",
modifyBundlerConfig: config => {
config.entry.app.push(
`${appDirectory}/src/core/client/ui/theme/variables.css.ts`
);
config.module.rules.push({
test: /\.css\.ts$/,
use: [
styleLoader,
{
loader: require.resolve("css-loader"),
options: {
modules: true,
importLoaders: 2,
localIdentName: "[name]-[local]-[hash:base64:5]",
sourceMap: true,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
path: postCSSConfigPath,
},
parser: "postcss-js",
},
},
{
loader: require.resolve("babel-loader"),
options: {
configFile: false,
babelrc: false,
presets: [
"@babel/typescript",
[
"@babel/env",
{ targets: { node: "current" }, modules: "commonjs" },
],
],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
},
},
],
});
config.module.rules.push({
test: /\.css$/,
use: [
styleLoader,
{
loader: require.resolve("css-loader"),
options: {
modules: true,
importLoaders: 1,
localIdentName: "[name]-[local]-[hash:base64:5]",
sourceMap: true,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
path: postCSSConfigPath,
},
},
},
],
});
config.resolve.plugins = [
new TsconfigPathsPlugin({
extensions,
// TODO: There is some weird issue with including paths.ts here
configFile: "./src/core/client/tsconfig.json",
}),
];
// fs.writeFileSync(path.resolve(__dirname, "tmp"), stringify(config, null, 2));
return config;
},
}; };
+216
View File
@@ -0,0 +1,216 @@
const fs = require("fs");
const path = require("path");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
/** Path to postCSSConfig */
const postCSSConfigPath = path.resolve(
__dirname,
"../src/core/build/postcss.config"
);
const rootDir = path.resolve(__dirname, "../");
const srcDir = path.resolve(rootDir, "./src");
const appTsconfig = path.resolve(rootDir, "./src/core/client/tsconfig.json");
const CSS_PATTERN = /\.css$/;
const MODULE_CSS_PATTERN = /\.module\.css$/;
// Define `RegExp.toJSON` so that we can stringify RegExp.
Object.defineProperty(RegExp.prototype, "toJSON", {
value: RegExp.prototype.toString,
});
const isCssRules = (rule) =>
rule.test &&
(rule.test.toString() === CSS_PATTERN.toString() ||
rule.test.toString() === MODULE_CSS_PATTERN.toString());
const findCssRules = (config) =>
config.module.rules.find(
(rule) => Array.isArray(rule.oneOf) && rule.oneOf.every(isCssRules)
);
exports.onCreateWebpackConfig = ({
stage,
rules,
loaders,
plugins,
actions,
getConfig,
}) => {
// Get webpack config.
const config = getConfig();
if (stage === "develop") {
config.entry.commons.push(
// Add our global css variables file.
`${srcDir}/core/client/ui/theme/variables.css.ts`
);
}
/*
TODO: (cvle) couldn't get build to work...
if (stage === "build-javascript") {
config.entry.app = [
config.entry.app,
`${appDir}/core/client/ui/theme/variables.css.ts`,
];
}
*/
// Find the gatsby CSS rules.
const cssRules = findCssRules(config);
// Exclude them from our src dir because they are incomaptible with our
// CSS rules.
cssRules.exclude = srcDir;
// Add .tx .tsx to modules
config.resolve.extensions.push(".ts", ".tsx");
actions.replaceWebpackConfig(config);
// Write out webpack config to .docz folder.
fs.writeFileSync(
path.resolve(__dirname, "webpack-" + stage),
JSON.stringify(config, {}, 2)
);
// Turn on sourceMap during develop.
const sourceMap = stage.startsWith("develop");
// CSS loaders to prepend.
const prependCSSLoaders = [];
if (stage === "develop") {
prependCSSLoaders.push(loaders.style());
}
/*
TODO: (cvle) couldn't get build to work...
if (stage === "build-javascript") {
moreLoaders.push(loaders.style());
}
*/
actions.setWebpackConfig({
resolve: {
plugins: [
// Resolve our custom paths.
new TsconfigPathsPlugin({
extensions: [".ts", ".tsx", ".js"],
configFile: path.resolve(rootDir, "./src/core/client/tsconfig.json"),
}),
],
},
module: {
rules: [
{
include: srcDir,
oneOf: [
{
test: /\.css\.ts$/,
use: [
...prependCSSLoaders,
{
loader: require.resolve("css-loader"),
options: {
modules: {
localIdentName: "[name]-[local]-[hash:base64:5]",
},
importLoaders: 2,
sourceMap,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
path: postCSSConfigPath,
},
parser: "postcss-js",
},
},
{
loader: require.resolve("babel-loader"),
options: {
configFile: false,
babelrc: false,
presets: [
"@babel/typescript",
[
"@babel/env",
{ targets: { node: "current" }, modules: "commonjs" },
],
],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
},
},
],
},
{
test: /\.css$/,
use: [
...prependCSSLoaders,
{
loader: require.resolve("css-loader"),
options: {
modules: {
localIdentName: "[name]-[local]-[hash:base64:5]",
},
importLoaders: 1,
sourceMap,
},
},
{
loader: require.resolve("postcss-loader"),
options: {
config: {
path: postCSSConfigPath,
},
},
},
],
},
{
test: /\.tsx?$/,
use: [
{
loader: require.resolve("babel-loader"),
options: {
root: rootDir,
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
},
},
{
loader: require.resolve("ts-loader"),
options: {
configFile: appTsconfig,
compilerOptions: {
target: "es2015",
module: "esnext",
jsx: "preserve",
noEmit: false,
},
transpileOnly: true,
// Overwrites the behavior of `include` and `exclude` to only
// include files that are actually being imported and which
// are necessary to compile the bundle.
onlyCompileBundledFiles: true,
},
},
],
},
],
},
],
},
});
// Write out processed webpack config to .docz folder.
fs.writeFileSync(
path.resolve(__dirname, "webpack-" + stage + "-processed"),
JSON.stringify(getConfig(), {}, 2)
);
};
+25447 -14254
View File
File diff suppressed because it is too large Load Diff
+256 -243
View File
@@ -59,337 +59,344 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@coralproject/bunyan-prettystream": "^0.1.4", "@coralproject/bunyan-prettystream": "^0.1.4",
"@fluent/bundle": "^0.14.0", "@emotion/core": "^10.0.28",
"@fluent/bundle": "^0.15.0",
"@fluent/dom": "^0.6.0", "@fluent/dom": "^0.6.0",
"@metascraper/helpers": "^5.7.21", "@hapi/joi": "^17.1.1",
"@metascraper/helpers": "^5.11.6",
"abort-controller": "^3.0.0", "abort-controller": "^3.0.0",
"akismet-api": "^4.2.0", "akismet-api": "^5.0.0",
"apollo-server-express": "^2.8.1", "apollo-server-express": "^2.11.0",
"archiver": "^3.0.3", "archiver": "^3.1.1",
"basic-auth": "^2.0.1", "basic-auth": "^2.0.1",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"bull": "^3.8.1", "bull": "^3.13.0",
"bunyan": "^1.8.12", "bunyan": "^1.8.12",
"cheerio": "^1.0.0-rc.2", "cheerio": "^1.0.0-rc.3",
"consolidate": "0.14.0", "consolidate": "0.14.0",
"content-security-policy-builder": "^2.0.0", "content-security-policy-builder": "^2.1.0",
"convict": "^4.3.1", "convict": "^5.2.0",
"cookie": "^0.4.0", "cookie": "^0.4.0",
"cookie-parser": "^1.4.4", "cookie-parser": "^1.4.5",
"cors": "^2.8.4", "cors": "^2.8.5",
"cron": "^1.7.1", "cron": "^1.8.2",
"csv-stringify": "^5.3.0", "csv-stringify": "^5.3.6",
"dataloader": "^1.4.0", "dataloader": "1.4.0",
"dompurify": "^2.0.7", "dompurify": "^2.0.8",
"dotenv": "^6.0.0", "dotenv": "^8.2.0",
"dotenv-expand": "^4.2.0",
"env-rewrite": "^1.0.2", "env-rewrite": "^1.0.2",
"express": "^4.17.1", "express": "^4.17.1",
"express-enforces-ssl": "^1.1.0", "express-enforces-ssl": "^1.1.0",
"express-static-gzip": "^0.3.2", "express-static-gzip": "^2.0.6",
"fs-extra": "^6.0.1", "fs-extra": "^8.1.0",
"graphql": "^0.13.2", "graphql": "^14.6.0",
"graphql-config": "^2.0.1", "graphql-config": "^2.2.2",
"graphql-extensions": "^0.2.1", "graphql-extensions": "^0.11.0",
"graphql-fields": "^1.1.0", "graphql-fields": "2.0.3",
"graphql-import": "^0.7.1", "graphql-import": "^0.7.1",
"graphql-playground-html": "^1.6.0", "graphql-playground-html": "^1.6.13",
"graphql-redis-subscriptions": "^2.1.0", "graphql-redis-subscriptions": "^2.2.1",
"graphql-subscriptions": "^1.1.0", "graphql-subscriptions": "^1.1.0",
"graphql-tools": "^3.0.5", "graphql-tools": "^4.0.7",
"helmet": "^3.21.2", "helmet": "^3.22.0",
"html-minifier": "^3.5.21", "html-minifier": "^4.0.0",
"html-to-text": "^4.0.0", "html-to-text": "^5.1.1",
"ioredis": "^4.9.0", "ioredis": "^4.16.1",
"joi": "^13.4.0", "jsdom": "^16.2.2",
"jsdom": "^15.0.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"juice": "^5.2.0", "juice": "^6.0.0",
"jwks-rsa": "^1.6.0", "jwks-rsa": "^1.7.0",
"keymaster": "^1.6.2", "linkifyjs": "^2.1.9",
"linkifyjs": "^2.1.8",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"lru-cache": "^5.1.1", "lru-cache": "^5.1.1",
"luxon": "^1.12.0", "luxon": "^1.22.2",
"metascraper-author": "^5.8.0", "metascraper-author": "^5.11.6",
"metascraper-description": "^5.8.0", "metascraper-description": "^5.11.6",
"metascraper-image": "^5.8.0", "metascraper-image": "^5.11.6",
"metascraper-title": "^5.8.0", "metascraper-title": "^5.11.6",
"mongodb": "^3.2.7", "mongodb": "^3.5.5",
"mongodb-core": "^3.2.7", "mongodb-core": "^3.2.7",
"ms": "^2.1.1", "ms": "^2.1.2",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"nodemailer": "^4.6.7", "nodemailer": "^6.4.6",
"nunjucks": "^3.1.3", "nunjucks": "^3.2.1",
"on-finished": "^2.3.0", "on-finished": "^2.3.0",
"passport": "^0.4.1", "passport": "^0.4.1",
"passport-facebook": "^3.0.0", "passport-facebook": "^3.0.0",
"passport-google-oauth2": "^0.2.0", "passport-google-oauth2": "^0.2.0",
"passport-local": "^1.0.0", "passport-local": "^1.0.0",
"passport-oauth2": "^1.4.0", "passport-oauth2": "^1.5.0",
"passport-strategy": "^1.0.0", "passport-strategy": "^1.0.0",
"permit": "^0.2.4", "permit": "^0.2.4",
"prom-client": "^11.3.0", "prom-client": "^12.0.0",
"proxy-agent": "^3.1.1", "proxy-agent": "^3.1.1",
"querystringify": "^2.1.1", "querystringify": "^2.1.1",
"react-helmet": "^5.2.1", "source-map-support": "^0.5.16",
"source-map-support": "^0.5.12", "stack-utils": "^2.0.1",
"stack-utils": "^1.0.2",
"striptags": "^3.1.1", "striptags": "^3.1.1",
"throng": "^4.0.0", "throng": "^4.0.0",
"tsscmp": "^1.0.6", "tsscmp": "^1.0.6",
"url-regex": "^5.0.0", "url-regex": "^5.0.0",
"uuid": "^3.3.3", "uuid": "^7.0.3",
"verror": "^1.10.0", "verror": "^1.10.0",
"xregexp": "^4.3.0" "xregexp": "^4.3.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.8.3", "@babel/core": "^7.9.0",
"@babel/preset-env": "^7.8.3", "@babel/preset-env": "^7.9.0",
"@babel/preset-react": "^7.8.3", "@babel/preset-react": "^7.9.4",
"@babel/preset-typescript": "^7.8.3", "@babel/preset-typescript": "^7.9.0",
"@babel/runtime-corejs3": "^7.8.3", "@babel/runtime-corejs3": "^7.9.2",
"@coralproject/npm-run-all": "^4.1.5", "@coralproject/npm-run-all": "^4.1.5",
"@coralproject/rte": "^0.11.1", "@coralproject/rte": "^0.11.1",
"@fluent/react": "^0.10.0", "@fluent/react": "^0.11.1",
"@intervolga/optimize-cssnano-plugin": "^1.0.6", "@intervolga/optimize-cssnano-plugin": "^1.0.6",
"@types/agent-base": "^4.2.0", "@types/archiver": "^3.1.0",
"@types/archiver": "^3.0.0", "@types/basic-auth": "^1.1.3",
"@types/basic-auth": "^1.1.2", "@types/bcryptjs": "^2.4.2",
"@types/bcryptjs": "^2.4.1", "@types/bull": "^3.12.1",
"@types/bull": "^3.5.12", "@types/bunyan": "^1.8.6",
"@types/bunyan": "^1.8.4", "@types/case-sensitive-paths-webpack-plugin": "^2.1.4",
"@types/case-sensitive-paths-webpack-plugin": "^2.1.2", "@types/cheerio": "^0.22.17",
"@types/cheerio": "^0.22.8", "@types/classnames": "^2.2.10",
"@types/classnames": "^2.2.7",
"@types/commander": "^2.12.2",
"@types/common-tags": "^1.8.0", "@types/common-tags": "^1.8.0",
"@types/compression-webpack-plugin": "^2.0.0", "@types/compression-webpack-plugin": "^2.0.1",
"@types/consolidate": "0.0.34", "@types/consolidate": "0.14.0",
"@types/convict": "^4.2.0", "@types/convict": "^4.2.1",
"@types/cookie": "^0.3.3", "@types/cookie": "^0.3.3",
"@types/cookie-parser": "^1.4.1", "@types/cookie-parser": "^1.4.2",
"@types/cors": "^2.8.4", "@types/cors": "^2.8.6",
"@types/cron": "^1.7.1", "@types/cron": "^1.7.2",
"@types/cross-spawn": "^6.0.0", "@types/cross-spawn": "^6.0.1",
"@types/dompurify": "0.0.33", "@types/dompurify": "^2.0.1",
"@types/dotenv": "^4.0.3", "@types/enzyme": "^3.10.5",
"@types/enzyme": "^3.1.15", "@types/enzyme-adapter-react-16": "^1.0.6",
"@types/enzyme-adapter-react-16": "^1.0.3",
"@types/eventemitter2": "^4.1.0", "@types/eventemitter2": "^4.1.0",
"@types/express": "^4.16.0", "@types/express": "^4.17.4",
"@types/express-enforces-ssl": "^1.1.1", "@types/express-enforces-ssl": "^1.1.1",
"@types/flat": "0.0.28", "@types/express-serve-static-core": "^4.17.3",
"@types/fs-extra": "^5.0.4", "@types/flat": "^5.0.0",
"@types/graphql": "^0.13.3", "@types/fs-extra": "^8.1.0",
"@types/helmet": "0.0.45", "@types/hapi__joi": "^16.0.12",
"@types/html-minifier": "^3.5.2", "@types/helmet": "^0.0.45",
"@types/html-minifier": "^3.5.3",
"@types/html-minifier-terser": "^5.0.0",
"@types/html-to-text": "^1.4.31", "@types/html-to-text": "^1.4.31",
"@types/html-webpack-plugin": "^3.2.0", "@types/html-webpack-plugin": "^3.2.2",
"@types/ioredis": "^4.0.10", "@types/ioredis": "^4.14.9",
"@types/jest": "^24.0.23", "@types/jest": "^25.1.4",
"@types/jest-axe": "^3.2.1", "@types/jest-axe": "^3.2.1",
"@types/joi": "^13.0.8", "@types/jsdom": "^16.2.0",
"@types/jsdom": "^12.2.3", "@types/jsonwebtoken": "^8.3.8",
"@types/jsonwebtoken": "^8.3.5", "@types/linkifyjs": "^2.1.3",
"@types/linkifyjs": "^2.1.1", "@types/lodash": "^4.14.149",
"@types/lodash": "^4.14.118",
"@types/lru-cache": "^5.1.0", "@types/lru-cache": "^5.1.0",
"@types/luxon": "^1.12.0", "@types/luxon": "^1.22.0",
"@types/marked": "^0.6.0", "@types/marked": "^0.7.3",
"@types/mini-css-extract-plugin": "^0.2.0", "@types/mini-css-extract-plugin": "^0.9.1",
"@types/mongodb": "^3.1.22", "@types/mongodb": "3.1.22",
"@types/ms": "^0.7.30", "@types/ms": "^0.7.31",
"@types/node": "^10.5.2", "@types/node": "^12.12.34",
"@types/node-fetch": "^2.5.3", "@types/node-fetch": "^2.5.5",
"@types/nodemailer": "^4.6.2", "@types/nodemailer": "^6.4.0",
"@types/nunjucks": "^3.1.1", "@types/nunjucks": "^3.1.3",
"@types/object-diff": "0.0.0",
"@types/on-finished": "^2.3.1", "@types/on-finished": "^2.3.1",
"@types/passport": "^1.0.2", "@types/passport": "^1.0.3",
"@types/passport-facebook": "^2.1.8", "@types/passport-facebook": "^2.1.9",
"@types/passport-local": "^1.0.33", "@types/passport-local": "^1.0.33",
"@types/passport-oauth2": "^1.4.5", "@types/passport-oauth2": "^1.4.8",
"@types/passport-strategy": "^0.2.33", "@types/passport-strategy": "^0.2.35",
"@types/permit": "^0.2.1", "@types/permit": "^0.2.1",
"@types/prettier": "^1.19.0", "@types/prettier": "^1.19.1",
"@types/prop-types": "^15.5.8", "@types/react": "^16.9.31",
"@types/react": "^16.8.15",
"@types/react-axe": "^3.1.0", "@types/react-axe": "^3.1.0",
"@types/react-copy-to-clipboard": "^4.2.6", "@types/react-copy-to-clipboard": "^4.3.0",
"@types/react-dom": "^16.8.4", "@types/react-dom": "^16.9.6",
"@types/react-helmet": "^5.0.10", "@types/react-helmet": "^5.0.15",
"@types/react-relay": "^5.0.1", "@types/react-relay": "^7.0.3",
"@types/react-responsive": "^3.0.1", "@types/react-responsive": "^8.0.2",
"@types/react-test-renderer": "^16.8.1", "@types/react-test-renderer": "^16.9.2",
"@types/react-transition-group": "^2.0.14", "@types/react-transition-group": "^4.2.4",
"@types/recompose": "^0.26.5", "@types/recompose": "^0.30.7",
"@types/relay-runtime": "^5.0.5", "@types/relay-runtime": "^8.0.7",
"@types/sane": "^2.0.0", "@types/sane": "^2.0.0",
"@types/shallow-equals": "^1.0.0", "@types/shallow-equals": "^1.0.0",
"@types/simplemde": "^1.11.7", "@types/simplemde": "^1.11.7",
"@types/sinon": "^7.0.11", "@types/sinon": "^7.5.2",
"@types/source-map-support": "^0.5.0", "@types/source-map-support": "^0.5.1",
"@types/stack-trace": "0.0.29", "@types/stack-trace": "0.0.29",
"@types/stack-utils": "^1.0.1", "@types/stack-utils": "^1.0.1",
"@types/throng": "^4.0.2", "@types/throng": "^4.0.2",
"@types/uuid": "^3.4.4", "@types/uuid": "^7.0.2",
"@types/verror": "^1.10.3", "@types/verror": "^1.10.3",
"@types/vinyl": "^2.0.2", "@types/vinyl": "^2.0.4",
"@types/webpack": "^4.4.31", "@types/webpack": "^4.41.10",
"@types/webpack-assets-manifest": "^3.0.0", "@types/webpack-assets-manifest": "^3.0.0",
"@types/webpack-bundle-analyzer": "^2.13.1", "@types/webpack-bundle-analyzer": "^2.13.3",
"@types/webpack-dev-server": "^3.1.5", "@types/webpack-dev-server": "^3.10.1",
"@types/ws": "^5.1.2", "@types/ws": "^7.2.3",
"@types/xregexp": "^4.3.0", "@types/xregexp": "^4.3.0",
"@typescript-eslint/eslint-plugin": "2.3.3", "@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/eslint-plugin-tslint": "2.3.3", "@typescript-eslint/eslint-plugin-tslint": "^2.26.0",
"@typescript-eslint/parser": "2.3.3", "@typescript-eslint/parser": "^2.26.0",
"acorn": "^6.1.1", "autoprefixer": "^9.7.5",
"ansi-styles": "^3.2.0",
"autoprefixer": "^9.5.1",
"babel-core": "^7.0.0-bridge.0", "babel-core": "^7.0.0-bridge.0",
"babel-jest": "^24.9.0", "babel-jest": "^25.2.4",
"babel-loader": "^8.0.6", "babel-loader": "^8.1.0",
"babel-plugin-lodash": "^3.3.4", "babel-plugin-lodash": "^3.3.4",
"babel-plugin-module-resolver": "^3.2.0", "babel-plugin-module-resolver": "^4.0.0",
"babel-plugin-relay": "^5.0.0", "babel-plugin-relay": "^9.0.0",
"babel-plugin-use-lodash-es": "^0.2.0", "babel-plugin-use-lodash-es": "^0.2.0",
"bowser": "^1.9.4", "bowser": "^2.9.0",
"case-sensitive-paths-webpack-plugin": "^2.2.0", "case-sensitive-paths-webpack-plugin": "^2.3.0",
"chalk": "^2.4.2", "chalk": "^3.0.0",
"chokidar": "^3.0.0", "chokidar": "^3.3.1",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"commander": "^2.20.0", "commander": "^5.0.0",
"comment-json": "^1.1.3", "comment-json": "^3.0.2",
"common-tags": "^1.8.0", "common-tags": "^1.8.0",
"compression-webpack-plugin": "^2.0.0", "compression-webpack-plugin": "^3.1.0",
"copy-webpack-plugin": "^5.0.3",
"core-js": "^3.6.4", "core-js": "^3.6.4",
"cross-spawn": "^6.0.5", "cross-spawn": "^7.0.1",
"css-loader": "^1.0.1", "css-loader": "^3.4.2",
"css-vars-ponyfill": "^2.1.2", "css-vars-ponyfill": "^2.2.1",
"del": "^4.1.1", "del": "^5.1.0",
"doctoc": "^1.4.0", "doctoc": "^1.4.0",
"docz": "^0.13.7", "docz": "^v2.3.0-alpha.14",
"docz-theme-default": "^0.13.7", "enzyme": "^3.11.0",
"enzyme": "^3.9.0", "enzyme-adapter-react-16": "^1.15.2",
"enzyme-adapter-react-16": "^1.12.1", "enzyme-to-json": "^3.4.4",
"enzyme-to-json": "^3.3.5", "eslint": "^6.8.0",
"eslint": "^6.5.1", "eslint-config-prettier": "^6.10.1",
"eslint-config-prettier": "^6.3.0", "eslint-plugin-jsdoc": "^22.1.0",
"eslint-plugin-jsdoc": "^15.9.7",
"eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.1", "eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-react": "^7.15.1", "eslint-plugin-react": "^7.19.0",
"eventemitter2": "^5.0.1", "eventemitter2": "^6.3.1",
"farce": "^0.2.6", "farce": "^0.2.8",
"final-form": "4.18.6", "final-form": "4.18.6",
"final-form-arrays": "1.1.2", "final-form-arrays": "^3.0.2",
"flat": "^4.1.0", "flat": "^5.0.0",
"fluent-intl-polyfill": "^0.1.0", "fluent-intl-polyfill": "^0.1.0",
"fork-ts-checker-webpack-plugin": "^1.5.0", "fork-ts-checker-webpack-plugin": "^4.1.2",
"found": "^0.4.9", "found": "^0.4.10",
"found-relay": "^0.4.3", "found-relay": "^0.7.0",
"graphql-schema-linter": "^0.2.0", "graphql-schema-linter": "^0.2.4",
"graphql-schema-typescript": "^1.2.9", "graphql-schema-typescript": "^1.3.2",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-babel": "^8.0.0", "gulp-babel": "^8.0.0",
"gulp-cli": "^2.2.0", "gulp-cli": "^2.2.0",
"gulp-sourcemaps": "^2.6.5", "gulp-sourcemaps": "^2.6.5",
"gulp-typescript": "^5.0.1", "gulp-typescript": "^6.0.0-alpha.1",
"html-webpack-plugin": "^4.0.0-beta.11", "html-webpack-plugin": "^4.0.4",
"husky": "^2.2.0", "husky": "^4.2.3",
"intersection-observer": "^0.6.0", "intersection-observer": "^0.7.0",
"jest": "^24.8.0", "jest": "^25.2.4",
"jest-axe": "^3.2.0", "jest-axe": "^3.4.0",
"jest-junit": "^6.4.0", "jest-junit": "^10.0.0",
"jest-localstorage-mock": "^2.4.0", "jest-localstorage-mock": "^2.4.0",
"jest-mock-console": "^1.0.0", "jest-mock-console": "^1.0.0",
"lint-staged": "^8.1.6", "keymaster": "^1.6.2",
"loader-utils": "^1.2.3", "lint-staged": "^10.1.1",
"lodash-es": "^4.17.14", "loader-utils": "^2.0.0",
"marked": "^0.7.0", "lodash-es": "^4.17.15",
"marked": "^0.8.2",
"material-design-icons": "^3.0.1", "material-design-icons": "^3.0.1",
"mini-css-extract-plugin": "^0.6.0", "mini-css-extract-plugin": "^0.9.0",
"object-diff": "0.0.4", "postcss-advanced-variables": "^3.0.1",
"postcss-advanced-variables": "^3.0.0",
"postcss-calc-function": "^1.1.0", "postcss-calc-function": "^1.1.0",
"postcss-css-variables": "^0.11.0", "postcss-flexbugs-fixes": "^4.2.0",
"postcss-flexbugs-fixes": "^4.1.0", "postcss-font-magician": "^2.3.1",
"postcss-font-magician": "^2.2.1", "postcss-import": "^12.0.1",
"postcss-import": "^11.1.0", "postcss-js": "^2.0.3",
"postcss-js": "^2.0.1",
"postcss-loader": "^3.0.0", "postcss-loader": "^3.0.0",
"postcss-mixins": "^6.2.1", "postcss-mixins": "^6.2.3",
"postcss-nested": "^4.1.1", "postcss-nested": "^4.2.1",
"postcss-prepend-imports": "^1.0.1", "postcss-prepend-imports": "^1.0.1",
"postcss-preset-env": "^6.5.0", "postcss-preset-env": "^6.7.0",
"prettier": "^1.18.2", "prettier": "^2.0.2",
"prop-types": "^15.6.2", "proxy-polyfill": "^0.3.1",
"proxy-polyfill": "^0.3.0", "pstree.remy": "^1.1.7",
"pstree.remy": "^1.1.6",
"pym.js": "^1.3.2", "pym.js": "^1.3.2",
"raw-loader": "^0.5.1", "raw-loader": "^4.0.0",
"react": "^16.9.0", "react": "^16.13.1",
"react-axe": "^3.3.0", "react-axe": "^3.4.1",
"react-copy-to-clipboard": "^5.0.1", "react-copy-to-clipboard": "^5.0.2",
"react-dev-utils": "^9.0.0", "react-dev-utils": "^10.2.1",
"react-dom": "^16.9.0", "react-dom": "^16.13.1",
"react-error-overlay": "^5.1.6", "react-error-overlay": "^6.0.7",
"react-final-form": "6.3.0", "react-final-form": "6.3.0",
"react-final-form-arrays": "3.1.0", "react-final-form-arrays": "^3.1.1",
"react-popper": "^1.3.2", "react-helmet": "^5.2.1",
"react-relay": "^5.0.0", "react-popper": "^1.3.7",
"react-relay-network-modern": "^4.0.4", "react-relay": "^9.0.0",
"react-responsive": "^7.0.0", "react-relay-network-modern": "^4.6.1",
"react-test-renderer": "^16.9.0", "react-responsive": "^8.0.3",
"react-timeago": "^4.1.9", "react-test-renderer": "^16.13.1",
"react-transition-group": "^2.9.0", "react-timeago": "^4.4.0",
"react-with-state-props": "^2.0.4", "react-transition-group": "^4.3.0",
"recompose": "0.27.1", "recompose": "^0.30.0",
"regenerator-runtime": "^0.13.3", "regenerator-runtime": "^0.13.5",
"relay-compiler": "^5.0.0", "relay-compiler": "^9.0.0",
"relay-compiler-language-typescript": "^4.1.0", "relay-compiler-language-typescript": "^12.0.0",
"relay-local-schema": "^0.8.0", "relay-local-schema": "^0.8.0",
"relay-runtime": "^5.0.0", "relay-runtime": "^9.0.0",
"resize-observer-polyfill": "^1.5.1", "resize-observer-polyfill": "^1.5.1",
"sane": "^4.1.0", "sane": "^4.1.0",
"scheduler": "^0.15.0",
"shallow-equals": "^1.0.0", "shallow-equals": "^1.0.0",
"simplemde": "^1.11.2", "simplemde": "^1.11.2",
"simulant": "^0.2.2", "simulant": "^0.2.2",
"sinon": "^7.3.2", "sinon": "^9.0.1",
"sockjs-client": "^1.3.0", "sockjs-client": "^1.4.0",
"stack-trace": "0.0.10", "stack-trace": "^0.0.10",
"strip-ansi": "^5.2.0", "strip-ansi": "^6.0.0",
"style-loader": "^0.23.1", "style-loader": "^1.1.3",
"subscriptions-transport-ws": "^0.9.16", "subscriptions-transport-ws": "^0.9.16",
"terser-webpack-plugin": "^1.2.3", "terser-webpack-plugin": "^2.3.5",
"thread-loader": "^2.1.2", "thread-loader": "^2.1.3",
"timekeeper": "^2.2.0", "timekeeper": "^2.2.0",
"ts-jest": "<23.10.0", "ts-jest": "^25.3.0",
"ts-loader": "^6.0.0", "ts-loader": "^6.2.2",
"ts-node": "^8.1.0", "ts-node": "^8.8.1",
"ts-node-dev": "^1.0.0-pre.37", "ts-node-dev": "^1.0.0-pre.44",
"tsconfig-paths": "^3.8.0", "tsconfig-paths": "^3.9.0",
"tsconfig-paths-webpack-plugin": "^3.2.0", "tsconfig-paths-webpack-plugin": "^3.2.0",
"tslint": "^5.20.0", "tslint": "^6.1.0",
"typed-css-modules": "^0.4.2", "typed-css-modules": "^0.6.3",
"typeface-manuale": "^0.0.71", "typeface-manuale": "^1.1.4",
"typeface-nunito": "0.0.72", "typeface-nunito": "^1.1.3",
"typeface-open-sans": "0.0.75", "typeface-open-sans": "^0.0.75",
"typeface-source-sans-pro": "^0.0.54", "typeface-source-sans-pro": "^1.1.5",
"typescript": "3.3.4000", "typescript": "^3.8.3",
"typescript-snapshots-plugin": "^1.6.0", "typescript-snapshots-plugin": "^1.7.0",
"wait-for-expect": "^1.1.1", "wait-for-expect": "^1.3.0",
"webpack": "^4.41.5", "webpack": "^4.42.1",
"webpack-assets-manifest": "^3.1.1", "webpack-assets-manifest": "^3.1.1",
"webpack-bundle-analyzer": "^3.3.2", "webpack-bundle-analyzer": "^3.6.1",
"webpack-cli": "^3.3.2", "webpack-cli": "^3.3.11",
"webpack-dev-server": "3.2.1", "webpack-dev-server": "^3.10.3",
"whatwg-fetch": "^3.0.0" "whatwg-fetch": "^3.0.0"
}, },
"dependencies-pins-documentation": {
"wait-for-expect@1.x.x": [
"Newer versions breaks the use of jest fake timers"
],
"consolidate@14.0.0": [
"Newer versions has problems with using nunjucks.",
"Update when the following issue is resolved:",
"https://github.com/tj/consolidate.js/issues/244"
],
"final-form@4.18.6": [
"Newer versions has problems with resetting forms.",
"Update when the following issue is resolved:",
"https://github.com/final-form/final-form/issues/317"
],
"react-final-form@6.3.0": [
"Newer versions has problems with radio and checkbox fields.",
"Update when the following issue is resolved:",
"https://github.com/final-form/react-final-form/issues/683"
]
},
"husky": { "husky": {
"hooks": { "hooks": {
"pre-commit": "FAST_LINT=true lint-staged" "pre-commit": "FAST_LINT=true lint-staged"
@@ -406,8 +413,7 @@
"npm run docs:events -- --verify" "npm run docs:events -- --verify"
], ],
"{README,CLIENT_EVENTS,CONTRIBUTING,WEBHOOKS}.md": [ "{README,CLIENT_EVENTS,CONTRIBUTING,WEBHOOKS}.md": [
"npm run doctoc", "npm run doctoc"
"git add"
] ]
}, },
"bundlesize": [ "bundlesize": [
@@ -420,5 +426,12 @@
"rules": [ "rules": [
"types-are-capitalized" "types-are-capitalized"
] ]
} },
"browsers": [
">1%",
"last 4 versions",
"Firefox ESR",
"IE 11",
"not dead"
]
} }
+13 -11
View File
@@ -27,14 +27,14 @@ const forkTsCheckerWebpackPlugin = require("react-dev-utils/ForkTsCheckerWebpack
const isInteractive = false; const isInteractive = false;
function prepareUrls(protocol, host, port) { function prepareUrls(protocol, host, port) {
const formatUrl = hostname => const formatUrl = (hostname) =>
url.format({ url.format({
protocol, protocol,
hostname, hostname,
port, port,
pathname: "/", pathname: "/",
}); });
const prettyPrintUrl = hostname => const prettyPrintUrl = (hostname) =>
url.format({ url.format({
protocol, protocol,
hostname, hostname,
@@ -144,12 +144,12 @@ function createCompiler({
const tsMessagesPromises = []; const tsMessagesPromises = [];
if (useTypeScript) { if (useTypeScript) {
compiler.compilers.forEach(singleCompiler => { compiler.compilers.forEach((singleCompiler) => {
let tsMessagesPromise; let tsMessagesPromise;
let tsMessagesResolver; let tsMessagesResolver;
singleCompiler.hooks.beforeCompile.tap("beforeCompile", () => { singleCompiler.hooks.beforeCompile.tap("beforeCompile", () => {
tsMessagesPromise = new Promise(resolve => { tsMessagesPromise = new Promise((resolve) => {
tsMessagesResolver = msgs => resolve(msgs); tsMessagesResolver = (msgs) => resolve(msgs);
}); });
tsMessagesPromises.push(tsMessagesPromise); tsMessagesPromises.push(tsMessagesPromise);
}); });
@@ -170,13 +170,15 @@ function createCompiler({
(diagnostics, lints) => { (diagnostics, lints) => {
console.log("RECEIVED"); console.log("RECEIVED");
const allMsgs = [...diagnostics, ...lints]; const allMsgs = [...diagnostics, ...lints];
const format = message => const format = (message) =>
`${message.file}\n${typescriptFormatter(message, true)}`; `${message.file}\n${typescriptFormatter(message, true)}`;
tsMessagesResolver({ tsMessagesResolver({
errors: allMsgs.filter(msg => msg.severity === "error").map(format), errors: allMsgs
.filter((msg) => msg.severity === "error")
.map(format),
warnings: allMsgs warnings: allMsgs
.filter(msg => msg.severity === "warning") .filter((msg) => msg.severity === "warning")
.map(format), .map(format),
}); });
} }
@@ -186,7 +188,7 @@ function createCompiler({
// "done" event fires when Webpack has finished recompiling the bundle. // "done" event fires when Webpack has finished recompiling the bundle.
// Whether or not you have warnings or errors, you will get this event. // Whether or not you have warnings or errors, you will get this event.
compiler.hooks.done.tap("done", async stats => { compiler.hooks.done.tap("done", async (stats) => {
if (isInteractive) { if (isInteractive) {
clearConsole(); clearConsole();
} }
@@ -203,7 +205,7 @@ function createCompiler({
...config.stats, ...config.stats,
}; };
if (Array.isArray(config)) { if (Array.isArray(config)) {
statOptions.children = config.map(c => c.stats || {}); statOptions.children = config.map((c) => c.stats || {});
} }
const statsData = stats.toJson(statOptions); const statsData = stats.toJson(statOptions);
@@ -220,7 +222,7 @@ function createCompiler({
const results = await Promise.all(tsMessagesPromises); const results = await Promise.all(tsMessagesPromises);
clearTimeout(delayedMsg); clearTimeout(delayedMsg);
results.forEach(msgs => { results.forEach((msgs) => {
statsData.errors.push(...msgs.errors); statsData.errors.push(...msgs.errors);
statsData.warnings.push(...msgs.warnings); statsData.warnings.push(...msgs.warnings);
+4 -2
View File
@@ -31,7 +31,7 @@ const isProduction = process.env.NODE_ENV === "production";
// Makes the script crash on unhandled rejections instead of silently // Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will // ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code. // terminate the Node.js process with a non-zero exit code.
process.on("unhandledRejection", err => { process.on("unhandledRejection", (err) => {
throw err; throw err;
}); });
@@ -117,7 +117,9 @@ function build(previousFileSizes: any) {
return reject(err); return reject(err);
} }
const messages = formatWebpackMessages( const messages = formatWebpackMessages(
stats.toJson({ children: webpackConfig.map(c => c.stats || {}) as any }) stats.toJson({
children: webpackConfig.map((c) => c.stats || {}) as any,
})
); );
if (messages.errors.length) { if (messages.errors.length) {
// Only keep the first error. Others are often indicative // Only keep the first error. Others are often indicative
+3 -3
View File
@@ -104,7 +104,7 @@ function gatherEntries(
docs: ts.displayPartsToString(symbol.getDocumentationComment(checker)), docs: ts.displayPartsToString(symbol.getDocumentationComment(checker)),
type: type.getSymbol()!.getName() as DocEntry["type"], type: type.getSymbol()!.getName() as DocEntry["type"],
}; };
typeNode.forEachChild(ch => { typeNode.forEachChild((ch) => {
if (ts.isTypeLiteralNode(ch)) { if (ts.isTypeLiteralNode(ch)) {
const text = printer.printNode( const text = printer.printNode(
ts.EmitHint.Unspecified, ts.EmitHint.Unspecified,
@@ -179,13 +179,13 @@ function emitDocs(markdownFile: string, entries: DocEntry[], verify = false) {
const summary = stripIndent` const summary = stripIndent`
- ${entries - ${entries
.map( .map(
e => `<a href="#${getEventName(e.name)}">${getEventName(e.name)}</a>` (e) => `<a href="#${getEventName(e.name)}">${getEventName(e.name)}</a>`
) )
.join("\n - ")} .join("\n - ")}
`; `;
const list = entries const list = entries
.map( .map(
e => (e) =>
codeBlock` codeBlock`
- ${ - ${
e.type === "ViewerEvent" e.type === "ViewerEvent"
+3 -3
View File
@@ -47,7 +47,7 @@ async function main() {
} }
// Create the types for this file. // Create the types for this file.
const types = await generateTSTypesAsString(schema, { const types = await generateTSTypesAsString(schema, file.fileName, {
tabSpaces: 2, tabSpaces: 2,
typePrefix: "GQL", typePrefix: "GQL",
strictNulls: false, strictNulls: false,
@@ -66,13 +66,13 @@ if (require.main === module) {
// Only run the main module on file load if this is the main module (we're // Only run the main module on file load if this is the main module (we're
// executing this file directly). // executing this file directly).
main() main()
.then(files => { .then((files) => {
for (const { fileName } of files) { for (const { fileName } of files) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(`Generated ${fileName}`); console.log(`Generated ${fileName}`);
} }
}) })
.catch(err => { .catch((err) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(err); console.error(err);
}); });
+1 -1
View File
@@ -26,7 +26,7 @@ process.env.NODE_ENV = "development";
// Makes the script crash on unhandled rejections instead of silently // Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will // ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code. // terminate the Node.js process with a non-zero exit code.
process.on("unhandledRejection", err => { process.on("unhandledRejection", (err) => {
throw err; throw err;
}); });
+1 -1
View File
@@ -17,7 +17,7 @@ process.env.NODE_ENV = "test";
// Makes the script crash on unhandled rejections instead of silently // Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will // ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code. // terminate the Node.js process with a non-zero exit code.
process.on("unhandledRejection", err => { process.on("unhandledRejection", (err) => {
throw err; throw err;
}); });
+1
View File
@@ -1,5 +1,6 @@
import chokidar from "chokidar"; import chokidar from "chokidar";
import path from "path"; import path from "path";
import { Watcher, WatchOptions } from "./types"; import { Watcher, WatchOptions } from "./types";
function prependRootDir( function prependRootDir(
+1 -1
View File
@@ -30,7 +30,7 @@ const cmd = program
.description("Run watchers defined in <configFile>") .description("Run watchers defined in <configFile>")
.parse(process.argv); .parse(process.argv);
run(cmd.args, cmd.opts()).catch(err => { run(cmd.args, cmd.opts()).catch((err) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(err); console.error(err);
process.exit(1); process.exit(1);
+4 -14
View File
@@ -1,4 +1,4 @@
import Joi from "joi"; import Joi from "@hapi/joi";
export interface WatchOptions { export interface WatchOptions {
ignore?: ReadonlyArray<string>; ignore?: ReadonlyArray<string>;
@@ -44,23 +44,13 @@ export const configSchema = Joi.object({
watchers: Joi.object().pattern( watchers: Joi.object().pattern(
/.*/, /.*/,
Joi.object({ Joi.object({
paths: Joi.array() paths: Joi.array().items(Joi.string()).unique(),
.items(Joi.string()) ignore: Joi.array().items(Joi.string()).unique().optional(),
.unique(),
ignore: Joi.array()
.items(Joi.string())
.unique()
.optional(),
executor: Joi.object(), executor: Joi.object(),
}) })
), ),
defaultSet: Joi.string().optional(), defaultSet: Joi.string().optional(),
sets: Joi.object() sets: Joi.object()
.pattern( .pattern(/.*/, Joi.array().items(Joi.string()).unique())
/.*/,
Joi.array()
.items(Joi.string())
.unique()
)
.optional(), .optional(),
}).with("defaultSet", "sets"); }).with("defaultSet", "sets");
+6 -6
View File
@@ -1,5 +1,5 @@
import Joi from "@hapi/joi";
import chalk from "chalk"; import chalk from "chalk";
import Joi from "joi";
import { pickBy } from "lodash"; import { pickBy } from "lodash";
import SaneWatcher from "./SaneWatcher"; import SaneWatcher from "./SaneWatcher";
@@ -28,7 +28,7 @@ async function beginWatch(
} }
function setupCleanup(watcher: Watcher, config: Config) { function setupCleanup(watcher: Watcher, config: Config) {
["SIGINT", "SIGTERM"].forEach(signal => ["SIGINT", "SIGTERM"].forEach((signal) =>
process.once(signal as any, async () => { process.once(signal as any, async () => {
const cleanups = []; const cleanups = [];
if (watcher.onCleanup) { if (watcher.onCleanup) {
@@ -50,7 +50,7 @@ function resolveSets(
value: ReadonlyArray<string> value: ReadonlyArray<string>
) { ) {
const resolved: string[] = []; const resolved: string[] = [];
value.forEach(v => { value.forEach((v) => {
if (v in sets) { if (v in sets) {
resolved.push(...sets[v]); resolved.push(...sets[v]);
return; return;
@@ -66,12 +66,12 @@ function filterOnly(
sets?: Record<string, ReadonlyArray<string>> sets?: Record<string, ReadonlyArray<string>>
): Config["watchers"] { ): Config["watchers"] {
const resolved = sets ? resolveSets(sets, only) : only; const resolved = sets ? resolveSets(sets, only) : only;
const unknown = resolved.filter(r => !(r in watchers)); const unknown = resolved.filter((r) => !(r in watchers));
if (unknown.length) { if (unknown.length) {
throw new Error(`Watcher Configuration or Set for ${unknown} not found`); throw new Error(`Watcher Configuration or Set for ${unknown} not found`);
} }
return pickBy(watchers, (value, key) => { return pickBy(watchers, (value, key) => {
if (resolved.indexOf(key) === -1) { if (!resolved.includes(key)) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(chalk.grey(`Disabled watcher "${key}"`)); console.log(chalk.grey(`Disabled watcher "${key}"`));
return false; return false;
@@ -101,7 +101,7 @@ export default async function watch(config: Config, options: Options = {}) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(chalk.cyanBright(`Start watcher "${key}"`)); console.log(chalk.cyanBright(`Start watcher "${key}"`));
const watcherConfig = watchersConfigs[key]; const watcherConfig = watchersConfigs[key];
beginWatch(watcher, key, watcherConfig, rootDir).catch(err => { beginWatch(watcher, key, watcherConfig, rootDir).catch((err) => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(err); console.error(err);
process.exit(1); process.exit(1);
+6 -14
View File
@@ -7,7 +7,6 @@ import HtmlWebpackPlugin from "html-webpack-plugin";
import { identity } from "lodash"; import { identity } from "lodash";
import MiniCssExtractPlugin from "mini-css-extract-plugin"; import MiniCssExtractPlugin from "mini-css-extract-plugin";
import path from "path"; import path from "path";
import typescriptFormatter from "react-dev-utils/typescriptFormatter";
import WatchMissingNodeModulesPlugin from "react-dev-utils/WatchMissingNodeModulesPlugin"; import WatchMissingNodeModulesPlugin from "react-dev-utils/WatchMissingNodeModulesPlugin";
import TerserPlugin from "terser-webpack-plugin"; import TerserPlugin from "terser-webpack-plugin";
import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin"; import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin";
@@ -82,10 +81,6 @@ export default function createWebpackConfig(
const styleLoader = { const styleLoader = {
loader: require.resolve("style-loader"), loader: require.resolve("style-loader"),
options: {
sourceMap: !disableSourcemaps,
hmr: watch,
},
}; };
const localesOptions = { const localesOptions = {
@@ -367,9 +362,10 @@ export default function createWebpackConfig(
{ {
loader: require.resolve("css-loader"), loader: require.resolve("css-loader"),
options: { options: {
modules: true, modules: {
localIdentName: "[name]-[local]-[contenthash]",
},
importLoaders: 2, importLoaders: 2,
localIdentName: "[name]-[local]-[contenthash]",
sourceMap: !disableSourcemaps, sourceMap: !disableSourcemaps,
}, },
}, },
@@ -471,9 +467,10 @@ export default function createWebpackConfig(
{ {
loader: require.resolve("css-loader"), loader: require.resolve("css-loader"),
options: { options: {
modules: true, modules: {
localIdentName: "[name]-[local]-[hash:base64:5]",
},
importLoaders: 1, importLoaders: 1,
localIdentName: "[name]-[local]-[hash:base64:5]",
sourceMap: !disableSourcemaps, sourceMap: !disableSourcemaps,
}, },
}, },
@@ -525,11 +522,6 @@ export default function createWebpackConfig(
useTypescriptIncrementalApi: false, useTypescriptIncrementalApi: false,
checkSyntacticErrors: true, checkSyntacticErrors: true,
tsconfig: paths.appTsconfig, tsconfig: paths.appTsconfig,
watch: paths.appSrc,
// TODO: (cvle) ForkTsCheckerWebpackPlugin are currently not working, so we resort to default reporting.
silent: false,
// The formatter is normally invoked directly in WebpackDevServerUtils during development
formatter: typescriptFormatter,
}) })
), ),
// Makes some environment variables available to the JS code, for example: // Makes some environment variables available to the JS code, for example:
+12 -12
View File
@@ -40,7 +40,7 @@ function getFiles(target, pathToLocale, context) {
const files = fs.readdirSync(pathToLocale); const files = fs.readdirSync(pathToLocale);
files.forEach(f => { files.forEach((f) => {
if (commonFiles.includes(f)) { if (commonFiles.includes(f)) {
common.push(f); common.push(f);
return; return;
@@ -62,12 +62,12 @@ function generateTarget(target, context) {
locales, locales,
bundled, bundled,
} = context; } = context;
const getLocalePath = locale => path.join(pathToLocales, locale); const getLocalePath = (locale) => path.join(pathToLocales, locale);
const getLocaleFiles = memoize(locale => const getLocaleFiles = memoize((locale) =>
getFiles(target, getLocalePath(locale), context) getFiles(target, getLocalePath(locale), context)
); );
const loadables = locales.filter(locale => !bundled.includes(locale)); const loadables = locales.filter((locale) => !bundled.includes(locale));
return ` return `
var ret = { var ret = {
@@ -81,22 +81,22 @@ function generateTarget(target, context) {
// Bundled locales are directly available in the main bundle. // Bundled locales are directly available in the main bundle.
${bundled ${bundled
.map( .map(
locale => ` (locale) => `
{ {
var suffixes = ${JSON.stringify(getLocaleFiles(locale).suffixes)}; var suffixes = ${JSON.stringify(getLocaleFiles(locale).suffixes)};
var contents = []; var contents = [];
${getLocaleFiles(locale) ${getLocaleFiles(locale)
.common.map( .common.map(
file => ` (file) => `
contents.push(require(${JSON.stringify( contents.push(require(${JSON.stringify(
path.join(getLocalePath(locale), file).replace(/\\/g, "/") path.join(getLocalePath(locale), file).replace(/\\/g, "/")
)})); )}).default);
` `
) )
.join("\n")} .join("\n")}
contents = contents.concat(suffixes.map(function(suffix) { return require("${path contents = contents.concat(suffixes.map(function(suffix) { return require("${path
.join(getLocalePath(locale), target) .join(getLocalePath(locale), target)
.replace(/\\/g, "/")}" + suffix); })); .replace(/\\/g, "/")}" + suffix).default; }));
ret.bundled[${JSON.stringify(locale)}] = contents.join("\\n"); ret.bundled[${JSON.stringify(locale)}] = contents.join("\\n");
} }
` `
@@ -106,13 +106,13 @@ function generateTarget(target, context) {
// Loadables are in a separate bundle, that can be easily loaded. // Loadables are in a separate bundle, that can be easily loaded.
${loadables ${loadables
.map( .map(
locale => ` (locale) => `
ret.loadables[${JSON.stringify(locale)}] = function() { ret.loadables[${JSON.stringify(locale)}] = function() {
var suffixes = ${JSON.stringify(getLocaleFiles(locale).suffixes)}; var suffixes = ${JSON.stringify(getLocaleFiles(locale).suffixes)};
var promises = []; var promises = [];
${getLocaleFiles(locale) ${getLocaleFiles(locale)
.common.map( .common.map(
file => ` (file) => `
promises.push( promises.push(
import( import(
/* webpackChunkName: ${JSON.stringify( /* webpackChunkName: ${JSON.stringify(
@@ -147,7 +147,7 @@ function generateTarget(target, context) {
`; `;
} }
module.exports = function(source) { module.exports = function (source) {
const options = Object.assign( const options = Object.assign(
{}, {},
DEFAULT_QUERY_VALUES, DEFAULT_QUERY_VALUES,
@@ -165,7 +165,7 @@ module.exports = function(source) {
let locales = fs.readdirSync(pathToLocales); let locales = fs.readdirSync(pathToLocales);
if (availableLocales) { if (availableLocales) {
availableLocales.forEach(locale => { availableLocales.forEach((locale) => {
if (!locales.includes(locale)) { if (!locales.includes(locale)) {
throw new Error(`locale ${fallbackLocale} not available`); throw new Error(`locale ${fallbackLocale} not available`);
} }
+2 -8
View File
@@ -20,7 +20,7 @@ const postcssAdvancedVariables = require("postcss-advanced-variables");
delete require.cache[paths.appThemeVariables]; delete require.cache[paths.appThemeVariables];
const variables = require(paths.appThemeVariables).default; const variables = require(paths.appThemeVariables).default;
const flatKebabVariables = mapKeys( const flatKebabVariables = mapKeys(
mapValues(flat(variables, { delimiter: "-" }), v => v.toString()), mapValues(flat(variables, { delimiter: "-" }), (v) => v.toString()),
(_, k) => kebabCase(k) (_, k) => kebabCase(k)
); );
@@ -32,7 +32,7 @@ const mediaQueryVariables = mapValues(
// with the smallest screen and gradually add styling for the // with the smallest screen and gradually add styling for the
// next bigger screen. This is realized using `min-width` without // next bigger screen. This is realized using `min-width` without
// ever using `max-width`. // ever using `max-width`.
v => `${Number.parseInt(v, 10) + 1}px` (v) => `${Number.parseInt(v, 10) + 1}px`
); );
module.exports = { module.exports = {
@@ -63,12 +63,6 @@ module.exports = {
postcssFlexbugsFixes, postcssFlexbugsFixes,
// Vendor prefixing. // Vendor prefixing.
autoprefixer({ autoprefixer({
browsers: [
">1%",
"last 4 versions",
"Firefox ESR",
"not ie < 9", // React doesn't support IE8 anyway
],
flexbox: "no-2009", flexbox: "no-2009",
}), }),
], ],
@@ -17,7 +17,7 @@ interface Props {
onGotoComment?: React.EventHandler<React.MouseEvent>; onGotoComment?: React.EventHandler<React.MouseEvent>;
} }
const ApprovedComment: FunctionComponent<Props> = props => ( const ApprovedComment: FunctionComponent<Props> = (props) => (
<DecisionItem icon={<ApprovedIcon />}> <DecisionItem icon={<ApprovedIcon />}>
<Localized <Localized
id="decisionHistory-approvedCommentBy" id="decisionHistory-approvedCommentBy"
@@ -19,13 +19,13 @@ interface Props {
onClosePopover: () => void; onClosePopover: () => void;
} }
const DecisionHistory: FunctionComponent<Props> = props => ( const DecisionHistory: FunctionComponent<Props> = (props) => (
<div data-testid="decisionHistory-container"> <div data-testid="decisionHistory-container">
<Title /> <Title />
<Main> <Main>
<DecisionList> <DecisionList>
{props.actions.length === 0 && <Empty />} {props.actions.length === 0 && <Empty />}
{props.actions.map(action => ( {props.actions.map((action) => (
<DecisionHistoryItemContainer <DecisionHistoryItemContainer
key={action.id} key={action.id}
action={action} action={action}
@@ -23,7 +23,7 @@ export class DecisionHistoryContainer extends React.Component<
public render() { public render() {
const actions = this.props.viewer.commentModerationActionHistory.edges.map( const actions = this.props.viewer.commentModerationActionHistory.edges.map(
edge => edge.node (edge) => edge.node
); );
return ( return (
<DecisionHistory <DecisionHistory
@@ -43,7 +43,7 @@ export class DecisionHistoryContainer extends React.Component<
this.setState({ disableLoadMore: true }); this.setState({ disableLoadMore: true });
this.props.relay.loadMore( this.props.relay.loadMore(
10, // Fetch the next 10 feed items 10, // Fetch the next 10 feed items
error => { (error) => {
this.setState({ disableLoadMore: false }); this.setState({ disableLoadMore: false });
if (error) { if (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
@@ -1,6 +1,7 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { graphql } from "react-relay";
import { graphql, QueryRenderer } from "coral-framework/lib/relay"; import { QueryRenderer } from "coral-framework/lib/relay";
import { DecisionHistoryQuery as QueryTypes } from "coral-admin/__generated__/DecisionHistoryQuery.graphql"; import { DecisionHistoryQuery as QueryTypes } from "coral-admin/__generated__/DecisionHistoryQuery.graphql";
@@ -9,7 +9,7 @@ interface Props {
children: React.ReactNode; children: React.ReactNode;
} }
const DecisionItem: FunctionComponent<Props> = props => ( const DecisionItem: FunctionComponent<Props> = (props) => (
<li className={styles.root}> <li className={styles.root}>
<Flex> <Flex>
<div className={styles.leftCol}>{props.icon}</div> <div className={styles.leftCol}>{props.icon}</div>
@@ -2,7 +2,7 @@ import React, { FunctionComponent } from "react";
import styles from "./DecisionList.css"; import styles from "./DecisionList.css";
const DecisionList: FunctionComponent = props => ( const DecisionList: FunctionComponent = (props) => (
<ul className={styles.root}>{props.children}</ul> <ul className={styles.root}>{props.children}</ul>
); );
@@ -8,7 +8,7 @@ interface Props {
children: React.ReactNode; children: React.ReactNode;
} }
const Footer: FunctionComponent<Props> = props => ( const Footer: FunctionComponent<Props> = (props) => (
<Flex className={styles.root} alignItems="baseline"> <Flex className={styles.root} alignItems="baseline">
{props.children} {props.children}
</Flex> </Flex>
@@ -11,7 +11,7 @@ interface Props {
onClick?: React.EventHandler<React.MouseEvent>; onClick?: React.EventHandler<React.MouseEvent>;
} }
const GoToCommentLink: FunctionComponent<Props> = props => { const GoToCommentLink: FunctionComponent<Props> = (props) => {
return ( return (
<Link <Link
as={TextLink} as={TextLink}
@@ -6,7 +6,7 @@ interface Props {
children: React.ReactNode; children: React.ReactNode;
} }
const Info: FunctionComponent<Props> = props => ( const Info: FunctionComponent<Props> = (props) => (
<span className={styles.root}>{props.children}</span> <span className={styles.root}>{props.children}</span>
); );
@@ -2,7 +2,7 @@ import React, { FunctionComponent } from "react";
import styles from "./Main.css"; import styles from "./Main.css";
const Main: FunctionComponent = props => ( const Main: FunctionComponent = (props) => (
<div className={styles.root}>{props.children}</div> <div className={styles.root}>{props.children}</div>
); );
@@ -17,7 +17,7 @@ interface Props {
onGotoComment?: React.EventHandler<React.MouseEvent>; onGotoComment?: React.EventHandler<React.MouseEvent>;
} }
const RejectedComment: FunctionComponent<Props> = props => ( const RejectedComment: FunctionComponent<Props> = (props) => (
<DecisionItem icon={<RejectedIcon />}> <DecisionItem icon={<RejectedIcon />}>
<Localized <Localized
id="decisionHistory-rejectedCommentBy" id="decisionHistory-rejectedCommentBy"
@@ -10,7 +10,7 @@ interface Props {
onClick?: () => void; onClick?: () => void;
} }
const ShowMoreButton: FunctionComponent<Props> = props => ( const ShowMoreButton: FunctionComponent<Props> = (props) => (
<Localized id="decisionHistory-showMoreButton"> <Localized id="decisionHistory-showMoreButton">
<BaseButton <BaseButton
className={styles.root} className={styles.root}
@@ -8,7 +8,7 @@ interface Props {
children: string; children: string;
} }
const DecisionHistory: FunctionComponent<Props> = props => ( const DecisionHistory: FunctionComponent<Props> = (props) => (
<Timestamp className={styles.root}>{props.children}</Timestamp> <Timestamp className={styles.root}>{props.children}</Timestamp>
); );
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = ` exports[`renders correctly 1`] = `
<ForwardRef(render) <Link
as={[Function]} as={[Function]}
className="GoToCommentLink-root" className="GoToCommentLink-root"
onClick={[Function]} onClick={[Function]}
@@ -18,5 +18,5 @@ exports[`renders correctly 1`] = `
<ForwardRef(forwardRef)> <ForwardRef(forwardRef)>
chevron_right chevron_right
</ForwardRef(forwardRef)> </ForwardRef(forwardRef)>
</ForwardRef(render)> </Link>
`; `;
@@ -6,9 +6,9 @@ interface State {
} }
type Action = type Action =
| { | ({
type: "SET_MESSAGE"; type: "SET_MESSAGE";
} & State } & State)
| { | {
type: "CLEAR_MESSAGE"; type: "CLEAR_MESSAGE";
}; };
+1 -1
View File
@@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import { graphql } from "react-relay";
import { graphql } from "coral-framework/lib/relay";
import { withRouteConfig } from "coral-framework/lib/router"; import { withRouteConfig } from "coral-framework/lib/router";
import { MainRouteQueryResponse } from "coral-admin/__generated__/MainRouteQuery.graphql"; import { MainRouteQueryResponse } from "coral-admin/__generated__/MainRouteQuery.graphql";
@@ -9,7 +9,7 @@ interface Props {
showConfigure: boolean; showConfigure: boolean;
} }
const Navigation: FunctionComponent<Props> = props => ( const Navigation: FunctionComponent<Props> = (props) => (
<AppBarNavigation> <AppBarNavigation>
<Localized id="navigation-moderate"> <Localized id="navigation-moderate">
<NavigationLink to="/admin/moderate">Moderate</NavigationLink> <NavigationLink to="/admin/moderate">Moderate</NavigationLink>
@@ -1,7 +1,8 @@
import React from "react"; import React from "react";
import { graphql } from "react-relay";
import { Ability, can } from "coral-admin/permissions"; import { Ability, can } from "coral-admin/permissions";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { import {
SignOutMutation, SignOutMutation,
withSignOutMutation, withSignOutMutation,
@@ -8,7 +8,7 @@ interface Props {
to: string | LocationDescriptor; to: string | LocationDescriptor;
} }
const NavigationLink: FunctionComponent<Props> = props => ( const NavigationLink: FunctionComponent<Props> = (props) => (
<Link to={props.to} as={AppBarNavigationItem as any} activePropName="active"> <Link to={props.to} as={AppBarNavigationItem as any} activePropName="active">
{props.children} {props.children}
</Link> </Link>
@@ -1,11 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = ` exports[`renders correctly 1`] = `
<ForwardRef(render) <Link
activePropName="active" activePropName="active"
as={[Function]} as={[Function]}
to="/moderate" to="/moderate"
> >
link link
</ForwardRef(render)> </Link>
`; `;
@@ -18,7 +18,7 @@ interface Props {
onSignOut: React.EventHandler<React.MouseEvent>; onSignOut: React.EventHandler<React.MouseEvent>;
} }
const UserMenu: FunctionComponent<Props> = props => ( const UserMenu: FunctionComponent<Props> = (props) => (
<Localized id="userMenu-popover" attrs={{ description: true }}> <Localized id="userMenu-popover" attrs={{ description: true }}>
<Popover <Popover
id="userMenu" id="userMenu"
@@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { graphql } from "react-relay";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { import {
SignOutMutation, SignOutMutation,
withSignOutMutation, withSignOutMutation,
@@ -2,7 +2,7 @@ import React, { FunctionComponent } from "react";
import styles from "./ButtonPadding.css"; import styles from "./ButtonPadding.css";
const ButtonPadding: FunctionComponent = props => ( const ButtonPadding: FunctionComponent = (props) => (
<div className={styles.root}>{props.children}</div> <div className={styles.root}>{props.children}</div>
); );
@@ -5,7 +5,7 @@ $comment-link: var(--v2-palette-primary-main);
$comment-link-active: var(--v2-palette-primary-darkest); $comment-link-active: var(--v2-palette-primary-darkest);
.root { .root {
composes: bodyCommentV2 from "coral-ui/shared/typography.css"; composes: bodyCommentV2 from "~coral-ui/shared/typography.css";
font-family: var(--v2-font-family-primary); font-family: var(--v2-font-family-primary);
font-size: var(--v2-font-size-3); font-size: var(--v2-font-size-3);
line-height: var(--v2-line-height-body-comment); line-height: var(--v2-line-height-body-comment);
@@ -8,7 +8,7 @@ export interface UsernameProps {
children: string; children: string;
} }
const Username: FunctionComponent<UsernameProps> = props => { const Username: FunctionComponent<UsernameProps> = (props) => {
return ( return (
<span className={cn(props.className, styles.root)}>{props.children}</span> <span className={cn(props.className, styles.root)}>{props.children}</span>
); );
@@ -1,8 +1,9 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import cn from "classnames"; import cn from "classnames";
import React, { FunctionComponent, useCallback, useState } from "react"; import React, { FunctionComponent, useCallback, useState } from "react";
import { graphql } from "react-relay";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { import {
Button, Button,
Flex, Flex,
@@ -10,13 +11,12 @@ import {
Timestamp, Timestamp,
} from "coral-ui/components/v2"; } from "coral-ui/components/v2";
import ConversationModalRepliesQuery from "./ConversationModalRepliesQuery";
import { ConversationModalCommentContainer_comment } from "coral-admin/__generated__/ConversationModalCommentContainer_comment.graphql"; import { ConversationModalCommentContainer_comment } from "coral-admin/__generated__/ConversationModalCommentContainer_comment.graphql";
import { ConversationModalCommentContainer_settings } from "coral-admin/__generated__/ConversationModalCommentContainer_settings.graphql"; import { ConversationModalCommentContainer_settings } from "coral-admin/__generated__/ConversationModalCommentContainer_settings.graphql";
import { CommentContent, InReplyTo, UsernameButton } from "../Comment"; import { CommentContent, InReplyTo, UsernameButton } from "../Comment";
import { Circle, Line } from "../Timeline"; import { Circle, Line } from "../Timeline";
import ConversationModalRepliesQuery from "./ConversationModalRepliesQuery";
import styles from "./ConversationModalCommentContainer.css"; import styles from "./ConversationModalCommentContainer.css";
@@ -37,7 +37,7 @@ const ConversationModalContainer: FunctionComponent<Props> = ({
onUsernameClicked, onUsernameClicked,
}) => { }) => {
const [loadMore] = useLoadMore(relay, 5); const [loadMore] = useLoadMore(relay, 5);
const parents = comment.parents.edges.map(edge => edge.node); const parents = comment.parents.edges.map((edge) => edge.node);
return ( return (
<HorizontalGutter className={styles.root}> <HorizontalGutter className={styles.root}>
{comment.parentCount > parents.length && ( {comment.parentCount > parents.length && (
@@ -60,7 +60,7 @@ const ConversationModalContainer: FunctionComponent<Props> = ({
</Flex> </Flex>
</div> </div>
)} )}
{parents.map(parent => ( {parents.map((parent) => (
<ConversationModalComment <ConversationModalComment
key={parent.id} key={parent.id}
isParent={true} isParent={true}
@@ -1,9 +1,10 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import { useRouter } from "found"; import { useRouter } from "found";
import React, { FunctionComponent, RefObject, useCallback } from "react"; import React, { FunctionComponent, RefObject, useCallback } from "react";
import { graphql } from "react-relay";
import { getModerationLink } from "coral-framework/helpers"; import { getModerationLink } from "coral-framework/helpers";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { Button, HorizontalGutter, ModalHeader } from "coral-ui/components/v2"; import { Button, HorizontalGutter, ModalHeader } from "coral-ui/components/v2";
import { ConversationModalHeaderContainer_comment } from "coral-admin/__generated__/ConversationModalHeaderContainer_comment.graphql"; import { ConversationModalHeaderContainer_comment } from "coral-admin/__generated__/ConversationModalHeaderContainer_comment.graphql";
@@ -1,11 +1,8 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { import { QueryRenderData, QueryRenderer } from "coral-framework/lib/relay";
graphql,
QueryRenderData,
QueryRenderer,
} from "coral-framework/lib/relay";
import { CallOut, Card, Spinner } from "coral-ui/components/v2"; import { CallOut, Card, Spinner } from "coral-ui/components/v2";
import { ConversationModalQuery as QueryTypes } from "coral-admin/__generated__/ConversationModalQuery.graphql"; import { ConversationModalQuery as QueryTypes } from "coral-admin/__generated__/ConversationModalQuery.graphql";
@@ -1,17 +1,22 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent, useCallback, useState } from "react"; import React, {
FunctionComponent,
useCallback,
useMemo,
useState,
} from "react";
import { graphql, RelayPaginationProp } from "react-relay"; import { graphql, RelayPaginationProp } from "react-relay";
import { import {
useLoadMore, useLoadMore,
withPaginationContainer, withPaginationContainer,
} from "coral-framework/lib/relay"; } from "coral-framework/lib/relay";
import { Omit } from "coral-framework/types";
import { Button, HorizontalGutter } from "coral-ui/components/v2"; import { Button, HorizontalGutter } from "coral-ui/components/v2";
import { ConversationModalRepliesContainer_comment } from "coral-admin/__generated__/ConversationModalRepliesContainer_comment.graphql"; import { ConversationModalRepliesContainer_comment } from "coral-admin/__generated__/ConversationModalRepliesContainer_comment.graphql";
import { ConversationModalRepliesContainer_settings } from "coral-admin/__generated__/ConversationModalRepliesContainer_settings.graphql"; import { ConversationModalRepliesContainer_settings } from "coral-admin/__generated__/ConversationModalRepliesContainer_settings.graphql";
import { ConversationModalRepliesContainerPaginationQueryVariables } from "coral-admin/__generated__/ConversationModalRepliesContainerPaginationQuery.graphql"; import { ConversationModalRepliesContainerPaginationQueryVariables } from "coral-admin/__generated__/ConversationModalRepliesContainerPaginationQuery.graphql";
import ConversationModalCommentContainer from "./ConversationModalCommentContainer"; import ConversationModalCommentContainer from "./ConversationModalCommentContainer";
import styles from "./ConversationModalRepliesContainer.css"; import styles from "./ConversationModalRepliesContainer.css";
@@ -31,7 +36,10 @@ const ConversationModalRepliesContainer: FunctionComponent<Props> = ({
onUsernameClicked, onUsernameClicked,
}) => { }) => {
const [loadMore] = useLoadMore(relay, 5); const [loadMore] = useLoadMore(relay, 5);
const replies = comment.replies.edges.map(edge => edge.node); const replies = useMemo(
() => comment.replies.edges.map((edge) => edge.node, comment.replies),
[comment.replies]
);
const [showReplies, setShowReplies] = useState(false); const [showReplies, setShowReplies] = useState(false);
const onShowReplies = useCallback(() => { const onShowReplies = useCallback(() => {
setShowReplies(true); setShowReplies(true);
@@ -39,7 +47,7 @@ const ConversationModalRepliesContainer: FunctionComponent<Props> = ({
return ( return (
<HorizontalGutter> <HorizontalGutter>
{showReplies && {showReplies &&
replies.map(reply => ( replies.map((reply) => (
<div key={reply.id} className={styles.comment}> <div key={reply.id} className={styles.comment}>
<ConversationModalCommentContainer <ConversationModalCommentContainer
key={reply.id} key={reply.id}
@@ -1,14 +1,12 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent, useMemo } from "react";
import { graphql } from "react-relay";
import { import { QueryRenderData, QueryRenderer } from "coral-framework/lib/relay";
graphql,
QueryRenderData,
QueryRenderer,
} from "coral-framework/lib/relay";
import { CallOut, Spinner } from "coral-ui/components/v2"; import { CallOut, Spinner } from "coral-ui/components/v2";
import { ConversationModalRepliesQuery as QueryTypes } from "coral-admin/__generated__/ConversationModalRepliesQuery.graphql"; import { ConversationModalRepliesQuery as QueryTypes } from "coral-admin/__generated__/ConversationModalRepliesQuery.graphql";
import ConversationModalCommentContainer from "./ConversationModalCommentContainer"; import ConversationModalCommentContainer from "./ConversationModalCommentContainer";
interface Props { interface Props {
@@ -62,10 +60,13 @@ const ConversationModalRepliesQuery: FunctionComponent<Props> = ({
); );
} }
const replies = props.comment.replies.edges.map(edge => edge.node); const replies = useMemo(
() => props.comment!.replies.edges.map((edge) => edge.node),
[props.comment.replies]
);
return ( return (
<div> <div>
{replies.map(reply => ( {replies.map((reply) => (
<div key={reply.id}> <div key={reply.id}>
<ConversationModalCommentContainer <ConversationModalCommentContainer
key={reply.id} key={reply.id}
@@ -7,7 +7,7 @@ import { BaseButton, Icon } from "coral-ui/components/v2";
import styles from "./ApproveButton.css"; import styles from "./ApproveButton.css";
interface Props extends PropTypesOf<typeof BaseButton> { interface Props extends Omit<PropTypesOf<typeof BaseButton>, "ref"> {
invert?: boolean; invert?: boolean;
} }
@@ -34,12 +34,12 @@ const BanCommentUserMutation = createMutation(
clientMutationId: clientMutationId.toString(), clientMutationId: clientMutationId.toString(),
}, },
}, },
updater: store => { updater: (store) => {
const user = store.get(input.userID); const user = store.get(input.userID);
if (user) { if (user) {
const comments = user.getLinkedRecords("comments"); const comments = user.getLinkedRecords("comments");
if (comments) { if (comments) {
comments.forEach(comment => { comments.forEach((comment) => {
if (comment) { if (comment) {
comment.setLinkedRecord(user, "author"); comment.setLinkedRecord(user, "author");
} }
@@ -1,7 +1,8 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { Tag } from "coral-ui/components/v2"; import { Tag } from "coral-ui/components/v2";
import { CommentAuthorContainer_comment as CommentData } from "coral-admin/__generated__/CommentAuthorContainer_comment.graphql"; import { CommentAuthorContainer_comment as CommentData } from "coral-admin/__generated__/CommentAuthorContainer_comment.graphql";
@@ -1,6 +1,7 @@
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { HorizontalGutter, Timestamp } from "coral-ui/components/v2"; import { HorizontalGutter, Timestamp } from "coral-ui/components/v2";
import { CommentRevisionContainer_comment as CommentData } from "coral-admin/__generated__/CommentRevisionContainer_comment.graphql"; import { CommentRevisionContainer_comment as CommentData } from "coral-admin/__generated__/CommentRevisionContainer_comment.graphql";
@@ -22,12 +23,12 @@ const CommentRevisionContainer: FunctionComponent<Props> = ({
{comment.revisionHistory {comment.revisionHistory
.concat() .concat()
.reverse() .reverse()
.filter(c => .filter((c) =>
comment && comment.revision && comment.revision.id comment && comment.revision && comment.revision.id
? comment.revision.id !== c.id ? comment.revision.id !== c.id
: true : true
) )
.map(c => ( .map((c) => (
<div key={c.id}> <div key={c.id}>
<Timestamp>{c.createdAt}</Timestamp> <Timestamp>{c.createdAt}</Timestamp>
<CommentContent phrases={settings}> <CommentContent phrases={settings}>
@@ -7,7 +7,7 @@ import { BaseButton } from "coral-ui/components/v2";
import styles from "./FeatureButton.css"; import styles from "./FeatureButton.css";
interface Props extends PropTypesOf<typeof BaseButton> { interface Props extends Omit<PropTypesOf<typeof BaseButton>, "ref"> {
featured: boolean; featured: boolean;
enabled?: boolean; enabled?: boolean;
} }
@@ -57,7 +57,7 @@ const FeatureCommentMutation = createMutation(
}, },
storyID: input.storyID, storyID: input.storyID,
}, },
optimisticUpdater: store => { optimisticUpdater: (store) => {
const comment = store.get(input.commentID)!; const comment = store.get(input.commentID)!;
const tags = comment.getLinkedRecords("tags"); const tags = comment.getLinkedRecords("tags");
if (tags) { if (tags) {
@@ -67,14 +67,14 @@ const FeatureCommentMutation = createMutation(
comment.setValue(GQLCOMMENT_STATUS.APPROVED, "status"); comment.setValue(GQLCOMMENT_STATUS.APPROVED, "status");
} }
}, },
updater: store => { updater: (store) => {
const connections = [ const connections = [
getQueueConnection(store, "PENDING", input.storyID), getQueueConnection(store, "PENDING", input.storyID),
getQueueConnection(store, "REPORTED", input.storyID), getQueueConnection(store, "REPORTED", input.storyID),
getQueueConnection(store, "UNMODERATED", input.storyID), getQueueConnection(store, "UNMODERATED", input.storyID),
getQueueConnection(store, "REJECTED", input.storyID), getQueueConnection(store, "REJECTED", input.storyID),
].filter(c => c); ].filter((c) => c);
connections.forEach(con => connections.forEach((con) =>
ConnectionHandler.deleteNode(con!, input.commentID) ConnectionHandler.deleteNode(con!, input.commentID)
); );
}, },
@@ -1,9 +1,10 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import CopyToClipboard from "react-copy-to-clipboard"; import CopyToClipboard from "react-copy-to-clipboard";
import { graphql } from "react-relay";
import { getURLWithCommentID } from "coral-framework/helpers"; import { getURLWithCommentID } from "coral-framework/helpers";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { getLocationOrigin } from "coral-framework/utils"; import { getLocationOrigin } from "coral-framework/utils";
import { Button, Icon } from "coral-ui/components/v2"; import { Button, Icon } from "coral-ui/components/v2";
@@ -1,5 +1,5 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React from "react"; import React, { useMemo } from "react";
import { graphql } from "react-relay"; import { graphql } from "react-relay";
import { withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
@@ -26,17 +26,17 @@ function hasDetails(c: MarkersContainer_comment) {
} }
let keyCounter = 0; let keyCounter = 0;
const markers: Array< const markers: Array<(
(c: MarkersContainer_comment) => React.ReactElement<any> | null c: MarkersContainer_comment
> = [ ) => React.ReactElement<any> | null> = [
c => (c) =>
(c.status === "PREMOD" && ( (c.status === "PREMOD" && (
<Localized id="moderate-marker-preMod" key={keyCounter++}> <Localized id="moderate-marker-preMod" key={keyCounter++}>
<Marker color="pending">Pre-Mod</Marker> <Marker color="pending">Pre-Mod</Marker>
</Localized> </Localized>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_LINKS && ( c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_LINKS && (
<Localized id="moderate-marker-link" key={keyCounter++}> <Localized id="moderate-marker-link" key={keyCounter++}>
@@ -44,7 +44,7 @@ const markers: Array<
</Localized> </Localized>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_BANNED_WORD && ( c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_BANNED_WORD && (
<Localized id="moderate-marker-bannedWord" key={keyCounter++}> <Localized id="moderate-marker-bannedWord" key={keyCounter++}>
@@ -52,7 +52,7 @@ const markers: Array<
</Localized> </Localized>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_SUSPECT_WORD && ( c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_SUSPECT_WORD && (
<Localized id="moderate-marker-suspectWord" key={keyCounter++}> <Localized id="moderate-marker-suspectWord" key={keyCounter++}>
@@ -60,7 +60,7 @@ const markers: Array<
</Localized> </Localized>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_SPAM && ( c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_SPAM && (
<Localized id="moderate-marker-spamDetected" key={keyCounter++}> <Localized id="moderate-marker-spamDetected" key={keyCounter++}>
@@ -68,7 +68,7 @@ const markers: Array<
</Localized> </Localized>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_TOXIC && ( c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_TOXIC && (
<Localized id="moderate-marker-toxic" key={keyCounter++}> <Localized id="moderate-marker-toxic" key={keyCounter++}>
@@ -76,7 +76,7 @@ const markers: Array<
</Localized> </Localized>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_REPEAT_POST && ( c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_REPEAT_POST && (
<Localized id="moderate-marker-repeatPost" key={keyCounter++}> <Localized id="moderate-marker-repeatPost" key={keyCounter++}>
@@ -84,7 +84,7 @@ const markers: Array<
</Localized> </Localized>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_RECENT_HISTORY && ( c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_RECENT_HISTORY && (
<Localized id="moderate-marker-recentHistory" key={keyCounter++}> <Localized id="moderate-marker-recentHistory" key={keyCounter++}>
@@ -92,7 +92,7 @@ const markers: Array<
</Localized> </Localized>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE && ( c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_OFFENSIVE && (
<Marker key={keyCounter++} color="reported"> <Marker key={keyCounter++} color="reported">
@@ -105,7 +105,7 @@ const markers: Array<
</Marker> </Marker>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM && ( c.revision.actionCounts.flag.reasons.COMMENT_REPORTED_SPAM && (
<Marker key={keyCounter++} color="reported"> <Marker key={keyCounter++} color="reported">
@@ -118,7 +118,7 @@ const markers: Array<
</Marker> </Marker>
)) || )) ||
null, null,
c => (c) =>
(c.revision && (c.revision &&
c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_NEW_COMMENTER && ( c.revision.actionCounts.flag.reasons.COMMENT_DETECTED_NEW_COMMENTER && (
<Localized id="moderate-marker-newCommenter" key={keyCounter++}> <Localized id="moderate-marker-newCommenter" key={keyCounter++}>
@@ -128,33 +128,38 @@ const markers: Array<
null, null,
]; ];
export class MarkersContainer extends React.Component<MarkersContainerProps> { export const MarkersContainer: React.FunctionComponent<MarkersContainerProps> = (
public render() { props
const elements = markers.map(cb => cb(this.props.comment)).filter(m => m); ) => {
const doesHaveDetails = hasDetails(this.props.comment); const elements = useMemo(
if (elements.length === 0 && !doesHaveDetails) { () => markers.map((cb) => cb(props.comment)).filter((m) => m),
return null; [markers, props.comment]
} );
const doesHaveDetails = useMemo(() => hasDetails(props.comment), [
return ( props.comment,
<Markers ]);
details={ if (elements.length === 0 && !doesHaveDetails) {
doesHaveDetails || this.props.comment.editing.edited ? ( return null;
<ModerateCardDetailsContainer
hasDetails={!!doesHaveDetails}
hasRevisions={this.props.comment.editing.edited}
onUsernameClick={this.props.onUsernameClick}
comment={this.props.comment}
settings={this.props.settings}
/>
) : null
}
>
{elements}
</Markers>
);
} }
}
return (
<Markers
details={
doesHaveDetails || props.comment.editing.edited ? (
<ModerateCardDetailsContainer
hasDetails={!!doesHaveDetails}
hasRevisions={props.comment.editing.edited}
onUsernameClick={props.onUsernameClick}
comment={props.comment}
settings={props.settings}
/>
) : null
}
>
{elements}
</Markers>
);
};
const enhanced = withFragmentContainer<MarkersContainerProps>({ const enhanced = withFragmentContainer<MarkersContainerProps>({
comment: graphql` comment: graphql`
@@ -64,7 +64,7 @@ function getStatus(comment: ModerateCardContainer_comment) {
} }
function isFeatured(comment: ModerateCardContainer_comment) { function isFeatured(comment: ModerateCardContainer_comment) {
return comment.tags.some(t => t.code === GQLTAG.FEATURED); return comment.tags.some((t) => t.code === GQLTAG.FEATURED);
} }
const ModerateCardContainer: FunctionComponent<Props> = ({ const ModerateCardContainer: FunctionComponent<Props> = ({
@@ -1,9 +1,7 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent, useState } from "react"; import React, { FunctionComponent, useCallback, useState } from "react";
import { graphql } from "react-relay"; import { graphql } from "react-relay";
import { ModerateCardDetailsContainer_comment as CommentData } from "coral-admin/__generated__/ModerateCardDetailsContainer_comment.graphql";
import { ModerateCardDetailsContainer_settings as SettingsData } from "coral-admin/__generated__/ModerateCardDetailsContainer_settings.graphql";
import { withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { import {
Flex, Flex,
@@ -13,6 +11,9 @@ import {
TabBar, TabBar,
} from "coral-ui/components/v2"; } from "coral-ui/components/v2";
import { ModerateCardDetailsContainer_comment as CommentData } from "coral-admin/__generated__/ModerateCardDetailsContainer_comment.graphql";
import { ModerateCardDetailsContainer_settings as SettingsData } from "coral-admin/__generated__/ModerateCardDetailsContainer_settings.graphql";
import CommentRevisionContainer from "./CommentRevisionContainer"; import CommentRevisionContainer from "./CommentRevisionContainer";
import FlagDetailsContainer from "./FlagDetailsContainer"; import FlagDetailsContainer from "./FlagDetailsContainer";
import LinkDetailsContainer from "./LinkDetailsContainer"; import LinkDetailsContainer from "./LinkDetailsContainer";
@@ -40,13 +41,13 @@ const ModerateCardDetailsContainer: FunctionComponent<Props> = ({
hasDetails ? "DETAILS" : "HISTORY" hasDetails ? "DETAILS" : "HISTORY"
); );
const onTabClick = useCallback((id) => setActiveTab(id as DetailsTabs), [
setActiveTab,
]);
return ( return (
<HorizontalGutter> <HorizontalGutter>
<TabBar <TabBar variant="default" activeTab={activeTab} onTabClick={onTabClick}>
variant="default"
activeTab={activeTab}
onTabClick={id => setActiveTab(id as DetailsTabs)}
>
{hasDetails && ( {hasDetails && (
<Tab tabID="DETAILS" classes={styles}> <Tab tabID="DETAILS" classes={styles}>
<Flex alignItems="center" itemGutter> <Flex alignItems="center" itemGutter>
@@ -7,7 +7,7 @@ import { BaseButton, Icon } from "coral-ui/components/v2";
import styles from "./RejectButton.css"; import styles from "./RejectButton.css";
interface Props extends PropTypesOf<typeof BaseButton> { interface Props extends Omit<PropTypesOf<typeof BaseButton>, "ref"> {
invert?: boolean; invert?: boolean;
} }
@@ -31,11 +31,11 @@ const UnfeatureCommentMutation = createMutation(
} }
} }
`, `,
optimisticUpdater: store => { optimisticUpdater: (store) => {
const comment = store.get(input.commentID)!; const comment = store.get(input.commentID)!;
const tags = comment.getLinkedRecords("tags")!; const tags = comment.getLinkedRecords("tags")!;
comment.setLinkedRecords( comment.setLinkedRecords(
tags.filter(t => t!.getValue("code") === GQLTAG.FEATURED), tags.filter((t) => t.getValue("code") === GQLTAG.FEATURED),
"tags" "tags"
); );
}, },
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`viewer's username shows on moderation cards moderated by viewer 1`] = ` exports[`viewer's username shows on moderation cards moderated by viewer 1`] = `
<ForwardRef(Relay(ModeratedByContainer)) <Relay(ModeratedByContainer)
comment={ comment={
Object { Object {
"id": "comment-id", "id": "comment-id",
@@ -3,7 +3,7 @@ import React, { FunctionComponent } from "react";
import styles from "./NotAvailable.css"; import styles from "./NotAvailable.css";
const NotAvailable: FunctionComponent = props => ( const NotAvailable: FunctionComponent = (props) => (
<Localized id="general-notAvailable"> <Localized id="general-notAvailable">
<span className={styles.root}>Not available</span> <span className={styles.root}>Not available</span>
</Localized> </Localized>
@@ -10,7 +10,7 @@ export interface CircleProps {
color?: "light" | "regular"; color?: "light" | "regular";
} }
const Circle: FunctionComponent<CircleProps> = props => { const Circle: FunctionComponent<CircleProps> = (props) => {
return ( return (
<div <div
className={cn(styles.root, props.className, { className={cn(styles.root, props.className, {
@@ -8,7 +8,7 @@ interface LineProps {
dotted?: boolean; dotted?: boolean;
} }
const Line: FunctionComponent<LineProps> = props => { const Line: FunctionComponent<LineProps> = (props) => {
return ( return (
<div <div
className={cn(styles.root, props.className, { className={cn(styles.root, props.className, {
@@ -19,7 +19,7 @@ function createElement(
} }
} }
const TranslatedRole: React.FunctionComponent<Props> = props => { const TranslatedRole: React.FunctionComponent<Props> = (props) => {
switch (props.children) { switch (props.children) {
case GQLUSER_ROLE.COMMENTER: case GQLUSER_ROLE.COMMENTER:
return ( return (
@@ -19,7 +19,7 @@ function createElement(
} }
} }
const TranslatedRole: React.FunctionComponent<Props> = props => { const TranslatedRole: React.FunctionComponent<Props> = (props) => {
switch (props.children) { switch (props.children) {
case GQLSTORY_STATUS.OPEN: case GQLSTORY_STATUS.OPEN:
return ( return (
@@ -25,7 +25,7 @@ const CreateModeratorNoteMutation = createMutation(
) => { ) => {
const viewer = getViewer(environment)!; const viewer = getViewer(environment)!;
const notes = const notes =
lookup<GQLUser>(environment, input.userID)!.moderatorNotes.map(note => { lookup<GQLUser>(environment, input.userID)!.moderatorNotes.map((note) => {
const createdBy = pick(note.createdBy, ["username", "id"]); const createdBy = pick(note.createdBy, ["username", "id"]);
return { return {
...pick(note, ["id", "body", "createdAt"]), ...pick(note, ["id", "body", "createdAt"]),
@@ -40,6 +40,7 @@ const CreateModeratorNoteMutation = createMutation(
) { ) {
createModeratorNote(input: $input) { createModeratorNote(input: $input) {
user { user {
id
moderatorNotes { moderatorNotes {
id id
body body
@@ -23,7 +23,7 @@ const DeleteModeratorNoteMutation = createMutation(
{ uuidGenerator }: CoralContext { uuidGenerator }: CoralContext
) => { ) => {
const notes = const notes =
lookup<GQLUser>(environment, input.userID)!.moderatorNotes.map(note => { lookup<GQLUser>(environment, input.userID)!.moderatorNotes.map((note) => {
const createdBy = pick(note.createdBy, ["username", "id"]); const createdBy = pick(note.createdBy, ["username", "id"]);
return { return {
...pick(note, ["id", "body", "createdAt"]), ...pick(note, ["id", "body", "createdAt"]),
@@ -37,6 +37,7 @@ const DeleteModeratorNoteMutation = createMutation(
) { ) {
deleteModeratorNote(input: $input) { deleteModeratorNote(input: $input) {
user { user {
id
moderatorNotes { moderatorNotes {
id id
body body
@@ -61,7 +62,7 @@ const DeleteModeratorNoteMutation = createMutation(
deleteModeratorNote: { deleteModeratorNote: {
user: { user: {
id: input.userID, id: input.userID,
moderatorNotes: notes.filter(note => note.id !== input.id), moderatorNotes: notes.filter((note) => note.id !== input.id),
}, },
clientMutationId: (clientMutationId++).toString(), clientMutationId: (clientMutationId++).toString(),
}, },
@@ -1,6 +1,7 @@
import React, { FunctionComponent, useMemo } from "react"; import React, { FunctionComponent, useMemo } from "react";
import { graphql } from "react-relay";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { GQLCOMMENT_STATUS } from "coral-framework/schema"; import { GQLCOMMENT_STATUS } from "coral-framework/schema";
import { RecentHistoryContainer_settings } from "coral-admin/__generated__/RecentHistoryContainer_settings.graphql"; import { RecentHistoryContainer_settings } from "coral-admin/__generated__/RecentHistoryContainer_settings.graphql";
@@ -17,7 +17,7 @@ const UserBadgesContainer: FunctionComponent<Props> = ({ user }) => {
} }
return ( return (
<> <>
{user.badges.map(badge => ( {user.badges.map((badge) => (
<Tag <Tag
key={badge} key={badge}
color="dark" color="dark"
@@ -1,8 +1,9 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent, useMemo } from "react"; import React, { FunctionComponent, useMemo } from "react";
import { graphql } from "react-relay";
import { useCoralContext } from "coral-framework/lib/bootstrap"; import { useCoralContext } from "coral-framework/lib/bootstrap";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { import {
CallOut, CallOut,
HorizontalGutter, HorizontalGutter,
@@ -53,7 +54,7 @@ const UserDrawerAccountHistory: FunctionComponent<Props> = ({ user }) => {
const history: HistoryRecord[] = []; const history: HistoryRecord[] = [];
// Merge in all the suspension history items. // Merge in all the suspension history items.
user.status.suspension.history.forEach(record => { user.status.suspension.history.forEach((record) => {
const from: From = { const from: From = {
start: new Date(record.from.start), start: new Date(record.from.start),
finish: new Date(record.from.finish), finish: new Date(record.from.finish),
@@ -96,7 +97,7 @@ const UserDrawerAccountHistory: FunctionComponent<Props> = ({ user }) => {
}); });
// Merge in all the ban status history items. // Merge in all the ban status history items.
user.status.ban.history.forEach(record => { user.status.ban.history.forEach((record) => {
history.push({ history.push({
kind: "ban", kind: "ban",
action: { action: {
@@ -108,7 +109,7 @@ const UserDrawerAccountHistory: FunctionComponent<Props> = ({ user }) => {
}); });
// Merge in all the premod history items. // Merge in all the premod history items.
user.status.premod.history.forEach(record => { user.status.premod.history.forEach((record) => {
history.push({ history.push({
kind: "premod", kind: "premod",
action: { action: {
@@ -1,11 +1,8 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { import { QueryRenderData, QueryRenderer } from "coral-framework/lib/relay";
graphql,
QueryRenderData,
QueryRenderer,
} from "coral-framework/lib/relay";
import { CallOut, Spinner } from "coral-ui/components/v2"; import { CallOut, Spinner } from "coral-ui/components/v2";
import { UserDrawerAccountHistoryQuery as QueryTypes } from "coral-admin/__generated__/UserDrawerAccountHistoryQuery.graphql"; import { UserDrawerAccountHistoryQuery as QueryTypes } from "coral-admin/__generated__/UserDrawerAccountHistoryQuery.graphql";
@@ -2,12 +2,9 @@ import { Localized } from "@fluent/react/compat";
import { FormApi } from "final-form"; import { FormApi } from "final-form";
import React, { FunctionComponent, useCallback } from "react"; import React, { FunctionComponent, useCallback } from "react";
import { Field, Form } from "react-final-form"; import { Field, Form } from "react-final-form";
import { graphql } from "react-relay";
import { import { useMutation, withFragmentContainer } from "coral-framework/lib/relay";
graphql,
useMutation,
withFragmentContainer,
} from "coral-framework/lib/relay";
import { required } from "coral-framework/lib/validation"; import { required } from "coral-framework/lib/validation";
import { import {
Button, Button,
@@ -91,7 +88,7 @@ const UserDrawerNotesContainer: FunctionComponent<Props> = ({
.concat() .concat()
.reverse() .reverse()
.map( .map(
note => (note) =>
note && ( note && (
<ModeratorNote <ModeratorNote
key={note.id} key={note.id}
@@ -1,7 +1,8 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { graphql, QueryRenderer } from "coral-framework/lib/relay"; import { QueryRenderer } from "coral-framework/lib/relay";
import { CallOut, Spinner } from "coral-ui/components/v2"; import { CallOut, Spinner } from "coral-ui/components/v2";
import { UserDrawerNotesQuery as QueryTypes } from "coral-admin/__generated__/UserDrawerNotesQuery.graphql"; import { UserDrawerNotesQuery as QueryTypes } from "coral-admin/__generated__/UserDrawerNotesQuery.graphql";
@@ -37,7 +37,7 @@ const UserHistoryDrawerAllComments: FunctionComponent<Props> = ({
}, [loadMore]); }, [loadMore]);
const hasMore = relay.hasMore(); const hasMore = relay.hasMore();
const comments = user ? user.allComments.edges.map(edge => edge.node) : []; const comments = user ? user.allComments.edges.map((edge) => edge.node) : [];
if (comments.length === 0) { if (comments.length === 0) {
return ( return (
@@ -59,7 +59,7 @@ const UserHistoryDrawerAllComments: FunctionComponent<Props> = ({
<ModerateCardContainer <ModerateCardContainer
comment={c} comment={c}
settings={settings} settings={settings}
danglingLogic={status => false} danglingLogic={(status) => false}
hideUsername hideUsername
showStoryInfo showStoryInfo
mini mini
@@ -1,7 +1,8 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { graphql, QueryRenderer } from "coral-framework/lib/relay"; import { QueryRenderer } from "coral-framework/lib/relay";
import { CallOut, Spinner } from "coral-ui/components/v2"; import { CallOut, Spinner } from "coral-ui/components/v2";
import { UserHistoryDrawerAllCommentsQuery as QueryTypes } from "coral-admin/__generated__/UserHistoryDrawerAllCommentsQuery.graphql"; import { UserHistoryDrawerAllCommentsQuery as QueryTypes } from "coral-admin/__generated__/UserHistoryDrawerAllCommentsQuery.graphql";
@@ -1,10 +1,11 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { UserStatusChangeContainer } from "coral-admin/components/UserStatus"; import { UserStatusChangeContainer } from "coral-admin/components/UserStatus";
import { CopyButton } from "coral-framework/components"; import { CopyButton } from "coral-framework/components";
import { useCoralContext } from "coral-framework/lib/bootstrap"; import { useCoralContext } from "coral-framework/lib/bootstrap";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { import {
Button, Button,
Divider, Divider,
@@ -1,11 +1,8 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { import { QueryRenderData, QueryRenderer } from "coral-framework/lib/relay";
graphql,
QueryRenderData,
QueryRenderer,
} from "coral-framework/lib/relay";
import { CallOut, Spinner } from "coral-ui/components/v2"; import { CallOut, Spinner } from "coral-ui/components/v2";
import { UserHistoryDrawerQuery as QueryTypes } from "coral-admin/__generated__/UserHistoryDrawerQuery.graphql"; import { UserHistoryDrawerQuery as QueryTypes } from "coral-admin/__generated__/UserHistoryDrawerQuery.graphql";
@@ -15,6 +15,8 @@ import { UserHistoryDrawerRejectedCommentsPaginationQueryVariables } from "coral
import styles from "./UserHistoryDrawerRejectedComments.css"; import styles from "./UserHistoryDrawerRejectedComments.css";
const danglingLogic = () => false;
interface Props { interface Props {
user: UserHistoryDrawerRejectedComments_user; user: UserHistoryDrawerRejectedComments_user;
settings: UserHistoryDrawerRejectedComments_settings; settings: UserHistoryDrawerRejectedComments_settings;
@@ -38,7 +40,7 @@ const UserHistoryDrawerRejectedComments: FunctionComponent<Props> = ({
const hasMore = relay.hasMore(); const hasMore = relay.hasMore();
const comments = user const comments = user
? user.rejectedComments.edges.map(edge => edge.node) ? user.rejectedComments.edges.map((edge) => edge.node)
: []; : [];
if (comments.length === 0) { if (comments.length === 0) {
@@ -61,7 +63,7 @@ const UserHistoryDrawerRejectedComments: FunctionComponent<Props> = ({
<ModerateCardContainer <ModerateCardContainer
comment={c} comment={c}
settings={settings} settings={settings}
danglingLogic={status => false} danglingLogic={danglingLogic}
hideUsername hideUsername
showStoryInfo showStoryInfo
mini mini
@@ -1,7 +1,8 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent } from "react"; import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { graphql, QueryRenderer } from "coral-framework/lib/relay"; import { QueryRenderer } from "coral-framework/lib/relay";
import { CallOut, Spinner } from "coral-ui/components/v2"; import { CallOut, Spinner } from "coral-ui/components/v2";
import UserHistoryDrawerRejectedComments from "./UserHistoryDrawerRejectedComments"; import UserHistoryDrawerRejectedComments from "./UserHistoryDrawerRejectedComments";
@@ -1,8 +1,9 @@
import { Localized } from "@fluent/react/compat"; import { Localized } from "@fluent/react/compat";
import React, { FunctionComponent, useMemo } from "react"; import React, { FunctionComponent, useMemo } from "react";
import { graphql } from "react-relay";
import { useCoralContext } from "coral-framework/lib/bootstrap"; import { useCoralContext } from "coral-framework/lib/bootstrap";
import { graphql, withFragmentContainer } from "coral-framework/lib/relay"; import { withFragmentContainer } from "coral-framework/lib/relay";
import { import {
BaseButton, BaseButton,
Box, Box,
@@ -25,11 +26,11 @@ const UserStatusDetailsContainer: FunctionComponent<Props> = ({ user }) => {
} }
const activeBan = useMemo(() => { const activeBan = useMemo(() => {
return user.status.ban.history.find(item => item.active); return user.status.ban.history.find((item) => item.active);
}, [user]); }, [user]);
const activeSuspension = useMemo(() => { const activeSuspension = useMemo(() => {
return user.status.suspension.history.find(item => item.active); return user.status.suspension.history.find((item) => item.active);
}, [user]); }, [user]);
const { locales } = useCoralContext(); const { locales } = useCoralContext();
@@ -122,7 +123,7 @@ const UserStatusDetailsContainer: FunctionComponent<Props> = ({ user }) => {
> >
{({ toggleVisibility, ref }) => ( {({ toggleVisibility, ref }) => (
<BaseButton <BaseButton
onClick={evt => { onClick={(evt) => {
evt.stopPropagation(); evt.stopPropagation();
toggleVisibility(); toggleVisibility();
}} }}
@@ -21,7 +21,7 @@ interface Props {
role: GQLUSER_ROLE_RL; role: GQLUSER_ROLE_RL;
} }
const UserRoleChange: FunctionComponent<Props> = props => ( const UserRoleChange: FunctionComponent<Props> = (props) => (
<Localized id="community-role-popover" attrs={{ description: true }}> <Localized id="community-role-popover" attrs={{ description: true }}>
<Popover <Popover
id="community-roleChange" id="community-roleChange"
@@ -1,11 +1,8 @@
import React, { FunctionComponent, useCallback } from "react"; import React, { FunctionComponent, useCallback } from "react";
import { graphql } from "react-relay";
import { Ability, can } from "coral-admin/permissions"; import { Ability, can } from "coral-admin/permissions";
import { import { useMutation, withFragmentContainer } from "coral-framework/lib/relay";
graphql,
useMutation,
withFragmentContainer,
} from "coral-framework/lib/relay";
import { GQLUSER_ROLE_RL } from "coral-framework/schema"; import { GQLUSER_ROLE_RL } from "coral-framework/schema";
import { UserRoleChangeContainer_user } from "coral-admin/__generated__/UserRoleChangeContainer_user.graphql"; import { UserRoleChangeContainer_user } from "coral-admin/__generated__/UserRoleChangeContainer_user.graphql";
@@ -21,7 +18,7 @@ interface Props {
user: UserRoleChangeContainer_user; user: UserRoleChangeContainer_user;
} }
const UserRoleChangeContainer: FunctionComponent<Props> = props => { const UserRoleChangeContainer: FunctionComponent<Props> = (props) => {
const updateUserRole = useMutation(UpdateUserRoleMutation); const updateUserRole = useMutation(UpdateUserRoleMutation);
const handleOnChangeRole = useCallback( const handleOnChangeRole = useCallback(
(role: GQLUSER_ROLE_RL) => { (role: GQLUSER_ROLE_RL) => {
@@ -11,7 +11,7 @@ interface Props {
children: PropTypesOf<typeof TranslatedRole>["children"]; children: PropTypesOf<typeof TranslatedRole>["children"];
} }
const UserRoleText: FunctionComponent<Props> = props => ( const UserRoleText: FunctionComponent<Props> = (props) => (
<TranslatedRole <TranslatedRole
container={ container={
<span <span
@@ -62,7 +62,9 @@ const BanModal: FunctionComponent<Props> = ({
<Localized <Localized
id="community-banModal-areYouSure" id="community-banModal-areYouSure"
strong={<ModalHeaderUsername />} strong={<ModalHeaderUsername />}
$username={username || <NotAvailable />} username={React.createElement(() => (
<strong>{username || <NotAvailable />}</strong>
))}
> >
<ChangeStatusModalHeader id="banModal-title"> <ChangeStatusModalHeader id="banModal-title">
Are you sure you want to ban{" "} Are you sure you want to ban{" "}
@@ -31,7 +31,7 @@ const ChangeStatusModal: FunctionComponent<Props> = ({
}) => { }) => {
return ( return (
<Modal {...rest} onClose={onClose}> <Modal {...rest} onClose={onClose}>
{renderProps => ( {(renderProps) => (
<Card className={styles.root}> <Card className={styles.root}>
<Flex justifyContent="flex-end"> <Flex justifyContent="flex-end">
<CardCloseButton <CardCloseButton
@@ -2,9 +2,9 @@ import React, { FunctionComponent, HTMLAttributes } from "react";
import styles from "./ChangeStatusModalHeader.css"; import styles from "./ChangeStatusModalHeader.css";
const ChangeStatusModalHeader: FunctionComponent< const ChangeStatusModalHeader: FunctionComponent<HTMLAttributes<
HTMLAttributes<HTMLHeadingElement> HTMLHeadingElement
> = ({ children, ...rest }) => { >> = ({ children, ...rest }) => {
return ( return (
<h2 {...rest} className={styles.root}> <h2 {...rest} className={styles.root}>
{children} {children}
@@ -54,7 +54,7 @@ const RemoveUserBanMutation = createMutation(
current: lookup<GQLUser>( current: lookup<GQLUser>(
environment, environment,
input.userID input.userID
)!.status.current.filter(s => s !== GQLUSER_STATUS.BANNED), )!.status.current.filter((s) => s !== GQLUSER_STATUS.BANNED),
ban: { ban: {
active: false, active: false,
history: [], history: [],
@@ -57,7 +57,7 @@ const RemoveUserPremodMutation = createMutation(
current: lookup<GQLUser>( current: lookup<GQLUser>(
environment, environment,
input.userID input.userID
)!.status.current.filter(s => s !== GQLUSER_STATUS.PREMOD), )!.status.current.filter((s) => s !== GQLUSER_STATUS.PREMOD),
premod: { premod: {
active: false, active: false,
history: [ history: [
@@ -23,7 +23,7 @@ const RemoveUserSuspensionMutation = createMutation(
MutationTypes["response"]["removeUserSuspension"]["user"]["status"]["suspension"]["history"] MutationTypes["response"]["removeUserSuspension"]["user"]["status"]["suspension"]["history"]
> = []; > = [];
if (user.status.suspension.history) { if (user.status.suspension.history) {
newHistory = user.status.suspension.history.map(h => newHistory = user.status.suspension.history.map((h) =>
pick(h, [ pick(h, [
"active", "active",
"from.start", "from.start",
@@ -65,7 +65,7 @@ const SuspendForm: FunctionComponent<Props> = ({
const onFormSubmit = useCallback( const onFormSubmit = useCallback(
({ duration, emailMessage }) => { ({ duration, emailMessage }) => {
const unit = DURATIONS.find(d => d.value === duration); const unit = DURATIONS.find((d) => d.value === duration);
onSubmit(unit!, emailMessage); onSubmit(unit!, emailMessage);
}, },
[onSubmit] [onSubmit]
@@ -76,7 +76,7 @@ const SuspendForm: FunctionComponent<Props> = ({
if (state.lastFormState) { if (state.lastFormState) {
const { duration, emailMessage } = state.lastFormState const { duration, emailMessage } = state.lastFormState
.values as FormStateValues; .values as FormStateValues;
const unit = DURATIONS.find(d => d.value === duration); const unit = DURATIONS.find((d) => d.value === duration);
const expectedEmailMessage = getMessageWithDuration(unit!); const expectedEmailMessage = getMessageWithDuration(unit!);
if (expectedEmailMessage === emailMessage) { if (expectedEmailMessage === emailMessage) {
changeValue(state, name, () => newValue); changeValue(state, name, () => newValue);
@@ -94,7 +94,7 @@ const SuspendForm: FunctionComponent<Props> = ({
if (state.lastFormState && !checked) { if (state.lastFormState && !checked) {
const { duration, emailMessage } = state.lastFormState const { duration, emailMessage } = state.lastFormState
.values as FormStateValues; .values as FormStateValues;
const unit = DURATIONS.find(d => d.value === duration); const unit = DURATIONS.find((d) => d.value === duration);
const expectedEmailMessage = getMessageWithDuration(unit!); const expectedEmailMessage = getMessageWithDuration(unit!);
if (expectedEmailMessage !== emailMessage) { if (expectedEmailMessage !== emailMessage) {
changeValue(state, name, () => expectedEmailMessage); changeValue(state, name, () => expectedEmailMessage);
@@ -141,7 +141,7 @@ const SuspendForm: FunctionComponent<Props> = ({
<RadioButton <RadioButton
{...input} {...input}
id={`duration-${value}`} id={`duration-${value}`}
onChange={event => { onChange={(event) => {
form.mutators.setMessageValue( form.mutators.setMessageValue(
"emailMessage", "emailMessage",
getMessageWithDuration({ scaled, unit }) getMessageWithDuration({ scaled, unit })
@@ -165,7 +165,7 @@ const SuspendForm: FunctionComponent<Props> = ({
<CheckBox <CheckBox
{...input} {...input}
id="suspendModal-editMessage" id="suspendModal-editMessage"
onChange={event => { onChange={(event) => {
form.mutators.resetMessageValue( form.mutators.resetMessageValue(
"emailMessage", "emailMessage",
!input.checked !input.checked
@@ -20,7 +20,7 @@ const render = (className: string, content: React.ReactNode) => (
</div> </div>
); );
const UserStatus: FunctionComponent<Props> = props => { const UserStatus: FunctionComponent<Props> = (props) => {
if (props.banned) { if (props.banned) {
return render( return render(
styles.error, styles.error,
@@ -1,10 +1,7 @@
import React, { FunctionComponent, useCallback, useState } from "react"; import React, { FunctionComponent, useCallback, useState } from "react";
import { graphql } from "react-relay";
import { import { useMutation, withFragmentContainer } from "coral-framework/lib/relay";
graphql,
useMutation,
withFragmentContainer,
} from "coral-framework/lib/relay";
import { GQLUSER_ROLE } from "coral-framework/schema"; import { GQLUSER_ROLE } from "coral-framework/schema";
import { UserStatusChangeContainer_settings as SettingsData } from "coral-admin/__generated__/UserStatusChangeContainer_settings.graphql"; import { UserStatusChangeContainer_settings as SettingsData } from "coral-admin/__generated__/UserStatusChangeContainer_settings.graphql";
@@ -29,7 +26,7 @@ interface Props {
bordered?: boolean; bordered?: boolean;
} }
const UserStatusChangeContainer: FunctionComponent<Props> = props => { const UserStatusChangeContainer: FunctionComponent<Props> = (props) => {
const { user, settings, fullWidth, bordered } = props; const { user, settings, fullWidth, bordered } = props;
const banUser = useMutation(BanUserMutation); const banUser = useMutation(BanUserMutation);
const suspendUser = useMutation(SuspendUserMutation); const suspendUser = useMutation(SuspendUserMutation);
@@ -12,7 +12,7 @@ interface Props {
user: UserData; user: UserData;
} }
const UserStatusContainer: FunctionComponent<Props> = props => { const UserStatusContainer: FunctionComponent<Props> = (props) => {
return ( return (
<UserStatus <UserStatus
banned={props.user.status.current.includes(GQLUSER_STATUS.BANNED)} banned={props.user.status.current.includes(GQLUSER_STATUS.BANNED)}

Some files were not shown because too many files have changed in this diff Show More