Merge branch 'devel' into feature/smart-form-reset

This commit is contained in:
Eric Burel 2018-12-15 17:16:24 +01:00 committed by GitHub
commit 93566aba1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
74 changed files with 928 additions and 243 deletions

21
.prettierrc.js Normal file
View file

@ -0,0 +1,21 @@
'use strict';
const {esNextPaths} = require('./.vulcan/shared/pathsByLanguageVersion');
module.exports = {
bracketSpacing: false,
singleQuote: true,
jsxBracketSameLine: true,
trailingComma: 'es5',
printWidth: 80,
parser: 'babylon',
overrides: [
{
files: esNextPaths,
options: {
trailingComma: 'all',
},
},
],
};

76
.vulcan/prettier/index.js Normal file
View file

@ -0,0 +1,76 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
// Based on similar script in Jest
// https://github.com/facebook/jest/blob/a7acc5ae519613647ff2c253dd21933d6f94b47f/scripts/prettier.js
const chalk = require('chalk');
const glob = require('glob');
const prettier = require('prettier');
const fs = require('fs');
const listChangedFiles = require('../shared/listChangedFiles');
const prettierConfigPath = require.resolve('../../.prettierrc');
const mode = process.argv[2] || 'check';
const shouldWrite = mode === 'write' || mode === 'write-changed';
const onlyChanged = mode === 'check-changed' || mode === 'write-changed';
const changedFiles = onlyChanged ? listChangedFiles() : null;
let didWarn = false;
let didError = false;
const files = glob
.sync('**/*.js', {ignore: '**/node_modules/**'})
.filter(f => !onlyChanged || changedFiles.has(f));
if (!files.length) {
return;
}
files.forEach(file => {
const options = prettier.resolveConfig.sync(file, {
config: prettierConfigPath,
});
try {
const input = fs.readFileSync(file, 'utf8');
if (shouldWrite) {
const output = prettier.format(input, options);
if (output !== input) {
fs.writeFileSync(file, output, 'utf8');
}
} else {
if (!prettier.check(input, options)) {
if (!didWarn) {
console.log(
'\n' +
chalk.red(
` This project uses prettier to format all JavaScript code.\n`
) +
chalk.dim(` Please run `) +
chalk.reset('yarn prettier-all') +
chalk.dim(
` and add changes to files listed below to your commit:`
) +
`\n\n`
);
didWarn = true;
}
console.log(file);
}
}
} catch (error) {
didError = true;
console.log('\n\n' + error.message);
console.log(file);
}
});
if (didWarn || didError) {
process.exit(1);
}

View file

@ -0,0 +1,36 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const execFileSync = require('child_process').execFileSync;
const exec = (command, args) => {
console.log('> ' + [command].concat(args).join(' '));
const options = {
cwd: process.cwd(),
env: process.env,
stdio: 'pipe',
encoding: 'utf-8',
};
return execFileSync(command, args, options);
};
const execGitCmd = args =>
exec('git', args)
.trim()
.toString()
.split('\n');
const listChangedFiles = () => {
const mergeBase = execGitCmd(['merge-base', 'HEAD', 'devel']);
return new Set([
...execGitCmd(['diff', '--name-only', '--diff-filter=ACMRTUB', mergeBase]),
...execGitCmd(['ls-files', '--others', '--exclude-standard']),
]);
};
module.exports = listChangedFiles;

View file

@ -0,0 +1,18 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
// Files that are transformed and can use ES6/Flow/JSX.
const esNextPaths = [
// Internal forwarding modules
'packages/*/*.js',
'packages/*/*.jsx',
];
module.exports = {
esNextPaths,
};

405
package-lock.json generated
View file

@ -1326,6 +1326,23 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
},
"caller-callsite": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
"integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
"dev": true,
"requires": {
"callsites": "^2.0.0"
},
"dependencies": {
"callsites": {
"version": "2.0.0",
"resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
"integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
"dev": true
}
}
},
"caller-path": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
@ -1512,6 +1529,12 @@
"moment": "^2.10.3"
}
},
"ci-info": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
"integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
"dev": true
},
"circular-json": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
@ -1737,6 +1760,30 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cosmiconfig": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz",
"integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==",
"dev": true,
"requires": {
"import-fresh": "^2.0.0",
"is-directory": "^0.3.1",
"js-yaml": "^3.9.0",
"parse-json": "^4.0.0"
},
"dependencies": {
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"dev": true,
"requires": {
"error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1"
}
}
}
},
"create-react-class": {
"version": "15.6.2",
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.2.tgz",
@ -1756,6 +1803,27 @@
"whatwg-fetch": "2.0.3"
}
},
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true,
"requires": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
},
"dependencies": {
"semver": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
"dev": true
}
}
},
"cross-spawn-async": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz",
@ -2100,6 +2168,15 @@
"iconv-lite": "~0.4.13"
}
},
"end-of-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
"dev": true,
"requires": {
"once": "^1.4.0"
}
},
"entities": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
@ -2835,6 +2912,21 @@
}
}
},
"execa": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
"dev": true,
"requires": {
"cross-spawn": "^6.0.0",
"get-stream": "^4.0.0",
"is-stream": "^1.1.0",
"npm-run-path": "^2.0.0",
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
}
},
"exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
@ -3235,6 +3327,21 @@
"is-property": "^1.0.0"
}
},
"get-stdin": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
"integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
"dev": true
},
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
"dev": true,
"requires": {
"pump": "^3.0.0"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@ -3244,9 +3351,9 @@
}
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -3574,6 +3681,117 @@
"sshpk": "^1.7.0"
}
},
"husky": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/husky/-/husky-1.2.0.tgz",
"integrity": "sha512-/ib3+iycykXC0tYIxsyqierikVa9DA2DrT32UEirqNEFVqOj1bFMTgP3jAz8HM7FgC/C8pc/BTUa9MV2GEkZaA==",
"dev": true,
"requires": {
"cosmiconfig": "^5.0.6",
"execa": "^1.0.0",
"find-up": "^3.0.0",
"get-stdin": "^6.0.0",
"is-ci": "^1.2.1",
"pkg-dir": "^3.0.0",
"please-upgrade-node": "^3.1.1",
"read-pkg": "^4.0.1",
"run-node": "^1.0.0",
"slash": "^2.0.0"
},
"dependencies": {
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"p-limit": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz",
"integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz",
"integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
"dev": true
},
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"dev": true,
"requires": {
"error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1"
}
},
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true
},
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
},
"pkg-dir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
"integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
"dev": true,
"requires": {
"find-up": "^3.0.0"
}
},
"read-pkg": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz",
"integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=",
"dev": true,
"requires": {
"normalize-package-data": "^2.3.2",
"parse-json": "^4.0.0",
"pify": "^3.0.0"
}
},
"slash": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
"dev": true
}
}
},
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
@ -3622,6 +3840,33 @@
}
}
},
"import-fresh": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
"integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
"dev": true,
"requires": {
"caller-path": "^2.0.0",
"resolve-from": "^3.0.0"
},
"dependencies": {
"caller-path": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
"integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
"dev": true,
"requires": {
"caller-callsite": "^2.0.0"
}
},
"resolve-from": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
"integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
"dev": true
}
}
},
"import-inspector": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/import-inspector/-/import-inspector-2.0.0.tgz",
@ -3795,6 +4040,15 @@
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
"integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI="
},
"is-ci": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
"integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
"dev": true,
"requires": {
"ci-info": "^1.5.0"
}
},
"is-date-object": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
@ -3805,6 +4059,12 @@
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.1.tgz",
"integrity": "sha1-9ftqlJlq2ejjdh+/vQkfH8qMToI="
},
"is-directory": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
"dev": true
},
"is-dotfile": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
@ -4201,6 +4461,12 @@
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
"dev": true
},
"json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
"dev": true
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
@ -4909,7 +5175,7 @@
"process": "^0.11.9",
"punycode": "^1.4.1",
"querystring-es3": "^0.2.1",
"readable-stream": "git+https://github.com/meteor/readable-stream.git#2e9112d7d31a2af6e0682db0e18679b1e5fd4694",
"readable-stream": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12",
"stream-browserify": "^2.0.1",
"string_decoder": "^1.0.1",
"timers-browserify": "^1.4.2",
@ -5318,11 +5584,6 @@
"resolved": "https://registry.npmjs.org/process/-/process-0.11.9.tgz",
"integrity": "sha1-e9WtIapiU+fahoImTx4R0RwDGME="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"public-encrypt": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
@ -5356,15 +5617,40 @@
"integrity": "sha1-Z0yZdgkBw8QRJ3GjHlIdw0nMCew="
},
"readable-stream": {
"version": "git+https://github.com/meteor/readable-stream.git#2e9112d7d31a2af6e0682db0e18679b1e5fd4694",
"version": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12",
"from": "git+https://github.com/meteor/readable-stream.git",
"requires": {
"inherits": "~2.0.1",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"safe-buffer": "^5.0.1",
"string_decoder": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.0",
"util-deprecate": "~1.0.1"
},
"dependencies": {
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"rimraf": {
@ -5618,6 +5904,12 @@
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz",
"integrity": "sha1-ddpKkn7liH45BliABltzNkE7MQ0="
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"node-fetch": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
@ -5672,6 +5964,15 @@
"integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
"dev": true
},
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
"dev": true,
"requires": {
"path-key": "^2.0.0"
}
},
"nth-check": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
@ -5842,6 +6143,12 @@
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true
},
"p-limit": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz",
@ -5943,6 +6250,12 @@
"integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
"dev": true
},
"path-key": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
"dev": true
},
"path-parse": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
@ -6004,6 +6317,15 @@
"find-up": "^1.0.0"
}
},
"please-upgrade-node": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz",
"integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==",
"dev": true,
"requires": {
"semver-compare": "^1.0.0"
}
},
"pluralize": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz",
@ -6130,6 +6452,12 @@
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
"dev": true
},
"prettier": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.15.2.tgz",
"integrity": "sha512-YgPLFFA0CdKL4Eg2IHtUSjzj/BWgszDHiNQAe0VAIBse34148whfdzLagRL+QiKS+YfK5ftB6X4v/MBw8yCoug==",
"dev": true
},
"pretty-format": {
"version": "23.2.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.2.0.tgz",
@ -6205,6 +6533,16 @@
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
"pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dev": true,
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
@ -6925,6 +7263,12 @@
"once": "^1.3.0"
}
},
"run-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz",
"integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==",
"dev": true
},
"rx-lite": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz",
@ -7006,6 +7350,12 @@
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"dev": true
},
"semver-compare": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
"dev": true
},
"send": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz",
@ -7229,6 +7579,21 @@
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.0.2.tgz",
"integrity": "sha512-zlVXeVUKvo+HEv1e2KQF/csyeMKx2oHvatQ9l6XjCUj3agvC8XGf6R9HvIPDSmp8FNPvx7b5kaEJTRi7CqxtEw=="
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
"dev": true,
"requires": {
"shebang-regex": "^1.0.0"
}
},
"shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true
},
"shelljs": {
"version": "0.7.8",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz",
@ -7240,6 +7605,12 @@
"rechoir": "^0.6.2"
}
},
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true
},
"simpl-schema": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/simpl-schema/-/simpl-schema-1.4.2.tgz",
@ -7428,6 +7799,12 @@
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
"dev": true
},
"strip-eof": {
"version": "1.0.0",
"resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",

View file

@ -1,6 +1,6 @@
{
"name": "Vulcan",
"version": "1.12.10",
"version": "1.12.11",
"engines": {
"npm": "^3.0"
},
@ -8,7 +8,15 @@
"start": "meteor --settings settings.json",
"lint": "eslint --cache --ext .jsx,js packages",
"test-unit": "TEST_WATCH=1 meteor test-packages ./packages/* --port 3002 --driver-package meteortesting:mocha --raw-logs",
"test": "npm run test-unit"
"test": "npm run test-unit",
"prettier": "node ./.vulcan/prettier/index.js write-changed",
"prettier-all": "node ./.vulcan/prettier/index.js write"
},
"husky": {
"hooks": {
"pre-commit": "npm run lint",
"pre-push": "npm run prettier"
}
},
"dependencies": {
"@babel/runtime": "^7.0.0-beta.38",
@ -93,6 +101,7 @@
"devDependencies": {
"autoprefixer": "^6.3.6",
"babel-eslint": "^7.0.0",
"babylon": "^6.18.0",
"chromedriver": "^2.40.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16.3": "^1.4.0",
@ -108,8 +117,11 @@
"eslint-plugin-prettier": "^2.5.0",
"eslint-plugin-react": "^6.7.1",
"expect": "^23.4.0",
"glob": "^7.1.3",
"husky": "^1.2.0",
"jsdom": "^11.11.0",
"jsdom-global": "^3.0.2",
"prettier": "^1.15.2",
"selenium-webdriver": "^4.0.0-alpha.1"
},
"postcss": {

View file

@ -1,6 +1,6 @@
Package.describe({
name: 'vulcan:accounts',
version: '1.12.10',
version: '1.12.11',
summary: 'Accounts UI for React in Meteor 1.3+',
git: 'https://github.com/studiointeract/accounts-ui',
documentation: 'README.md'
@ -9,7 +9,7 @@ Package.describe({
Package.onUse(function(api) {
api.versionsFrom('1.6.1');
api.use('vulcan:core@1.12.10');
api.use('vulcan:core@1.12.11');
api.use('ecmascript');
api.use('tracker');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:admin',
summary: 'Vulcan components package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -14,7 +14,7 @@ Package.onUse(function (api) {
'fourseven:scss@4.10.0',
'dynamic-import@0.1.1',
// Vulcan packages
'vulcan:core@1.12.10',
'vulcan:core@1.12.11',
]);

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:cloudinary',
summary: 'Vulcan file upload package.',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10'
'vulcan:core@1.12.11'
]);
api.mainModule('lib/client/main.js', 'client');

View file

@ -7,7 +7,7 @@ import {
detectLocale,
hasIntlFields,
} from 'meteor/vulcan:lib';
import React, { PureComponent, Fragment } from 'react';
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { IntlProvider, intlShape } from 'meteor/vulcan:i18n';
import withCurrentUser from '../containers/withCurrentUser.js';

View file

@ -32,15 +32,15 @@ EditForm Component
const EditForm = ({ closeModal, successCallback, removeSuccessCallback, ...props }) => {
const success = successCallback
? () => {
successCallback();
? document => {
successCallback(document);
closeModal();
}
: closeModal;
const remove = removeSuccessCallback
? () => {
removeSuccessCallback();
? document => {
removeSuccessCallback(document);
closeModal();
}
: closeModal;

View file

@ -31,8 +31,8 @@ NewForm Component
const NewForm = ({ closeModal, successCallback, ...props }) => {
const success = successCallback
? () => {
successCallback();
? document => {
successCallback(document);
closeModal();
}
: closeModal;

View file

@ -44,6 +44,7 @@ export default function withSingle(options) {
const propertyName = options.propertyName || 'document';
const props = {
loading: data.loading,
refetch: data.refetch,
// document: Utils.convertDates(collection, data[singleResolverName]),
[propertyName]: data[resolverName] && data[resolverName].result,
fragmentName,

View file

@ -4,8 +4,7 @@ Default list, single, and total resolvers
*/
import { Utils, debug, debugGroup, debugGroupEnd, Connectors, getTypeName, getCollectionName } from 'meteor/vulcan:lib';
import { createError } from 'apollo-errors';
import { Utils, debug, debugGroup, debugGroupEnd, Connectors, getTypeName, getCollectionName, throwError } from 'meteor/vulcan:lib';
const defaultOptions = {
cacheMaxAge: 300
@ -118,8 +117,7 @@ export function getDefaultResolvers(options) {
if (allowNull) {
return { result: null };
} else {
const MissingDocumentError = createError('app.missing_document', { message: 'app.missing_document' });
throw new MissingDocumentError({ data: { documentId, selector } });
throwError({ id: 'app.missing_document', data: {documentId, selector} });
}
}

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:core',
summary: 'Vulcan core package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -9,14 +9,14 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:lib@1.12.10',
'vulcan:i18n@1.12.10',
'vulcan:users@1.12.10',
'vulcan:routing@1.12.10',
'vulcan:debug@1.12.10'
'vulcan:lib@1.12.11',
'vulcan:i18n@1.12.11',
'vulcan:users@1.12.11',
'vulcan:routing@1.12.11',
'vulcan:debug@1.12.11'
]);
api.imply(['vulcan:lib@1.12.10']);
api.imply(['vulcan:lib@1.12.11']);
api.mainModule('lib/server/main.js', 'server');
api.mainModule('lib/client/main.js', 'client');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:debug',
summary: 'Vulcan debug package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git',
debugOnly: true
});
@ -17,8 +17,8 @@ Package.onUse(function (api) {
// Vulcan packages
'vulcan:lib@1.12.10',
'vulcan:email@1.12.10',
'vulcan:lib@1.12.11',
'vulcan:email@1.12.11',
]);

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:email',
summary: 'Vulcan email package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:lib@1.12.10'
'vulcan:lib@1.12.11'
]);
api.mainModule('lib/server.js', 'server');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:embed',
summary: 'Vulcan Embed package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -11,7 +11,7 @@ Package.onUse( function(api) {
api.use([
'http',
'vulcan:core@1.12.10',
'vulcan:core@1.12.11',
'fourseven:scss@4.10.0'
]);

View file

@ -1,4 +1,4 @@
import { getSetting, sourceVersion } from 'meteor/vulcan:core';
import { getSetting, getSourceVersion } from 'meteor/vulcan:core';
import { addInitFunction, addLogFunction, addUserFunction } from 'meteor/vulcan:errors';
import { serverDSNSetting } from '../modules/settings';
import Sentry from '@sentry/node';
@ -17,7 +17,7 @@ function initSentryForServer() {
dsn: serverDSN,
environment,
// see https://github.com/zodern/meteor-up/issues/807#issuecomment-346915622
release: sourceVersion,
release: getSourceVersion(),
});
}
addInitFunction(initSentryForServer);

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:errors-sentry',
summary: 'Vulcan Sentry error tracking package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -11,9 +11,9 @@ Package.onUse(function(api) {
api.use([
'ecmascript',
'vulcan:core@1.12.10',
'vulcan:users@1.12.10',
'vulcan:errors@1.12.10',
'vulcan:core@1.12.11',
'vulcan:users@1.12.11',
'vulcan:errors@1.12.11',
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -20,7 +20,7 @@ class ErrorCatcher extends Component {
};
componentDidCatch = (error, errorInfo) => {
const { currentUser, siteData } = this.props;
const { currentUser, siteData = {} } = this.props;
const { sourceVersion } = siteData;
this.setState({ error });
Errors.log({

View file

@ -24,10 +24,9 @@ class ErrorsUserMonitor extends PureComponent {
const errorsUserId = Errors.currentUser && Errors.currentUser._id;
if (currentUserId !== errorsUserId) {
const currentUserEmail = currentUser && currentUser.email;
const errorsUserEmail = Errors.currentUser && Errors.currentUser.email;
console.log(`User changed from ${errorsUserEmail} (${errorsUserId}) to ${currentUserEmail} (${currentUserId})`);
// const currentUserEmail = currentUser && currentUser.email;
// const errorsUserEmail = Errors.currentUser && Errors.currentUser.email;
// console.log(`User changed from ${errorsUserEmail} (${errorsUserId}) to ${currentUserEmail} (${currentUserId})`);
Errors.setCurrentUser(currentUser);
}

View file

@ -1,10 +1,10 @@
import Users from 'meteor/vulcan:users';
import { getSetting } from 'meteor/vulcan:core';
import get from 'lodash/get';
// import Users from 'meteor/vulcan:users';
// import { getSetting } from 'meteor/vulcan:core';
// import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import { formatMessage } from 'meteor/vulcan:i18n';
import _isEmpty from 'lodash/isEmpty';
import { inspect } from 'util';
// import { formatMessage } from 'meteor/vulcan:i18n';
// import _isEmpty from 'lodash/isEmpty';
// import { inspect } from 'util';
export const initFunctions = [];
export const logFunctions = [];

View file

@ -1,3 +1,3 @@
import '../components/ErrorsUserMonitor';
import '../components/ErrorCatcher';
export * from './errors';
export * from './errors.js';

View file

@ -1,8 +1,8 @@
Package.describe({
name: "vulcan:errors",
summary: "Vulcan error tracking package",
version: '1.12.10',
git: "https://github.com/VulcanJS/Vulcan.git"
name: 'vulcan:errors',
summary: 'Vulcan error tracking package',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
Package.onUse(function(api) {
@ -11,10 +11,10 @@ Package.onUse(function(api) {
api.use([
'ecmascript',
'vulcan:core@1.12.10',
'vulcan:core@1.12.11',
]);
api.mainModule("lib/server/main.js", "server");
api.mainModule('lib/server/main.js', 'server');
api.mainModule('lib/client/main.js', 'client');
});

View file

@ -1,5 +1,5 @@
import { getSetting } from 'meteor/vulcan:core';
import { addPageFunction, addInitFunction } from 'meteor/vulcan:events';
import { addPageFunction, addInitFunction, addTrackFunction } from 'meteor/vulcan:events';
/*
@ -19,10 +19,25 @@ function googleAnaticsTrackPage() {
}
return {};
}
// add client-side callback: log a ga request on page view
addPageFunction(googleAnaticsTrackPage);
function googleAnaticsTrackEvent(name, properties, currentUser) {
const { category = name, action = name, label = name, value } = properties;
if (window && window.ga) {
window.ga('send', {
hitType: 'event',
eventCategory: category,
eventAction: action,
eventLabel: label,
eventValue: value,
});
}
return {};
}
// add client-side callback: log a ga request on page view
addTrackFunction(googleAnaticsTrackEvent);
function googleAnalyticsInit() {
// get the google analytics id from the settings
const googleAnalyticsId = getSetting('googleAnalytics.apiKey');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:events-ga',
summary: 'Vulcan Google Analytics event tracking package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,8 +10,8 @@ Package.onUse(function(api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:events@1.12.10',
'vulcan:core@1.12.11',
'vulcan:events@1.12.11',
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:events-intercom',
summary: 'Vulcan Intercom integration package.',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,8 +10,8 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:events@1.12.10'
'vulcan:core@1.12.11',
'vulcan:events@1.12.11'
]);
api.mainModule('lib/client/main.js', 'client');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:events-internal',
summary: 'Vulcan internal event tracking package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,8 +10,8 @@ Package.onUse(function(api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:events@1.12.10',
'vulcan:core@1.12.11',
'vulcan:events@1.12.11',
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:events-segment',
summary: 'Vulcan Segment',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,8 +10,8 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:events@1.12.10',
'vulcan:core@1.12.11',
'vulcan:events@1.12.11',
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:events',
summary: 'Vulcan event tracking package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function(api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:core@1.12.11',
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -1,12 +1,9 @@
import React, { PureComponent } from 'react';
import FRC from 'formsy-react-components';
import ReactTagInput from 'react-tag-input';
import PropTypes from 'prop-types';
const ReactTags = ReactTagInput.WithContext;
const Input = FRC.Input;
class Tags extends PureComponent {
constructor(props) {

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:forms-tags',
summary: 'Vulcan tag input package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,8 +10,8 @@ Package.onUse( function(api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:forms@1.12.10'
'vulcan:core@1.12.11',
'vulcan:forms@1.12.11'
]);
api.mainModule('lib/export.js', ['client', 'server']);

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:forms-upload',
summary: 'Vulcan package extending vulcan:forms to upload images to Cloudinary from a drop zone.',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/xavcz/nova-forms-upload.git'
});
@ -10,8 +10,8 @@ Package.onUse( function(api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:forms@1.12.10',
'vulcan:core@1.12.11',
'vulcan:forms@1.12.11',
'fourseven:scss@4.10.0'
]);

View file

@ -26,7 +26,6 @@ import {
registerComponent,
Components,
runCallbacks,
getCollection,
getErrors,
getSetting,
Utils,
@ -106,6 +105,17 @@ const getInitialStateFromProps = nextProps => {
nextProps.prefilledProps,
nextProps.document
);
//if minCount is specified, go ahead and create empty nested documents
Object.keys(convertedSchema).forEach(key => {
let minCount = convertedSchema[key].minCount;
if(minCount) {
initialDocument[key] = initialDocument[key] || [];
while(initialDocument[key].length < minCount)
initialDocument[key].push({});
}
})
// remove all instances of the `__typename` property from document
Utils.removeProperty(initialDocument, '__typename');
@ -145,7 +155,7 @@ class SmartForm extends Component {
};
}
defaultValues = {};
defaultValues = {};
submitFormCallbacks = [];
successFormCallbacks = [];
@ -860,7 +870,7 @@ class SmartForm extends Component {
mutationSuccessCallback = (result, mutationType) => {
this.setState(prevState => ({ disabled: false }));
const document = result.data[Object.keys(result.data)[0]].data; // document is always on first property
let document = result.data[Object.keys(result.data)[0]].data; // document is always on first property
// for new mutation, run refetch function if it exists
if (mutationType === 'new' && this.props.refetch) this.props.refetch();
@ -875,10 +885,10 @@ class SmartForm extends Component {
}
// run document through mutation success callbacks
result = runCallbacks(this.successFormCallbacks, result);
document = runCallbacks(this.successFormCallbacks, document, { form: this });
// run success callback if it exists
if (this.props.successCallback) this.props.successCallback(document);
if (this.props.successCallback) this.props.successCallback(document, { form: this });
};
// catch graphql errors
@ -891,7 +901,7 @@ class SmartForm extends Component {
console.log(error);
// run mutation failure callbacks on error, we do not allow the callbacks to change the error
runCallbacks(this.failureFormCallbacks, error);
runCallbacks(this.failureFormCallbacks, error, { form: this });
if (!_.isEmpty(error)) {
// add error to state
@ -899,7 +909,7 @@ class SmartForm extends Component {
}
// run error callback if it exists
if (this.props.errorCallback) this.props.errorCallback(document, error);
if (this.props.errorCallback) this.props.errorCallback(document, error, { form: this });
// scroll back up to show error messages
Utils.scrollIntoView('.flash-message');
@ -990,6 +1000,7 @@ class SmartForm extends Component {
return (
<div className={'document-' + this.getFormType()}>
<Formsy.Form
id={this.props.id}
onSubmit={this.submitForm}
onKeyDown={this.formKeyDown}
ref={e => {
@ -1062,7 +1073,6 @@ SmartForm.propTypes = {
fields: PropTypes.arrayOf(PropTypes.string),
removeFields: PropTypes.arrayOf(PropTypes.string),
hideFields: PropTypes.arrayOf(PropTypes.string), // OpenCRUD backwards compatibility
addFields: PropTypes.arrayOf(PropTypes.string), // OpenCRUD backwards compatibility
showRemove: PropTypes.bool,
submitLabel: PropTypes.node,
cancelLabel: PropTypes.node,

View file

@ -58,14 +58,20 @@ class FormNestedArray extends PureComponent {
'inputProperties',
'nestedInput'
);
const { errors, path, label, formComponents } = this.props;
const { errors, path, label, formComponents, minCount, maxCount } = this.props;
const FormComponents = formComponents;
//filter out null values to calculate array length
let arrayLength = value.filter(singleValue => {
return !!singleValue;
}).length;
// only keep errors specific to the nested array (and not its subfields)
const nestedArrayErrors = errors.filter(
error => error.path && error.path === path
);
const hasErrors = nestedArrayErrors && nestedArrayErrors.length;
return (
<FormComponents.FormNestedArrayLayout
label={label}
@ -81,6 +87,7 @@ class FormNestedArray extends PureComponent {
removeItem={() => {
this.removeItem(i);
}}
hideRemove={minCount && arrayLength <= minCount}
/>
<FormComponents.FormNestedDivider
label={this.props.label}
@ -89,15 +96,17 @@ class FormNestedArray extends PureComponent {
</React.Fragment>
)
),
<Components.Button
key="add-button"
size="small"
variant="success"
onClick={this.addItem}
className="form-nested-button"
>
(!maxCount || arrayLength < maxCount) && (
<Components.Button
key="add-button"
size="small"
variant="success"
onClick={this.addItem}
className="form-nested-button"
>
<Components.IconAdd height={12} width={12} />
</Components.Button>,
</Components.Button>
),
hasErrors ? (
<FormComponents.FieldErrors
key="form-nested-errors"

View file

@ -1,7 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { registerComponent } from 'meteor/vulcan:core';
import { FormattedMessage } from 'meteor/vulcan:i18n';
const FormNestedDivider = ({ label, addItem }) => <div/>;

View file

@ -1,7 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Components, registerComponent } from 'meteor/vulcan:core';
import { FormattedMessage } from 'meteor/vulcan:i18n';
const FormNestedFoot = ({ label, addItem }) => (
<Components.Button size="small" variant="success" iconButton onClick={addItem} className="form-nested-button">

View file

@ -1,7 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { registerComponent } from 'meteor/vulcan:core';
import { FormattedMessage } from 'meteor/vulcan:i18n';
const FormNestedHead = ({ label, addItem }) => (
<label className="control-label col-sm-3">{label}</label>

View file

@ -27,7 +27,7 @@ registerComponent({
});
const FormNestedItem = (
{ nestedFields, name, path, removeItem, itemIndex, formComponents, ...props },
{ nestedFields, name, path, removeItem, itemIndex, formComponents, hideRemove, ...props },
{ errors }
) => {
const FormComponents = mergeWithComponents(formComponents);
@ -46,7 +46,7 @@ const FormNestedItem = (
);
})}
removeButton={
isArray && [
isArray && !hideRemove && [
<div key="remove-button" className="form-nested-item-remove">
<Components.Button
className="form-nested-button"

View file

@ -1,7 +1,7 @@
/** PropTypes for documentation purpose (not tested yet) */
import PropTypes from 'prop-types';
const fieldProps = {
export const fieldProps = {
//
defaultValue: PropTypes.any,
help: PropTypes.string,
@ -28,7 +28,8 @@ const fieldProps = {
nestedInput: PropTypes.boolean, // flag
nestedFields: PropTypes.array //arrayOf(fieldProps)
};
const groupProps = {
export const groupProps = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
order: PropTypes.number,

View file

@ -1,14 +1,14 @@
Package.describe({
name: 'vulcan:forms',
summary: 'Form containers for React',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/meteor-utilities/react-form-containers.git'
});
Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use(['vulcan:core@1.12.10']);
api.use(['vulcan:core@1.12.11']);
api.mainModule('lib/client/main.js', ['client']);
api.mainModule('lib/server/main.js', ['server']);

View file

@ -136,10 +136,23 @@ addStrings('en', {
'admin': 'Admin',
'notifications': 'Notifications',
'errors.expectedType': 'Expected a field “{label}” of type {dataType}, got “{value}” instead.',
'errors.expectedType': 'Expected type {dataType} for field “{label}”, received “{value}” instead.',
'errors.required': 'Field “{label}” is required.',
'errors.minString': 'Field “{label}” needs to have at least {min} characters',
'errors.maxString': 'Field “{label}” is limited to {max} characters.',
'errors.generic': 'Sorry, something went wrong: <code>{errorMessage}</code>.',
'errors.generic_report': 'Sorry, something went wrong: <code>{errorMessage}</code>. <br/>An error report has been generated.',
});
'errors.minNumber': 'Field “{label}” must be higher than {min}. ',
'errors.maxNumber': 'Field “{label}” must be lower than {max}. ',
'errors.minCount': 'There needs to be at least {count} in field “{label}”.',
'errors.maxCount': 'Field “{label}” is only allowed {count}.',
'errors.regEx': 'Field “{label}”: wrong formatting',
'errors.badDate': 'Field “{label}” is not a date.',
'errors.notAllowed': 'The value for field “{label}” is not allowed.',
'errors.noDecimal': 'The value for field “{label}” must not be a decimal number.',
//TODO other simple schema errors
'errors.minNumberExclusive': '',
'errors.maxNumberExclusive': '',
'errors.keyNotInSchema': ''
});

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:i18n-en-us',
summary: 'Vulcan i18n package (en_US)',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10'
'vulcan:core@1.12.11'
]);
api.addFiles([

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:i18n-es-es',
summary: 'Vulcan i18n package (es_ES)',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10'
'vulcan:core@1.12.11'
]);
api.addFiles([

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:i18n-fr-fr',
summary: 'Vulcan i18n package (fr_FR)',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10'
'vulcan:core@1.12.11'
]);
api.addFiles([

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:i18n',
summary: 'i18n client polyfill',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:lib@1.12.10',
'vulcan:lib@1.12.11',
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -2,11 +2,11 @@ import { Mongo } from 'meteor/mongo';
import SimpleSchema from 'simpl-schema';
import { addGraphQLCollection, addToGraphQLContext } from './graphql.js';
import { Utils } from './utils.js';
import { runCallbacks, runCallbacksAsync } from './callbacks.js';
import { runCallbacks, runCallbacksAsync, registerCallback, addCallback } from './callbacks.js';
import { getSetting, registerSetting } from './settings.js';
import { registerFragment, getDefaultFragmentText } from './fragments.js';
import escapeStringRegexp from 'escape-string-regexp';
import { validateIntlField, getIntlString, isIntlField } from './intl';
import { validateIntlField, getIntlString, isIntlField, schemaHasIntlFields } from './intl';
const wrapAsync = Meteor.wrapAsync ? Meteor.wrapAsync : Meteor._wrapAsync;
// import { debug } from './debug.js';
@ -48,7 +48,6 @@ Mongo.Collection.prototype.attachSchema = function(schemaOrFields) {
*/
Mongo.Collection.prototype.addField = function(fieldOrFieldArray) {
const collection = this;
const schema = collection.simpleSchema()._schema;
const fieldSchema = {};
const fieldArray = Array.isArray(fieldOrFieldArray) ? fieldOrFieldArray : [fieldOrFieldArray];
@ -126,10 +125,10 @@ export const createCollection = options => {
const {
typeName,
collectionName = getCollectionName(typeName),
schema,
generateGraphQLSchema = true,
dbCollectionName
} = options;
let { schema } = options;
// initialize new Mongo collection
const collection =
@ -153,40 +152,19 @@ export const createCollection = options => {
// add views
collection.views = [];
// generate foo_intl fields
Object.keys(schema).forEach(fieldName => {
const fieldSchema = schema[fieldName];
if (isIntlField(fieldSchema)) {
// we have at least one intl field
hasIntlFields = true;
//register individual collection callback
registerCollectionCallback(typeName.toLowerCase());
// remove `intl` to avoid treating new _intl field as a field to internationalize
// eslint-disable-next-line no-unused-vars
const { intl, ...propertiesToCopy } = schema[fieldName];
// if schema has at least one intl field, add intl callback just before
// `${collectionName}.collection` callbacks run to make sure it always runs last
if (schemaHasIntlFields(schema)) {
hasIntlFields = true; // we have at least one intl field
addCallback(`${typeName.toLowerCase()}.collection`, addIntlFields);
}
schema[`${fieldName}_intl`] = {
...propertiesToCopy, // copy properties from regular field
hidden: true,
type: Array,
isIntlData: true
};
delete schema[`${fieldName}_intl`].intl;
schema[`${fieldName}_intl.$`] = {
type: getIntlString()
};
// if original field is required, enable custom validation function instead of `optional` property
if (!schema[fieldName].optional) {
schema[`${fieldName}_intl`].optional = true;
schema[`${fieldName}_intl`].custom = validateIntlField;
}
// make original non-intl field optional
schema[fieldName].optional = true;
}
});
//run schema callbacks and run general callbacks last
schema = runCallbacks({ name: `${typeName.toLowerCase()}.collection`, iterator: schema, properties: { options }});
schema = runCallbacks({ name: '*.collection', iterator: schema, properties: { options }});
if (schema) {
// attach schema to collection
@ -203,8 +181,8 @@ export const createCollection = options => {
addGraphQLCollection(collection);
}
runCallbacksAsync({ name: '*.collection', properties: { options } });
runCallbacksAsync({ name: `${collectionName}.collection`, properties: { options } });
runCallbacksAsync({ name: '*.collection.async', properties: { options } });
runCallbacksAsync({ name: `${collectionName}.collection.async`, properties: { options } });
// ------------------------------------- Default Fragment -------------------------------- //
@ -313,6 +291,7 @@ export const createCollection = options => {
}
});
} else {
// eslint-disable-next-line no-console
console.warn(
`Warning: terms.query is set but schema ${
collection.options.typeName
@ -335,3 +314,67 @@ export const createCollection = options => {
return collection;
};
//register collection creation hook for each collection
function registerCollectionCallback(typeName) {
registerCallback({
name: `${typeName}.collection`,
iterator: { schema: 'the schema of the collection' },
properties: [
{ schema: 'The schema of the collection' },
{ validationErrors: 'An Object that can be used to accumulate validation errors' }
],
runs: 'sync',
returns: 'schema',
description: 'Modifies schemas on collection creation'
})
}
//register colleciton creation hook
registerCallback({
name: '*.collection',
iterator: { schema: 'the schema of the collection' },
properties: [
{ schema: 'The schema of the collection' },
{ validationErrors: 'An object that can be used to accumulate validation errors' }
],
runs: 'sync',
returns: 'schema',
description: 'Modifies schemas on collection creation',
});
// generate foo_intl fields
function addIntlFields(schema) {
Object.keys(schema).forEach(fieldName => {
const fieldSchema = schema[fieldName];
if (isIntlField(fieldSchema)) {
// remove `intl` to avoid treating new _intl field as a field to internationalize
// eslint-disable-next-line no-unused-vars
const { intl, ...propertiesToCopy } = schema[fieldName];
schema[`${fieldName}_intl`] = {
...propertiesToCopy, // copy properties from regular field
hidden: true,
type: Array,
isIntlData: true
};
delete schema[`${fieldName}_intl`].intl;
schema[`${fieldName}_intl.$`] = {
type: getIntlString()
};
// if original field is required, enable custom validation function instead of `optional` property
if (!schema[fieldName].optional) {
schema[`${fieldName}_intl`].optional = true;
schema[`${fieldName}_intl`].custom = validateIntlField;
}
// make original non-intl field optional
schema[fieldName].optional = true;
}
});
return schema;
}

View file

@ -9,7 +9,7 @@ import SimpleSchema from 'simpl-schema';
Vulcan = {};
// eslint-disable-next-line no-undef
Vulcan.VERSION = '1.12.10';
Vulcan.VERSION = '1.12.11';
// ------------------------------------- Schemas -------------------------------- //

View file

@ -1,3 +1,5 @@
import { createError } from 'apollo-errors';
/*
Get whatever word is contained between the first two double quotes
@ -89,4 +91,19 @@ export const getErrors = error => {
}
}
return errors;
}
}
/*
An error should have:
- id: will be used as i18n key (note: available as `name` on the client)
- message: optionally, a plain-text message
- data: data/values to give more context to the error
*/
export const throwError = error => {
const { id, message = id, data } = error;
const MissingDocumentError = createError(id, { message });
throw new MissingDocumentError({ id, data });
};

View file

@ -70,6 +70,13 @@ export const getIntlString = () => {
/*
Check if a schema has at least one intl field
*/
export const schemaHasIntlFields = schema => Object.keys(schema).some(fieldName => isIntlField(schema[fieldName]));
/*
Custom validation function to check for required locales
See https://github.com/aldeed/simple-schema-js#custom-field-validation
@ -87,7 +94,7 @@ export const validateIntlField = function() {
if (!hasString) {
const originalFieldName = this.key.replace('_intl', '');
errors.push({
id: '',
id: 'errors.required',
path: `${this.key}.${index}`,
properties: { name: originalFieldName, locale: locale.id }
});

View file

@ -14,6 +14,7 @@ import { getCollection } from './collections.js';
import set from 'lodash/set';
import get from 'lodash/get';
import isFunction from 'lodash/isFunction';
import { throwError } from './errors.js';
registerSetting('debug', false, 'Enable debug mode (more verbose logging)');
@ -169,13 +170,13 @@ Utils.slugify = function (s) {
return slug;
};
Utils.getUnusedSlug = function (collection, slug) {
let suffix = "";
let suffix = '';
let index = 0;
// test if slug is already in use
while (!!collection.findOne({slug: slug+suffix})) {
index++;
suffix = "-"+index;
suffix = '-'+index;
}
return slug+suffix;
@ -491,11 +492,11 @@ Utils.defineName = (o, name) => {
Utils.performCheck = (operation, user, checkedObject, context, documentId, operationName, collectionName) => {
if (!checkedObject) {
throw new Error(Utils.encodeIntlError({id: 'app.document_not_found', value: documentId}))
throwError({ id: 'app.document_not_found', data: { documentId, operationName } });
}
if (!operation(user, checkedObject, context)) {
throw new Error(Utils.encodeIntlError({id: 'app.operation_not_allowed', value: operationName, documentId }));
throwError({ id: 'app.operation_not_allowed', data: { documentId, operationName } });
}
}

View file

@ -26,7 +26,7 @@ export const validateDocument = (document, collection, context) => {
let validationErrors = [];
// Check validity of inserted document
_.forEach(document, (value, fieldName) => {
Object.keys(document).forEach(fieldName => {
const fieldSchema = schema[fieldName];
// 1. check that the current user has permission to insert each field
@ -48,7 +48,8 @@ export const validateDocument = (document, collection, context) => {
// eslint-disable-next-line no-console
// console.log(error);
if (error.type.includes('intlError')) {
validationErrors = validationErrors.concat(JSON.parse(error.type.replace('intlError|', '')));
const intlError = JSON.parse(error.type.replace('intlError|', ''));
validationErrors = validationErrors.concat(intlError);
} else {
validationErrors.push({
id: `errors.${error.type}`,

View file

@ -127,7 +127,7 @@ const createApolloServer = (givenOptions = {}, givenConfig = {}) => {
graphQLServer.use(compression());
// GraphQL endpoint
graphQLServer.use(config.path, bodyParser.json(), graphqlExpress(async (req) => {
graphQLServer.use(config.path, bodyParser.json({ limit: getSetting('apolloServer.jsonParserOptions.limit') }), graphqlExpress(async (req) => {
let options;
let user = null;

View file

@ -137,7 +137,7 @@ Take a header object, and figure out the locale
Also accepts userLocale to indicate the current user's preferred locale
*/
export const getHeaderLocale = (headers, forceLocale, userLocale) => {
export const getHeaderLocale = (headers, userLocale) => {
let cookieLocale, acceptedLocale, locale, localeMethod;

View file

@ -28,10 +28,10 @@ to the client.
*/
import { runCallbacks, runCallbacksAsync } from '../modules/index.js';
import { createError } from 'apollo-errors';
import { validateDocument, validateData, dataToModifier, modifierToData } from '../modules/validation.js';
import { registerSetting } from '../modules/settings.js';
import { debug, debugGroup, debugGroupEnd } from '../modules/debug.js';
import { throwError } from '../modules/errors.js';
import { Connectors } from './connectors.js';
import pickBy from 'lodash/pickBy';
import clone from 'lodash/clone';
@ -57,17 +57,18 @@ export const createMutator = async ({ collection, document, data, currentUser, v
if (validate) {
const validationErrors = validateDocument(newDocument, collection, context);
let validationErrors = [];
validationErrors = validationErrors.concat(validateDocument(newDocument, collection, context));
// run validation callbacks
newDocument = await runCallbacks({ name: `${typeName.toLowerCase()}.create.validate`, iterator: newDocument, properties: { ...callbackProperties, validationErrors } });
newDocument = await runCallbacks({ name: '*.create.validate', iterator: newDocument, properties: { ...callbackProperties, validationErrors } });
validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.create.validate`, iterator: validationErrors, properties: { ...callbackProperties, document: newDocument } });
validationErrors = await runCallbacks({ name: '*.create.validate', iterator: validationErrors, properties: { ...callbackProperties, document: newDocument } });
// OpenCRUD backwards compatibility
newDocument = await runCallbacks(`${collectionName.toLowerCase()}.new.validate`, newDocument, currentUser, validationErrors);
if (validationErrors.length) {
const NewDocumentValidationError = createError('app.validation_error', {message: 'app.new_document_validation_error'});
throw new NewDocumentValidationError({data: {break: true, errors: validationErrors}});
throwError({ id: 'app.validation_error', data: {break: true, errors: validationErrors}});
}
}
@ -132,8 +133,8 @@ export const createMutator = async ({ collection, document, data, currentUser, v
// run async callbacks
// note: query for document to get fresh document with collection-hooks effects applied
await runCallbacksAsync({ name: `${typeName.toLowerCase()}.create.async`, properties: { insertedDocument, ...callbackProperties }});
await runCallbacksAsync({ name: '*.create.async', properties: { insertedDocument, ...callbackProperties }});
await runCallbacksAsync({ name: `${typeName.toLowerCase()}.create.async`, properties: { insertedDocument, document: insertedDocument, ...callbackProperties }});
await runCallbacksAsync({ name: '*.create.async', properties: { insertedDocument, document: insertedDocument, ...callbackProperties }});
// OpenCRUD backwards compatibility
await runCallbacksAsync(`${collectionName.toLowerCase()}.new.async`, insertedDocument, currentUser, collection);
@ -168,7 +169,7 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
throw new Error(`Could not find document to update for selector: ${JSON.stringify(selector)}`);
}
const callbackProperties = { document, currentUser, collection, context };
const callbackProperties = { data, document, currentUser, collection, context };
debug('');
debugGroup(`--------------- start \x1b[36m${collectionName} Update Mutator\x1b[0m ---------------`);
@ -178,11 +179,12 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
if (validate) {
let validationErrors;
let validationErrors = [];
validationErrors = validateData(data, document, collection, context);
data = await runCallbacks({ name: `${typeName.toLowerCase()}.update.validate`, iterator: data, properties: { validationErrors, ...callbackProperties }});
data = await runCallbacks({ name: '*.update.validate', iterator: data, properties: { validationErrors, ...callbackProperties }});
validationErrors = validationErrors.concat(validateData(data, document, collection, context));
validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.update.validate`, iterator: validationErrors, properties: callbackProperties });
validationErrors = await runCallbacks({ name: '*.update.validate', iterator: validationErrors, properties: callbackProperties });
// OpenCRUD backwards compatibility
data = modifierToData(await runCallbacks(`${collectionName.toLowerCase()}.edit.validate`, dataToModifier(data), document, currentUser, validationErrors));
@ -191,8 +193,7 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
console.log('// validationErrors');
// eslint-disable-next-line no-console
console.log(validationErrors);
const EditDocumentValidationError = createError('app.validation_error', { message: 'app.edit_document_validation_error' });
throw new EditDocumentValidationError({data: {break: true, errors: validationErrors}});
throwError({ id: 'app.validation_error', data: {break: true, errors: validationErrors}});
}
}
@ -257,8 +258,8 @@ export const updateMutator = async ({ collection, documentId, selector, data, se
newDocument = await runCallbacks(`${collectionName.toLowerCase()}.edit.after`, newDocument, document, currentUser);
// run async callbacks
await runCallbacksAsync({ name: `${typeName.toLowerCase()}.update.async`, properties: { newDocument, ...callbackProperties }});
await runCallbacksAsync({ name: '*.update.async', properties: { newDocument, ...callbackProperties }});
await runCallbacksAsync({ name: `${typeName.toLowerCase()}.update.async`, properties: { ...callbackProperties,newDocument, document: newDocument, oldDocument: document }});
await runCallbacksAsync({ name: '*.update.async', properties: { ...callbackProperties, newDocument, document: newDocument, oldDocument: document }});
// OpenCRUD backwards compatibility
await runCallbacksAsync(`${collectionName.toLowerCase()}.edit.async`, newDocument, document, currentUser, collection);
@ -297,12 +298,23 @@ export const deleteMutator = async ({ collection, documentId, selector, currentU
const callbackProperties = { document, currentUser, collection, context };
// if document is not trusted, run validation callbacks
if (validate) {
document = await runCallbacks({ name: `${typeName.toLowerCase()}.delete.validate`, iterator: document, properties: callbackProperties });
document = await runCallbacks({ name: '*.delete.validate', iterator: document, properties: callbackProperties });
let validationErrors = [];
validationErrors = await runCallbacks({ name: `${typeName.toLowerCase()}.delete.validate`, iterator: validationErrors, properties: callbackProperties });
validationErrors = await runCallbacks({ name: '*.delete.validate', iterator: validationErrors, properties: callbackProperties });
// OpenCRUD backwards compatibility
document = await runCallbacks(`${collectionName.toLowerCase()}.remove.validate`, document, currentUser);
if (validationErrors.length) {
// eslint-disable-next-line no-console
console.log('// validationErrors');
// eslint-disable-next-line no-console
console.log(validationErrors);
throwError({id: 'app.validation_error', data: {break: true, errors: validationErrors}});
}
}
// run onRemove step

View file

@ -1,7 +1,7 @@
import { addGraphQLSchema, addGraphQLResolvers, addGraphQLQuery } from '../modules/graphql.js';
import { Utils } from '../modules/utils';
import { getSetting } from '../modules/settings.js';
import { sourceVersion } from './source_version.js';
import { getSourceVersion } from './source_version.js';
const siteSchema = `type Site {
title: String
@ -18,7 +18,7 @@ const siteResolvers = {
title: getSetting('title'),
url: getSetting('siteUrl', Meteor.absoluteUrl()),
logoUrl: Utils.getLogoUrl(),
sourceVersion,
sourceVersion: getSourceVersion(),
};
},
},

View file

@ -8,4 +8,16 @@ or current child process.
See https://github.com/zodern/meteor-up/issues/807#issuecomment-346915622
*/
export const sourceVersion = process.env.SOURCE_VERSION || childProcess.execSync('git rev-parse HEAD').toString().trim();
export const getSourceVersion = () => {
try {
return (
process.env.SOURCE_VERSION ||
childProcess
.execSync('git rev-parse HEAD')
.toString()
.trim()
);
} catch (error) {
return null;
}
};

View file

@ -1,5 +1,4 @@
import sanitizeHtml from 'sanitize-html';
import { Connectors } from './connectors';
import { Utils } from '../modules';
Utils.sanitize = function(s) {

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:lib',
summary: 'Vulcan libraries.',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});

View file

@ -3,10 +3,9 @@
// newsletter scheduling with MailChimp
import moment from 'moment';
import { getSetting, registerSetting } from 'meteor/vulcan:core';
import { getSetting, registerSetting, throwError } from 'meteor/vulcan:core';
import Newsletters from '../../modules/collection.js';
import MailChimpNPM from 'mailchimp';
import { createError } from 'apollo-errors';
registerSetting('mailchimp', null, 'MailChimp settings');
@ -59,8 +58,7 @@ if (settings) {
} else {
name = 'subscription_failed';
}
const NewsletterError = createError(name, { message });
throw new NewsletterError({ data: {path: 'newsletter_subscribeToNewsletter', message}});
throwError({ id: name, message, data: {path: 'newsletter_subscribeToNewsletter', message}});
}
},

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:newsletter',
summary: 'Vulcan email newsletter package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,8 +10,8 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:email@1.12.10'
'vulcan:core@1.12.11',
'vulcan:email@1.12.11'
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -20,6 +20,12 @@ class Checkout extends React.Component {
};
}
handleOpen = () => {
if (this.props.onClick) {
this.props.onClick();
}
}
onToken(token) {
const {paymentActionMutation, productKey, associatedCollection, associatedDocument, callback, successCallback, errorCallback, properties, currentUser, flash, coupon} = this.props;
@ -88,6 +94,7 @@ class Checkout extends React.Component {
return (
<div className={classNames('stripe-checkout', {'checkout-loading': this.state.loading})}>
<StripeCheckout
opened={this.handleOpen}
token={this.onToken}
stripeKey={Meteor.isDevelopment || stripeSettings.alwaysUseTest ? stripeSettings.publishableKeyTest : stripeSettings.publishableKey}
ComponentClass="div"
@ -117,6 +124,7 @@ Checkout.propTypes = {
coupon: PropTypes.string,
associatedDocument: PropTypes.object,
customAmount: PropTypes.number,
onClick: PropTypes.func,
};
const WrappedCheckout = (props) => {

View file

@ -128,8 +128,10 @@ export const receiveAction = async (args) => {
Retrieve or create a Stripe customer
*/
export const getCustomer = async (user, id) => {
export const getCustomer = async (user, token) => {
const { id } = token;
let customer;
try {

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:payments',
summary: 'Vulcan payments package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -11,7 +11,7 @@ Package.onUse(function (api) {
api.use([
'promise',
'vulcan:core@1.12.10',
'vulcan:core@1.12.11',
'fourseven:scss@4.5.4',
]);

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:routing',
summary: 'Vulcan router package',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:lib@1.12.10',
'vulcan:lib@1.12.11',
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:subscribe',
summary: 'Subscribe to posts, users, etc. to be notified of new activity',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -11,14 +11,14 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:core@1.12.10',
'vulcan:core@1.12.11',
// dependencies on posts, categories are done with nested imports to reduce explicit dependencies
]);
api.use([
'vulcan:posts@1.12.10',
'vulcan:comments@1.12.10',
'vulcan:categories@1.12.10',
'vulcan:posts@1.12.11',
'vulcan:comments@1.12.11',
'vulcan:categories@1.12.11',
], {weak: true});
api.mainModule('lib/modules.js', ['client']);

View file

@ -2,7 +2,7 @@ import React from 'react';
import { registerComponent } from 'meteor/vulcan:core';
const parseUrl = value => {
return value.slice(0,4) === 'http' ? <a href={value} target="_blank">{value}</a> : value;
return value && value.toString().slice(0,4) === 'http' ? <a href={value} target="_blank">{value}</a> : value;
}
const StaticComponent = ({ value, label }) => (

View file

@ -5,18 +5,23 @@ import PropTypes from 'prop-types';
class ModalTrigger extends PureComponent {
constructor() {
super();
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.state = {
modalIsOpen: false,
};
}
openModal() {
clickHandler = () => {
if (this.props.onClick) {
this.props.onClick();
}
this.openModal();
}
openModal = () => {
this.setState({ modalIsOpen: true });
}
closeModal() {
closeModal = () => {
this.setState({ modalIsOpen: false });
}
@ -37,9 +42,9 @@ class ModalTrigger extends PureComponent {
let triggerComponent = trigger || component;
triggerComponent = triggerComponent ? (
React.cloneElement(triggerComponent, { onClick: this.openModal })
React.cloneElement(triggerComponent, { onClick: this.clickHandler })
) : (
<a href="javascript:void(0)" onClick={this.openModal}>
<a href="javascript:void(0)" onClick={this.clickHandler}>
{label}
</a>
);
@ -75,6 +80,7 @@ ModalTrigger.propTypes = {
trigger: PropTypes.object,
size: PropTypes.string,
title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
onClick: PropTypes.func,
};
registerComponent('ModalTrigger', ModalTrigger);

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:ui-bootstrap',
summary: 'Vulcan Bootstrap UI components.',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:lib@1.12.10',
'vulcan:lib@1.12.11',
'fourseven:scss@4.10.0',
]);

View file

@ -111,6 +111,7 @@ const schema = {
type: Object,
optional: true,
blackbox: true,
hidden: true,
canCreate: ['members'],
},
// // telescope-specific data, kept for backward compatibility and migration purposes

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:users',
summary: 'Vulcan permissions.',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -10,7 +10,7 @@ Package.onUse(function (api) {
api.versionsFrom('1.6.1');
api.use([
'vulcan:lib@1.12.10'
'vulcan:lib@1.12.11'
]);
api.mainModule('lib/server/main.js', 'server');

View file

@ -1,5 +1,4 @@
import { Connectors, debug, debugGroup, debugGroupEnd /* runCallbacksAsync, runCallbacks, addCallback */ } from 'meteor/vulcan:core';
import { createError } from 'apollo-errors';
import { Connectors, debug, debugGroup, debugGroupEnd, throwError /* runCallbacksAsync, runCallbacks, addCallback */ } from 'meteor/vulcan:core';
import Votes from './votes/collection.js';
import Users from 'meteor/vulcan:users';
import { recalculateScore } from './scoring.js';
@ -289,8 +288,7 @@ export const performVoteServer = async ({ documentId, document, voteType = 'upvo
const voteOptions = {document, collection, voteType, user, voteId, updateDocument};
if (!document || !user || !Users.canDo(user, `${collectionName.toLowerCase()}.${voteType}`)) {
const VoteError = createError('voting.no_permission', {message: 'voting.no_permission'});
throw new VoteError();
throwError({ id: 'voting.no_permission' });
}
const existingVote = await hasVotedServer({document, voteType, user});

View file

@ -1,7 +1,7 @@
Package.describe({
name: 'vulcan:voting',
summary: 'Vulcan scoring package.',
version: '1.12.10',
version: '1.12.11',
git: 'https://github.com/VulcanJS/Vulcan.git'
});
@ -11,8 +11,8 @@ Package.onUse(function (api) {
api.use([
'fourseven:scss@4.10.0',
'vulcan:core@1.12.10',
'vulcan:i18n@1.12.10',
'vulcan:core@1.12.11',
'vulcan:i18n@1.12.11',
], ['client', 'server']);
api.mainModule('lib/server/main.js', 'server');