diff --git a/.bithoundrc b/.bithoundrc new file mode 100644 index 00000000000..3986566a291 --- /dev/null +++ b/.bithoundrc @@ -0,0 +1,76 @@ +{ + "ignore": [ + "**/deps/**", + "**/node_modules/**", + "**/thirdparty/**", + "**/third_party/**", + "**/vendor/**", + "**/**-min-**", + "**/**-min.**", + "**/**.min.**", + "**/**jquery.?(ui|effects)-*.*.?(*).?(cs|j)s", + "**/**jquery-*.*.?(*).?(cs|j)s", + "**/prototype?(*).js", + "**/mootools*.*.*.js", + "**/dojo.js", + "**/MochiKit.js", + "**/yahoo-*.js", + "**/yui*.js", + "**/ckeditor*.js", + "**/tiny_mce*.js", + "**/tiny_mce/?(langs|plugins|themes|utils)/**", + "**/MathJax/**", + "**/shBrush*.js", + "**/shCore.js", + "**/shLegacy.js", + "**/modernizr.custom.?(*).js", + "**/knockout-*.*.*.debug.js", + "**/extjs/*.js", + "**/extjs/*.xml", + "**/extjs/*.txt", + "**/extjs/*.html", + "**/extjs/*.properties", + "**/extjs/.sencha", + "**/extjs/docs/**", + "**/extjs/builds/**", + "**/extjs/cmd/**", + "**/extjs/examples/**", + "**/extjs/locale/**", + "**/extjs/packages/**", + "**/extjs/plugins/**", + "**/extjs/resources/**", + "**/extjs/src/**", + "**/extjs/welcome/**", + "bower_components/**" + ], + "test": [ + "**/test/**", + "**/tests/**", + "**/spec/**", + "**/specs/**", + "**/**.app-test.**" + ], + "critics": { + "wc": {"limit": 5000}, + "lint": {"engine": "eslint"} + }, + "dependencies": { + "mute": [ + "wdio-mocha-framework" + ], + "unused-ignores": [ + "jquery", + "sweetalert2", + "font-awesome", + "bcrypt", + "react-addons-pure-render-mixin", + "url", + "griddle-react", + "tether-tooltip", + "react-textarea-autosize", + "react-color", + "react-autosuggest", + "meteor-node-stubs" + ] + } +} diff --git a/.codeclimate.yml b/.codeclimate.yml index 1d9b1639232..438fa8df732 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -6,18 +6,17 @@ exclude_paths: - ".codeclimate.yml" engines: eslint: - enabled: true - channel: "eslint-2" + enabled: false csslint: enabled: false duplication: - enabled: true + enabled: false config: languages: javascript: mass_threshold: 150 fixme: - enabled: true + enabled: false config: strings: - FIXME diff --git a/.eslintignore b/.eslintignore index ca441ef1b09..c218494866f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,5 @@ +# things to ignore in lint + *.min.* +server/plugins.js +client/plugins.js diff --git a/.eslintrc b/.eslintrc index 997b9dd6a02..361695d2172 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "parser": "babel-eslint", // for support of spread operator + "parser": "babel-eslint", // now for the support of allowImportExportEverywhere "env": { "browser": true, "node": true, @@ -7,7 +7,8 @@ }, "parserOptions": { "ecmaVersion": 6, - "sourceType": "module" + "sourceType": "module", + "allowImportExportEverywhere": true }, "plugins": ["react"], "ecmaFeatures": { @@ -28,14 +29,14 @@ "templateStrings": true, "jsx": true }, - // NOTE: This is ESLINT v1 syntax because Code Climate v2 seg faults. + // NOTE: We're now using eslint-3 "rules": { /** * Strict mode * babel inserts "use strict"; for us * http://eslint.org/docs/rules/strict */ - "strict": [2, "never"], + "strict": 0, /** * ES6 @@ -83,7 +84,7 @@ * JSX / React */ "jsx-quotes": [2, "prefer-double"], // http://eslint.org/docs/rules/jsx-quotes - /*"react/no-deprecated": 1,*/ + "react/no-deprecated": 1, "react/display-name": 1, "react/forbid-prop-types": 1, "react/jsx-boolean-value": [1, "always"], @@ -93,11 +94,11 @@ "react/jsx-max-props-per-line": [1, { "maximum": 4 }], - /*"react/jsx-no-bind": 1,*/ + "react/jsx-no-bind": 1, "react/jsx-no-duplicate-props": 1, "react/jsx-no-literals": 1, "react/jsx-no-undef": 1, - "react/jsx-sort-prop-types": 1, + "react/sort-prop-types": 1, "react/jsx-sort-props": 1, "react/jsx-uses-react": 1, "react/jsx-uses-vars": 1, @@ -111,15 +112,16 @@ "react/prefer-es6-class": 1, "react/prop-types": 1, "react/react-in-jsx-scope": 0, - "react/require-extension": 1, + "react/require-extension": "off", "react/self-closing-comp": 1, "react/sort-comp": 1, - "react/wrap-multilines": 1, /** * Best practices */ - "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return + "consistent-return": [1, { // http://eslint.org/docs/rules/consistent-return + "treatUndefinedAsUnspecified": false + }], "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly "default-case": 2, // http://eslint.org/docs/rules/default-case "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation @@ -127,6 +129,10 @@ }], "eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq "guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in + "prefer-const": [1, { + "destructuring": "any", + "ignoreReadBeforeAssign": false + }], "no-caller": 2, // http://eslint.org/docs/rules/no-caller "no-else-return": 2, // http://eslint.org/docs/rules/no-else-return "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null @@ -158,11 +164,11 @@ "vars-on-top": 2, // http://eslint.org/docs/rules/vars-on-top "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife "yoda": 2, // http://eslint.org/docs/rules/yoda - "max-len": [2, 160, 2, { + "max-len": [1, 160, 2, { "ignoreComments": true, "ignoreUrls": true }], // http://eslint.org/docs/rules/max-len - "valid-jsdoc": 2, // http://eslint.org/docs/rules/valid-jsdoc + "valid-jsdoc": 1, // http://eslint.org/docs/rules/valid-jsdoc "quote-props": [2, "consistent-as-needed"], // http://eslint.org/docs/rules/quote-props /** * Style diff --git a/.gitignore b/.gitignore index f364c229162..15517295466 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ private/custom/* imports/plugins/custom/* !imports/plugins/custom/.gitkeep + +.reaction/config.json diff --git a/.meteor/.finished-upgraders b/.meteor/.finished-upgraders index 3e712bc5a9f..a541808f2b3 100644 --- a/.meteor/.finished-upgraders +++ b/.meteor/.finished-upgraders @@ -13,3 +13,4 @@ notices-for-facebook-graph-api-2 1.3.0-split-minifiers-package 1.3.5-remove-old-dev-bundle-link 1.4.0-remove-old-dev-bundle-link +1.4.1-add-shell-server-package diff --git a/.meteor/packages b/.meteor/packages index 3b6f05b393a..39f932d0f4c 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -10,38 +10,39 @@ meteor-base@1.0.4 # Packages every Meteor app needs to have mobile-experience@1.0.4 # Packages for a great mobile UX blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views -es5-shim@4.6.13 # ECMAScript 5 compatibility for older browsers. -ecmascript@0.5.7 # Enable ECMAScript2015+ syntax in app code +es5-shim@4.6.14 # ECMAScript 5 compatibility for older browsers. +ecmascript@0.5.8 # Enable ECMAScript2015+ syntax in app code audit-argument-checks@1.0.7 # ensure meteor method argument validation browser-policy@1.0.9 # security-related policies enforced by newer browsers juliancwirko:postcss # CSS post-processing plugin (replaces standard-minifier-css) -standard-minifier-js@1.1.8 # a minifier plugin used for Meteor apps by default +standard-minifier-js@1.2.0 # a minifier plugin used for Meteor apps by default session@1.1.6 # ReactiveDict whose contents are preserved across Hot Code Push tracker@1.1.0 # Meteor transparent reactive programming library -mongo@1.1.10 +mongo@1.1.11 random@1.0.10 reactive-var@1.0.10 reactive-dict@1.1.8 check@1.2.3 -http@1.2.8 +http@1.2.9 ddp-rate-limiter@1.0.5 underscore@1.0.9 -logging@1.1.14 +logging@1.1.15 reload@1.1.10 ejson@1.0.12 -less@2.7.4 -email@1.1.16 +less@2.7.5 +email@1.1.17 service-configuration@1.0.10 amplify mdg:validated-method +shell-server # Meteor Auth Packages -accounts-base@1.2.9 -accounts-password@1.2.12 +accounts-base@1.2.11 +accounts-password@1.3.0 accounts-facebook@1.0.10 accounts-google@1.0.10 accounts-twitter@1.1.11 -oauth-encryption@1.1.13 +oauth-encryption@1.2.0 # accounts-github # accounts-weibo # accounts-oauth diff --git a/.meteor/release b/.meteor/release index c85944c1dba..30b2c590e30 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -METEOR@1.4.0.1 +METEOR@1.4.1 diff --git a/.meteor/versions b/.meteor/versions index 05273e8a078..f20f1d612e4 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -1,8 +1,8 @@ -accounts-base@1.2.10 +accounts-base@1.2.11 accounts-facebook@1.0.10 accounts-google@1.0.10 accounts-oauth@1.1.13 -accounts-password@1.2.14 +accounts-password@1.3.0 accounts-twitter@1.1.11 alanning:roles@1.2.15 aldeed:autoform@5.8.1 @@ -16,8 +16,8 @@ allow-deny@1.0.5 amplify@1.0.0 audit-argument-checks@1.0.7 autoupdate@1.3.11 -babel-compiler@6.9.0 -babel-runtime@0.1.10 +babel-compiler@6.9.1 +babel-runtime@0.1.11 base64@1.0.9 binary-heap@1.0.9 blaze@2.1.8 @@ -28,7 +28,7 @@ browser-policy@1.0.9 browser-policy-common@1.0.10 browser-policy-content@1.0.11 browser-policy-framing@1.0.11 -caching-compiler@1.1.6 +caching-compiler@1.1.7 caching-html-compiler@1.0.6 callback-hook@1.0.9 cfs:access-point@0.1.49 @@ -53,29 +53,29 @@ cfs:upload-http@0.0.20 cfs:worker@0.1.4 check@1.2.3 chuangbo:cookie@1.1.0 -coffeescript@1.2.3 +coffeescript@1.2.4 dburles:factory@1.1.0 ddp@1.2.5 -ddp-client@1.3.0 +ddp-client@1.3.1 ddp-common@1.2.6 ddp-rate-limiter@1.0.5 -ddp-server@1.3.9 +ddp-server@1.3.10 deps@1.0.12 diff-sequence@1.0.6 dispatch:mocha@0.0.9 -ecmascript@0.5.7 -ecmascript-runtime@0.3.13 +ecmascript@0.5.8 +ecmascript-runtime@0.3.14 ejson@1.0.12 -email@1.1.16 -es5-shim@4.6.13 -facebook@1.2.8 +email@1.1.17 +es5-shim@4.6.14 +facebook@1.2.9 fastclick@1.0.12 geojson-utils@1.0.9 -google@1.1.13 +google@1.1.14 hot-code-push@1.0.4 html-tools@1.0.10 htmljs@1.0.10 -http@1.2.8 +http@1.2.9 id-map@1.0.8 jeremy:stripe@1.6.0 jparker:crypto-core@0.1.0 @@ -89,35 +89,35 @@ kadira:blaze-layout@2.3.0 kadira:dochead@1.5.0 kadira:flow-router-ssr@3.13.0 launch-screen@1.0.12 -less@2.7.4 +less@2.7.5 livedata@1.0.18 localstorage@1.0.11 -logging@1.1.14 -matb33:collection-hooks@0.8.3 +logging@1.1.15 +matb33:collection-hooks@0.8.4 mdg:validated-method@1.1.0 mdg:validation-error@0.5.1 -meteor@1.2.16 +meteor@1.2.17 meteor-base@1.0.4 -meteorhacks:fast-render@2.14.0 +meteorhacks:fast-render@2.16.0 meteorhacks:inject-data@2.0.0 meteorhacks:meteorx@1.4.1 meteorhacks:picker@1.0.3 meteorhacks:ssr@2.2.0 meteorhacks:subs-manager@1.6.4 -minifier-css@1.2.13 -minifier-js@1.2.13 +minifier-css@1.2.14 +minifier-js@1.2.14 minimongo@1.0.17 mobile-experience@1.0.4 mobile-status-bar@1.0.12 -modules@0.7.5 -modules-runtime@0.7.5 +modules@0.7.6 +modules-runtime@0.7.6 momentjs:moment@2.14.4 -mongo@1.1.10 +mongo@1.1.11 mongo-id@1.0.5 mongo-livedata@1.0.12 mrt:later@1.6.1 -npm-bcrypt@0.8.7_1 -npm-mongo@1.5.45 +npm-bcrypt@0.9.1 +npm-mongo@1.5.46 oauth@1.1.11 oauth-encryption@1.2.0 oauth1@1.1.10 @@ -128,7 +128,7 @@ ordered-dict@1.0.8 practicalmeteor:chai@2.1.0_1 practicalmeteor:mocha-core@1.0.1 practicalmeteor:sinon@1.14.1_2 -promise@0.8.3 +promise@0.8.4 raix:eventemitter@0.1.3 raix:ui-dropped-event@0.0.7 random@1.0.10 @@ -143,11 +143,12 @@ routepolicy@1.0.11 service-configuration@1.0.10 session@1.1.6 sha@1.0.8 +shell-server@0.2.1 spacebars@1.0.12 spacebars-compiler@1.0.12 srp@1.0.9 -standard-minifier-js@1.1.8 -templating@1.2.13 +standard-minifier-js@1.2.0 +templating@1.2.14 templating-tools@1.0.4 tmeasday:check-npm-versions@0.3.1 tmeasday:publish-counts@0.7.3 @@ -157,5 +158,5 @@ ui@1.0.11 underscore@1.0.9 url@1.0.10 vsivsi:job-collection@1.4.0 -webapp@1.3.10 +webapp@1.3.11 webapp-hashing@1.0.9 diff --git a/README.md b/README.md index 2ca04c6a8bd..1edb4a1e50e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Reaction [![Circle CI](https://circleci.com/gh/reactioncommerce/reaction.svg?style=svg)](https://circleci.com/gh/reactioncommerce/reaction) [![Code Climate](https://codeclimate.com/github/reactioncommerce/reaction/badges/gpa.svg)](https://codeclimate.com/github/reactioncommerce/reaction) [![bitHound Code](https://www.bithound.io/github/reactioncommerce/reaction/badges/code.svg)](https://www.bithound.io/github/reactioncommerce/reaction) +# Reaction -[![Gitter](https://badges.gitter.im/JoinChat.svg)](https://gitter.im/reactioncommerce/reaction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![bitHound Overall Score](https://www.bithound.io/github/reactioncommerce/reaction/badges/score.svg)](https://www.bithound.io/github/reactioncommerce/reaction) [![bitHound Dev Dependencies](https://www.bithound.io/github/reactioncommerce/reaction/badges/devDependencies.svg)](https://www.bithound.io/github/reactioncommerce/reaction/9a858eb459d7260d5ae59124c2b364bc791a3e70/dependencies/npm) [![bitHound Code](https://www.bithound.io/github/reactioncommerce/reaction/badges/code.svg)](https://www.bithound.io/github/reactioncommerce/reaction) [![Code Climate](https://codeclimate.com/github/reactioncommerce/reaction/badges/gpa.svg)](https://codeclimate.com/github/reactioncommerce/reaction) [![Circle CI](https://circleci.com/gh/reactioncommerce/reaction.svg?style=svg)](https://circleci.com/gh/reactioncommerce/reaction) [![Gitter](https://badges.gitter.im/JoinChat.svg)](https://gitter.im/reactioncommerce/reaction?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Reaction is a modern reactive, real-time event driven ecommerce platform. @@ -13,6 +13,8 @@ Reaction is built with JavaScript (ES6), Meteor, Node.js and works nicely with D ```bash npm install -g reaction-cli reaction init +cd reaction +reaction ``` > **reaction-cli** requires a recent version of [npm](https://www.npmjs.com/). @@ -28,8 +30,6 @@ n stable Additional setup options, such as how to set the default credentials, installation without `reaction-cli`, and [Meteor](https://www.meteor.com/install) installation can be found in the [installation](https://docs.reactioncommerce.com/reaction-docs/development/installation) and [configuration documentation](https://docs.reactioncommerce.com/reaction-docs/development/configuration). -_Note: When using a standalone MongoDB server, make sure you are using version 2.6 or later._ - ## Docs Installation, configuration and development documentation is available on [docs.reactioncommerce.com](https://docs.reactioncommerce.com/) diff --git a/client/jquery-ui.css b/client/jquery-ui.css deleted file mode 100644 index 18d36c75a61..00000000000 --- a/client/jquery-ui.css +++ /dev/null @@ -1,955 +0,0 @@ -/*! jQuery UI - v1.10.3 - 2013-12-08 -* http://jqueryui.com -* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Helvetica%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=2px&bgColorHeader=dddddd&bgTextureHeader=highlight_soft&bgImgOpacityHeader=50&borderColorHeader=dddddd&fcHeader=444444&iconColorHeader=0073ea&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=dddddd&fcContent=444444&iconColorContent=ff0084&bgColorDefault=f6f6f6&bgTextureDefault=highlight_soft&bgImgOpacityDefault=100&borderColorDefault=dddddd&fcDefault=0073ea&iconColorDefault=666666&bgColorHover=0073ea&bgTextureHover=highlight_soft&bgImgOpacityHover=25&borderColorHover=0073ea&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=dddddd&fcActive=ff0084&iconColorActive=454545&bgColorHighlight=ffffff&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=cccccc&fcHighlight=444444&iconColorHighlight=0073ea&bgColorError=ffffff&bgTextureError=flat&bgImgOpacityError=55&borderColorError=ff0084&fcError=222222&iconColorError=ff0084&bgColorOverlay=eeeeee&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=80&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=60&thicknessShadow=4px&offsetTopShadow=-4px&offsetLeftShadow=-4px&cornerRadiusShadow=0px -* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { - display: none; -} -.ui-helper-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.ui-helper-reset { - margin: 0; - padding: 0; - border: 0; - outline: 0; - line-height: 1.3; - text-decoration: none; - font-size: 100%; - list-style: none; -} -.ui-helper-clearfix:before, -.ui-helper-clearfix:after { - content: ""; - display: table; - border-collapse: collapse; -} -.ui-helper-clearfix:after { - clear: both; -} -.ui-helper-clearfix { - min-height: 0; /* support: IE7 */ -} -.ui-helper-zfix { - width: 100%; - height: 100%; - top: 0; - left: 0; - position: absolute; - opacity: 0; - filter:Alpha(Opacity=0); -} - -.ui-front { - z-index: 100; -} - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { - cursor: default !important; -} - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - display: block; - text-indent: -99999px; - overflow: hidden; - background-repeat: no-repeat; -} - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; -} -.ui-resizable { - position: relative; -} -.ui-resizable-handle { - position: absolute; - font-size: 0.1px; - display: block; -} -.ui-resizable-disabled .ui-resizable-handle, -.ui-resizable-autohide .ui-resizable-handle { - display: none; -} -.ui-resizable-n { - cursor: n-resize; - height: 7px; - width: 100%; - top: -5px; - left: 0; -} -.ui-resizable-s { - cursor: s-resize; - height: 7px; - width: 100%; - bottom: -5px; - left: 0; -} -.ui-resizable-e { - cursor: e-resize; - width: 7px; - right: -5px; - top: 0; - height: 100%; -} -.ui-resizable-w { - cursor: w-resize; - width: 7px; - left: -5px; - top: 0; - height: 100%; -} -.ui-resizable-se { - cursor: se-resize; - width: 12px; - height: 12px; - right: 1px; - bottom: 1px; -} -.ui-resizable-sw { - cursor: sw-resize; - width: 9px; - height: 9px; - left: -5px; - bottom: -5px; -} -.ui-resizable-nw { - cursor: nw-resize; - width: 9px; - height: 9px; - left: -5px; - top: -5px; -} -.ui-resizable-ne { - cursor: ne-resize; - width: 9px; - height: 9px; - right: -5px; - top: -5px; -} -.ui-autocomplete { - position: absolute; - top: 0; - left: 0; - cursor: default; -} -.ui-button { - display: inline-block; - position: relative; - padding: 0; - line-height: normal; - margin-right: .1em; - cursor: pointer; - vertical-align: middle; - text-align: center; - overflow: visible; /* removes extra width in IE */ -} -.ui-button, -.ui-button:link, -.ui-button:visited, -.ui-button:hover, -.ui-button:active { - text-decoration: none; -} -/* to make room for the icon, a width needs to be set here */ -.ui-button-icon-only { - width: 2.2em; -} -/* button elements seem to need a little more width */ -button.ui-button-icon-only { - width: 2.4em; -} -.ui-button-icons-only { - width: 3.4em; -} -button.ui-button-icons-only { - width: 3.7em; -} - -/* button text element */ -.ui-button .ui-button-text { - display: block; - line-height: normal; -} -.ui-button-text-only .ui-button-text { - padding: .4em 1em; -} -.ui-button-icon-only .ui-button-text, -.ui-button-icons-only .ui-button-text { - padding: .4em; - text-indent: -9999999px; -} -.ui-button-text-icon-primary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 1em .4em 2.1em; -} -.ui-button-text-icon-secondary .ui-button-text, -.ui-button-text-icons .ui-button-text { - padding: .4em 2.1em .4em 1em; -} -.ui-button-text-icons .ui-button-text { - padding-left: 2.1em; - padding-right: 2.1em; -} -/* no icon support for input elements, provide padding by default */ -input.ui-button { - padding: .4em 1em; -} - -/* button icon element(s) */ -.ui-button-icon-only .ui-icon, -.ui-button-text-icon-primary .ui-icon, -.ui-button-text-icon-secondary .ui-icon, -.ui-button-text-icons .ui-icon, -.ui-button-icons-only .ui-icon { - position: absolute; - top: 50%; - margin-top: -8px; -} -.ui-button-icon-only .ui-icon { - left: 50%; - margin-left: -8px; -} -.ui-button-text-icon-primary .ui-button-icon-primary, -.ui-button-text-icons .ui-button-icon-primary, -.ui-button-icons-only .ui-button-icon-primary { - left: .5em; -} -.ui-button-text-icon-secondary .ui-button-icon-secondary, -.ui-button-text-icons .ui-button-icon-secondary, -.ui-button-icons-only .ui-button-icon-secondary { - right: .5em; -} - -/* button sets */ -.ui-buttonset { - margin-right: 7px; -} -.ui-buttonset .ui-button { - margin-left: 0; - margin-right: -.3em; -} - -/* workarounds */ -/* reset extra padding in Firefox, see h5bp.com/l */ -input.ui-button::-moz-focus-inner, -button.ui-button::-moz-focus-inner { - border: 0; - padding: 0; -} -.ui-datepicker { - width: 17em; - padding: .2em .2em 0; - display: none; -} -.ui-datepicker .ui-datepicker-header { - position: relative; - padding: .2em 0; -} -.ui-datepicker .ui-datepicker-prev, -.ui-datepicker .ui-datepicker-next { - position: absolute; - top: 2px; - width: 1.8em; - height: 1.8em; -} -.ui-datepicker .ui-datepicker-prev-hover, -.ui-datepicker .ui-datepicker-next-hover { - top: 1px; -} -.ui-datepicker .ui-datepicker-prev { - left: 2px; -} -.ui-datepicker .ui-datepicker-next { - right: 2px; -} -.ui-datepicker .ui-datepicker-prev-hover { - left: 1px; -} -.ui-datepicker .ui-datepicker-next-hover { - right: 1px; -} -.ui-datepicker .ui-datepicker-prev span, -.ui-datepicker .ui-datepicker-next span { - display: block; - position: absolute; - left: 50%; - margin-left: -8px; - top: 50%; - margin-top: -8px; -} -.ui-datepicker .ui-datepicker-title { - margin: 0 2.3em; - line-height: 1.8em; - text-align: center; -} -.ui-datepicker .ui-datepicker-title select { - font-size: 1em; - margin: 1px 0; -} -.ui-datepicker select.ui-datepicker-month-year { - width: 100%; -} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { - width: 49%; -} -.ui-datepicker table { - width: 100%; - font-size: .9em; - border-collapse: collapse; - margin: 0 0 .4em; -} -.ui-datepicker th { - padding: .7em .3em; - text-align: center; - font-weight: bold; - border: 0; -} -.ui-datepicker td { - border: 0; - padding: 1px; -} -.ui-datepicker td span, -.ui-datepicker td a { - display: block; - padding: .2em; - text-align: right; - text-decoration: none; -} -.ui-datepicker .ui-datepicker-buttonpane { - background-image: none; - margin: .7em 0 0 0; - padding: 0 .2em; - border-left: 0; - border-right: 0; - border-bottom: 0; -} -.ui-datepicker .ui-datepicker-buttonpane button { - float: right; - margin: .5em .2em .4em; - cursor: pointer; - padding: .2em .6em .3em .6em; - width: auto; - overflow: visible; -} -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { - float: left; -} - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { - width: auto; -} -.ui-datepicker-multi .ui-datepicker-group { - float: left; -} -.ui-datepicker-multi .ui-datepicker-group table { - width: 95%; - margin: 0 auto .4em; -} -.ui-datepicker-multi-2 .ui-datepicker-group { - width: 50%; -} -.ui-datepicker-multi-3 .ui-datepicker-group { - width: 33.3%; -} -.ui-datepicker-multi-4 .ui-datepicker-group { - width: 25%; -} -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { - border-left-width: 0; -} -.ui-datepicker-multi .ui-datepicker-buttonpane { - clear: left; -} -.ui-datepicker-row-break { - clear: both; - width: 100%; - font-size: 0; -} - -/* RTL support */ -.ui-datepicker-rtl { - direction: rtl; -} -.ui-datepicker-rtl .ui-datepicker-prev { - right: 2px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next { - left: 2px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-prev:hover { - right: 1px; - left: auto; -} -.ui-datepicker-rtl .ui-datepicker-next:hover { - left: 1px; - right: auto; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane { - clear: right; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button { - float: left; -} -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, -.ui-datepicker-rtl .ui-datepicker-group { - float: right; -} -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { - border-right-width: 0; - border-left-width: 1px; -} -.ui-dialog { - position: absolute; - top: 0; - left: 0; - padding: .2em; - outline: 0; -} -.ui-dialog .ui-dialog-titlebar { - padding: .4em 1em; - position: relative; -} -.ui-dialog .ui-dialog-title { - float: left; - margin: .1em 0; - white-space: nowrap; - width: 90%; - overflow: hidden; - text-overflow: ellipsis; -} -.ui-dialog .ui-dialog-titlebar-close { - position: absolute; - right: .3em; - top: 50%; - width: 21px; - margin: -10px 0 0 0; - padding: 1px; - height: 20px; -} -.ui-dialog .ui-dialog-content { - position: relative; - border: 0; - padding: .5em 1em; - background: none; - overflow: auto; -} -.ui-dialog .ui-dialog-buttonpane { - text-align: left; - border-width: 1px 0 0 0; - background-image: none; - margin-top: .5em; - padding: .3em 1em .5em .4em; -} -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { - float: right; -} -.ui-dialog .ui-dialog-buttonpane button { - margin: .5em .4em .5em 0; - cursor: pointer; -} -.ui-dialog .ui-resizable-se { - width: 12px; - height: 12px; - right: -5px; - bottom: -5px; - background-position: 16px 16px; -} -.ui-draggable .ui-dialog-titlebar { - cursor: move; -} -.ui-menu { - list-style: none; - padding: 2px; - margin: 0; - display: block; - outline: none; -} -.ui-menu .ui-menu { - margin-top: -3px; - position: absolute; -} -.ui-menu .ui-menu-item { - margin: 0; - padding: 0; - width: 100%; - /* support: IE10, see #8844 */ - list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); -} -.ui-menu .ui-menu-divider { - margin: 5px -2px 5px -2px; - height: 0; - font-size: 0; - line-height: 0; - border-width: 1px 0 0 0; -} -.ui-menu .ui-menu-item a { - text-decoration: none; - display: block; - padding: 2px .4em; - line-height: 1.5; - min-height: 0; /* support: IE7 */ - font-weight: normal; -} -.ui-menu .ui-menu-item a.ui-state-focus, -.ui-menu .ui-menu-item a.ui-state-active { - font-weight: normal; - margin: -1px; -} - -.ui-menu .ui-state-disabled { - font-weight: normal; - margin: .4em 0 .2em; - line-height: 1.5; -} -.ui-menu .ui-state-disabled a { - cursor: default; -} - -/* icon support */ -.ui-menu-icons { - position: relative; -} -.ui-menu-icons .ui-menu-item a { - position: relative; - padding-left: 2em; -} - -/* left-aligned */ -.ui-menu .ui-icon { - position: absolute; - top: .2em; - left: .2em; -} - -/* right-aligned */ -.ui-menu .ui-menu-icon { - position: static; - float: right; -} - -/* Component containers -----------------------------------*/ -.ui-widget { - font-family: Helvetica,Arial,sans-serif; - font-size: 1.1em; -} -.ui-widget .ui-widget { - font-size: 1em; -} -.ui-widget input, -.ui-widget select, -.ui-widget textarea, -.ui-widget button { - font-family: Helvetica,Arial,sans-serif; - font-size: 1em; -} -.ui-widget-content { - border: 1px solid #dddddd; - background: #ffffff url(/images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; - color: #444444; -} -.ui-widget-content a { - color: #444444; -} -.ui-widget-header { - border: 1px solid #dddddd; - background: #dddddd url(/images/ui-bg_highlight-soft_50_dddddd_1x100.png) 50% 50% repeat-x; - color: #444444; - font-weight: bold; -} -.ui-widget-header a { - color: #444444; -} - -/* Interaction states -----------------------------------*/ -.ui-state-default, -.ui-widget-content .ui-state-default, -.ui-widget-header .ui-state-default { - border: 1px solid #dddddd; - background: #f6f6f6 url(/images/ui-bg_highlight-soft_100_f6f6f6_1x100.png) 50% 50% repeat-x; - font-weight: bold; - color: #0073ea; -} -.ui-state-default a, -.ui-state-default a:link, -.ui-state-default a:visited { - color: #0073ea; - text-decoration: none; -} -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, -.ui-widget-header .ui-state-focus { - border: 1px solid #0073ea; - background: #0073ea url(/images/ui-bg_highlight-soft_25_0073ea_1x100.png) 50% 50% repeat-x; - font-weight: bold; - color: #ffffff; -} -.ui-state-hover a, -.ui-state-hover a:hover, -.ui-state-hover a:link, -.ui-state-hover a:visited { - color: #ffffff; - text-decoration: none; -} -.ui-state-active, -.ui-widget-content .ui-state-active, -.ui-widget-header .ui-state-active { - border: 1px solid #dddddd; - background: #ffffff url(/images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; - font-weight: bold; - color: #ff0084; -} -.ui-state-active a, -.ui-state-active a:link, -.ui-state-active a:visited { - color: #ff0084; - text-decoration: none; -} - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, -.ui-widget-header .ui-state-highlight { - border: 1px solid #cccccc; - background: #ffffff url(/images/ui-bg_flat_55_ffffff_40x100.png) 50% 50% repeat-x; - color: #444444; -} -.ui-state-highlight a, -.ui-widget-content .ui-state-highlight a, -.ui-widget-header .ui-state-highlight a { - color: #444444; -} -.ui-state-error, -.ui-widget-content .ui-state-error, -.ui-widget-header .ui-state-error { - border: 1px solid #ff0084; - background: #ffffff url(/images/ui-bg_flat_55_ffffff_40x100.png) 50% 50% repeat-x; - color: #222222; -} -.ui-state-error a, -.ui-widget-content .ui-state-error a, -.ui-widget-header .ui-state-error a { - color: #222222; -} -.ui-state-error-text, -.ui-widget-content .ui-state-error-text, -.ui-widget-header .ui-state-error-text { - color: #222222; -} -.ui-priority-primary, -.ui-widget-content .ui-priority-primary, -.ui-widget-header .ui-priority-primary { - font-weight: bold; -} -.ui-priority-secondary, -.ui-widget-content .ui-priority-secondary, -.ui-widget-header .ui-priority-secondary { - opacity: .7; - filter:Alpha(Opacity=70); - font-weight: normal; -} -.ui-state-disabled, -.ui-widget-content .ui-state-disabled, -.ui-widget-header .ui-state-disabled { - opacity: .35; - filter:Alpha(Opacity=35); - background-image: none; -} -.ui-state-disabled .ui-icon { - filter:Alpha(Opacity=35); /* For IE8 - See #6059 */ -} - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { - width: 16px; - height: 16px; -} -.ui-icon, -.ui-widget-content .ui-icon { - background-image: url(/images/ui-icons_ff0084_256x240.png); -} -.ui-widget-header .ui-icon { - background-image: url(/images/ui-icons_0073ea_256x240.png); -} -.ui-state-default .ui-icon { - background-image: url(/images/ui-icons_666666_256x240.png); -} -.ui-state-hover .ui-icon, -.ui-state-focus .ui-icon { - background-image: url(/images/ui-icons_ffffff_256x240.png); -} -.ui-state-active .ui-icon { - background-image: url(/images/ui-icons_454545_256x240.png); -} -.ui-state-highlight .ui-icon { - background-image: url(/images/ui-icons_0073ea_256x240.png); -} -.ui-state-error .ui-icon, -.ui-state-error-text .ui-icon { - background-image: url(/images/ui-icons_ff0084_256x240.png); -} - -/* positioning */ -.ui-icon-blank { background-position: 16px 16px; } -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-on { background-position: -96px -144px; } -.ui-icon-radio-off { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, -.ui-corner-top, -.ui-corner-left, -.ui-corner-tl { - border-top-left-radius: 2px; -} -.ui-corner-all, -.ui-corner-top, -.ui-corner-right, -.ui-corner-tr { - border-top-right-radius: 2px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-left, -.ui-corner-bl { - border-bottom-left-radius: 2px; -} -.ui-corner-all, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-br { - border-bottom-right-radius: 2px; -} - -/* Overlays */ -.ui-widget-overlay { - background: #eeeeee url(/images/ui-bg_flat_0_eeeeee_40x100.png) 50% 50% repeat-x; - opacity: .8; - filter: Alpha(Opacity=80); -} -.ui-widget-shadow { - margin: -4px 0 0 -4px; - padding: 4px; - background: #aaaaaa url(/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; - opacity: .6; - filter: Alpha(Opacity=60); - border-radius: 0px; -} diff --git a/client/modules/accounts/helpers/templates.js b/client/modules/accounts/helpers/templates.js index 5fe6700133d..2a53d05d986 100644 --- a/client/modules/accounts/helpers/templates.js +++ b/client/modules/accounts/helpers/templates.js @@ -59,18 +59,18 @@ Template.registerHelper("fName", function (displayUser) { if (user && user.services) { const username = (function () { switch (false) { - case !user.services.twitter: - return user.services.twitter.first_name; - case !user.services.google: - return user.services.google.given_name; - case !user.services.facebook: - return user.services.facebook.first_name; - case !user.services.instagram: - return user.services.instagram.first_name; - case !user.services.pinterest: - return user.services.pinterest.first_name; - default: - return i18next.t("accountsUI.guest", {defaultValue: "Guest"}); + case !user.services.twitter: + return user.services.twitter.first_name; + case !user.services.google: + return user.services.google.given_name; + case !user.services.facebook: + return user.services.facebook.first_name; + case !user.services.instagram: + return user.services.instagram.first_name; + case !user.services.pinterest: + return user.services.pinterest.first_name; + default: + return i18next.t("accountsUI.guest", {defaultValue: "Guest"}); } })(); return username; diff --git a/client/modules/accounts/templates/addressBook/add/add.js b/client/modules/accounts/templates/addressBook/add/add.js index 88ca8c36578..27750701db0 100644 --- a/client/modules/accounts/templates/addressBook/add/add.js +++ b/client/modules/accounts/templates/addressBook/add/add.js @@ -6,9 +6,9 @@ import { Template } from "meteor/templating"; Template.addressBookAdd.helpers({ thisAddress: function () { - let thisAddress = {}; + const thisAddress = {}; // admin should receive his account - let account = Collections.Accounts.findOne({ + const account = Collections.Accounts.findOne({ userId: Meteor.userId() }); if (account) { @@ -38,7 +38,7 @@ Template.addressBookAdd.helpers({ }, hasAddressBookEntries: function () { - let account = Collections.Accounts.findOne({ + const account = Collections.Accounts.findOne({ userId: Meteor.userId() }); if (account) { @@ -72,7 +72,7 @@ AutoForm.hooks({ addressBookAddForm: { onSubmit: function (insertDoc) { this.event.preventDefault(); - let addressBook = $(this.template.firstNode).closest(".address-book"); + const addressBook = $(this.template.firstNode).closest(".address-book"); Meteor.call("accounts/addressBookAdd", insertDoc, (error, result) => { if (error) { diff --git a/client/modules/accounts/templates/addressBook/addressBook.js b/client/modules/accounts/templates/addressBook/addressBook.js index ce72a1e442d..5946ea1a02b 100644 --- a/client/modules/accounts/templates/addressBook/addressBook.js +++ b/client/modules/accounts/templates/addressBook/addressBook.js @@ -18,7 +18,7 @@ Template.addressBook.onCreated(function () { this.autorun(() => { this.subscribe("Accounts", Meteor.userId()); - let account = Collections.Accounts.findOne({ + const account = Collections.Accounts.findOne({ userId: Meteor.userId() }); @@ -42,7 +42,7 @@ Template.addressBook.onCreated(function () { Template.addressBook.helpers({ account: function () { - let account = Collections.Accounts.findOne({ + const account = Collections.Accounts.findOne({ userId: Meteor.userId() }); return account; @@ -99,7 +99,7 @@ Template.addressBook.events({ Alerts.toast(i18next.t("addressBookGrid.cantRemoveThisAddress", { err: error.message }), "error"); } if (result) { - let account = Collections.Accounts.findOne({ + const account = Collections.Accounts.findOne({ userId: Meteor.userId() }); if (account) { diff --git a/client/modules/accounts/templates/addressBook/form/form.js b/client/modules/accounts/templates/addressBook/form/form.js index 68e41b47d3e..a9e5f95b800 100644 --- a/client/modules/accounts/templates/addressBook/form/form.js +++ b/client/modules/accounts/templates/addressBook/form/form.js @@ -24,12 +24,14 @@ Template.addressBookForm.helpers({ } options = []; const ref = shop !== null ? shop.locales.countries[selectedCountry].states : void 0; - for (let state in ref) { - locale = ref[state]; - options.push({ - label: locale.name, - value: state - }); + for (const state in ref) { + if ({}.hasOwnProperty.call(ref, state)) { + locale = ref[state]; + options.push({ + label: locale.name, + value: state + }); + } } return options; }, @@ -44,7 +46,7 @@ Template.addressBookForm.helpers({ return typeof this.address === "object" ? this.address.isShippingDefault : true; }, hasAddressBookEntries: function () { - let account = Collections.Accounts.findOne({ + const account = Collections.Accounts.findOne({ userId: Meteor.userId() }); if (account) { diff --git a/client/modules/accounts/templates/addressBook/grid/grid.js b/client/modules/accounts/templates/addressBook/grid/grid.js index fa308b9df23..57486194221 100644 --- a/client/modules/accounts/templates/addressBook/grid/grid.js +++ b/client/modules/accounts/templates/addressBook/grid/grid.js @@ -7,7 +7,7 @@ import { Template } from "meteor/templating"; */ Template.addressBookGrid.helpers({ selectedBilling: function () { - let cart = Collections.Cart.findOne({ + const cart = Collections.Cart.findOne({ userId: Meteor.userId() }); @@ -29,7 +29,7 @@ Template.addressBookGrid.helpers({ }, selectedShipping: function () { - let cart = Collections.Cart.findOne({ + const cart = Collections.Cart.findOne({ userId: Meteor.userId() }); diff --git a/client/modules/accounts/templates/dashboard/dashboard.js b/client/modules/accounts/templates/dashboard/dashboard.js index 2ba66f9ce88..246c23e947b 100644 --- a/client/modules/accounts/templates/dashboard/dashboard.js +++ b/client/modules/accounts/templates/dashboard/dashboard.js @@ -42,7 +42,7 @@ Template.accountsDashboard.helpers({ const shopUsers = Meteor.users.find(); return shopUsers.map(user => { - let member = {}; + const member = {}; member.userId = user._id; @@ -153,7 +153,7 @@ Template.accountsSettings.events({ // todo remove this after i18next 2 will be installed // let niceName = serviceHelper.capitalizedServiceName(service); - for (let field of fields) { + for (const field of fields) { field.value = event.target[field.property].value; } diff --git a/client/modules/accounts/templates/forgot/forgot.js b/client/modules/accounts/templates/forgot/forgot.js index 1f0087827fc..4060cafd114 100644 --- a/client/modules/accounts/templates/forgot/forgot.js +++ b/client/modules/accounts/templates/forgot/forgot.js @@ -13,10 +13,10 @@ Template.loginFormResetPasswordView.events({ "submit form": (event, template) => { event.preventDefault(); - let emailAddress = template.$(".login-input-email").val().trim(); - let validatedEmail = LoginFormValidation.email(emailAddress); - let templateInstance = Template.instance(); - let errors = {}; + const emailAddress = template.$(".login-input-email").val().trim(); + const validatedEmail = LoginFormValidation.email(emailAddress); + const templateInstance = Template.instance(); + const errors = {}; templateInstance.formMessages.set({}); @@ -55,7 +55,7 @@ Template.loginFormResetPasswordView.events({ * */ Template.loginFormResetPasswordView.onCreated(() => { - let template = Template.instance(); + const template = Template.instance(); template.uniqueId = Random.id(); template.formMessages = new ReactiveVar({}); diff --git a/client/modules/accounts/templates/login/loginForm.js b/client/modules/accounts/templates/login/loginForm.js index 9e4a5cde038..e7825e870ba 100644 --- a/client/modules/accounts/templates/login/loginForm.js +++ b/client/modules/accounts/templates/login/loginForm.js @@ -8,7 +8,7 @@ import { Template } from "meteor/templating"; // XXX from http://epeli.github.com/underscore.string/lib/underscore.string.js function capitalize(str) { - let finalString = str === null ? "" : String(str); + const finalString = str === null ? "" : String(str); return finalString.charAt(0).toUpperCase() + finalString.slice(1); } @@ -51,8 +51,8 @@ Template.loginForm.helpers({ * Login form onCreated */ Template.loginForm.onCreated(function () { - let template = Template.instance(); - let currentData = Template.currentData(); + const template = Template.instance(); + const currentData = Template.currentData(); let startView = "loginFormSignInView"; if (currentData) { @@ -148,8 +148,8 @@ Template.loginFormServiceButton.events({ serviceName = capitalize(serviceName); } - let loginWithService = Meteor["loginWith" + serviceName]; - let options = {}; // use default scope unless specified + const loginWithService = Meteor["loginWith" + serviceName]; + const options = {}; // use default scope unless specified loginWithService(options, () => { // TODO: add error message for failed login attempt diff --git a/client/modules/accounts/templates/members/member.js b/client/modules/accounts/templates/members/member.js index 20a4306a4c0..ab3af69a67b 100644 --- a/client/modules/accounts/templates/members/member.js +++ b/client/modules/accounts/templates/members/member.js @@ -43,12 +43,12 @@ Template.memberSettings.helpers({ } }, groupsForUser: function (groupUserId) { - let userId = groupUserId || this.userId || Template.parentData(1).userId; + const userId = groupUserId || this.userId || Template.parentData(1).userId; return Roles.getGroupsForUser(userId); }, shopLabel: function (thisShopId) { const shopId = thisShopId || Template.currentData(); - let shop = Shops.findOne({ + const shop = Shops.findOne({ _id: shopId }); if (shop && shop.name) { @@ -56,7 +56,7 @@ Template.memberSettings.helpers({ } }, permissionGroups: function (thisShopId) { - let permissionGroups = []; + const permissionGroups = []; const shopId = thisShopId || Template.currentData(); const packages = Packages.find({ shopId: shopId @@ -65,7 +65,7 @@ Template.memberSettings.helpers({ packages.forEach(function (pkg) { const permissions = []; if (pkg.registry && pkg.enabled) { - for (let registryItem of pkg.registry) { + for (const registryItem of pkg.registry) { // Skip entires with missing routes if (!registryItem.route) { continue; @@ -73,14 +73,14 @@ Template.memberSettings.helpers({ // Get all permissions, add them to an array if (registryItem.permissions) { - for (let permission of registryItem.permissions) { + for (const permission of registryItem.permissions) { permission.shopId = shopId; permissions.push(permission); } } // Also create an object map of those same permissions as above - let permissionMap = getPermissionMap(permissions); + const permissionMap = getPermissionMap(permissions); if (!permissionMap[registryItem.route]) { permissions.push({ shopId: pkg.shopId, @@ -120,14 +120,14 @@ Template.memberSettings.helpers({ Template.memberSettings.events({ "change [data-event-action=toggleMemberPermission]": function (event, template) { const self = this; - let permissions = []; + const permissions = []; const member = template.data; if (!this.shopId) { throw new Meteor.Error("Shop is required"); } if (self.name) { permissions.push(self.name); - for (let pkgPermissions of self.permissions) { + for (const pkgPermissions of self.permissions) { permissions.push(pkgPermissions.permission); } } else { @@ -143,7 +143,7 @@ Template.memberSettings.events({ const $icon = $(event.currentTarget); if (confirm($icon.data("confirm"))) { const results = []; - for (let role of template.data.roles) { + for (const role of template.data.roles) { results.push(Meteor.call("accounts/setUserPermissions", this.userId, ["guest", "account/profile"], role)); } return results; diff --git a/client/modules/accounts/templates/members/memberForm.js b/client/modules/accounts/templates/members/memberForm.js index bf380ac4d01..6d23cdf8508 100644 --- a/client/modules/accounts/templates/members/memberForm.js +++ b/client/modules/accounts/templates/members/memberForm.js @@ -10,8 +10,8 @@ Template.memberForm.events({ "submit form": function (event, template) { event.preventDefault(); - let newMemberEmail = template.$('input[name="email"]').val(); - let newMemberName = template.$('input[name="name"]').val(); + const newMemberEmail = template.$('input[name="email"]').val(); + const newMemberName = template.$('input[name="name"]').val(); return Meteor.call("accounts/inviteShopMember", Reaction.getShopId(), newMemberEmail, newMemberName, function (error, result) { diff --git a/client/modules/accounts/templates/profile/profile.js b/client/modules/accounts/templates/profile/profile.js index fc6829daf14..4c1df963822 100644 --- a/client/modules/accounts/templates/profile/profile.js +++ b/client/modules/accounts/templates/profile/profile.js @@ -6,7 +6,7 @@ import { Template } from "meteor/templating"; * onCreated: Account Profile View */ Template.accountProfile.onCreated(() => { - let template = Template.instance(); + const template = Template.instance(); template.userHasPassword = ReactiveVar(false); @@ -59,7 +59,7 @@ Template.accountProfile.helpers({ * @return {String} "addressBookGrid" || "addressBookAdd" */ addressBookView: function () { - let account = Collections.Accounts.findOne(); + const account = Collections.Accounts.findOne(); if (account.profile) { return "addressBookGrid"; } diff --git a/client/modules/accounts/templates/signIn/signIn.js b/client/modules/accounts/templates/signIn/signIn.js index 3cfcadcb8e1..935335f8cdc 100644 --- a/client/modules/accounts/templates/signIn/signIn.js +++ b/client/modules/accounts/templates/signIn/signIn.js @@ -6,7 +6,7 @@ import { Template } from "meteor/templating"; * onCreated: Login form sign in view */ Template.loginFormSignInView.onCreated(() => { - let template = Template.instance(); + const template = Template.instance(); template.uniqueId = Random.id(); template.formMessages = new ReactiveVar({}); @@ -31,17 +31,17 @@ Template.loginFormSignInView.events({ "submit form": (event, template) => { event.preventDefault(); - let usernameInput = template.$(".login-input-email"); - let passwordInput = template.$(".login-input-password"); + const usernameInput = template.$(".login-input-email"); + const passwordInput = template.$(".login-input-password"); - let username = usernameInput.val().trim(); - let password = passwordInput.val().trim(); + const username = usernameInput.val().trim(); + const password = passwordInput.val().trim(); - let validatedEmail = LoginFormValidation.email(username); - let validatedPassword = LoginFormValidation.password(password, {validationLevel: "exists"}); + const validatedEmail = LoginFormValidation.email(username); + const validatedPassword = LoginFormValidation.password(password, {validationLevel: "exists"}); - let templateInstance = Template.instance(); - let errors = {}; + const templateInstance = Template.instance(); + const errors = {}; templateInstance.formMessages.set({}); diff --git a/client/modules/accounts/templates/signUp/signUp.js b/client/modules/accounts/templates/signUp/signUp.js index 4b1c4ea50a3..4b94a19aa59 100644 --- a/client/modules/accounts/templates/signUp/signUp.js +++ b/client/modules/accounts/templates/signUp/signUp.js @@ -5,7 +5,7 @@ import { Template } from "meteor/templating"; * onCreated: Login form sign up view */ Template.loginFormSignUpView.onCreated(() => { - let template = Template.instance(); + const template = Template.instance(); template.uniqueId = Random.id(); template.formMessages = new ReactiveVar({}); @@ -31,17 +31,17 @@ Template.loginFormSignUpView.events({ event.preventDefault(); // var usernameInput = template.$(".login-input--username"); - let emailInput = template.$(".login-input-email"); - let passwordInput = template.$(".login-input-password"); + const emailInput = template.$(".login-input-email"); + const passwordInput = template.$(".login-input-password"); - let email = emailInput.val().trim(); - let password = passwordInput.val().trim(); + const email = emailInput.val().trim(); + const password = passwordInput.val().trim(); - let validatedEmail = LoginFormValidation.email(email); - let validatedPassword = LoginFormValidation.password(password); + const validatedEmail = LoginFormValidation.email(email); + const validatedPassword = LoginFormValidation.password(password); - let templateInstance = Template.instance(); - let errors = {}; + const templateInstance = Template.instance(); + const errors = {}; templateInstance.formMessages.set({}); @@ -61,7 +61,7 @@ Template.loginFormSignUpView.events({ return; } - let newUserData = { + const newUserData = { // username: username, email: email, password: password diff --git a/client/modules/accounts/templates/updatePassword/updatePassword.js b/client/modules/accounts/templates/updatePassword/updatePassword.js index 9e2b8e75e48..4739c7478cf 100644 --- a/client/modules/accounts/templates/updatePassword/updatePassword.js +++ b/client/modules/accounts/templates/updatePassword/updatePassword.js @@ -42,7 +42,7 @@ Accounts.onEmailVerificationLink(function (token, done) { * onCreated: Login Form Update Password Overlay */ Template.loginFormUpdatePasswordOverlay.onCreated(() => { - let template = Template.instance(); + const template = Template.instance(); template.uniqueId = Random.id(); template.formMessages = new ReactiveVar({}); @@ -78,12 +78,12 @@ Template.loginFormUpdatePasswordOverlay.events({ event.preventDefault(); event.stopPropagation(); - let passwordInput = template.$(".login-input--password"); - let password = passwordInput.val().trim(); - let validatedPassword = LoginFormValidation.password(password); + const passwordInput = template.$(".login-input--password"); + const password = passwordInput.val().trim(); + const validatedPassword = LoginFormValidation.password(password); - let templateInstance = Template.instance(); - let errors = {}; + const templateInstance = Template.instance(); + const errors = {}; templateInstance.formMessages.set({}); @@ -121,7 +121,7 @@ Template.loginFormUpdatePasswordOverlay.events({ * onCreated: Login Form Change Password */ Template.loginFormChangePassword.onCreated(() => { - let template = Template.instance(); + const template = Template.instance(); template.uniqueId = Random.id(); template.formMessages = new ReactiveVar({}); @@ -147,19 +147,19 @@ Template.loginFormChangePassword.events({ event.preventDefault(); event.stopPropagation(); - let oldPasswordInput = template.$(".login-input--oldPassword"); - let passwordInput = template.$(".login-input--password"); + const oldPasswordInput = template.$(".login-input--oldPassword"); + const passwordInput = template.$(".login-input--password"); - let oldPassword = oldPasswordInput.val().trim(); - let password = passwordInput.val().trim(); + const oldPassword = oldPasswordInput.val().trim(); + const password = passwordInput.val().trim(); // We only check if it exists, just incase we"ve change the password strength and want the // user to have an oppurtinity to update to a stronger password - let validatedOldPassword = LoginFormValidation.password(password, {validationLevel: "exists"}); - let validatedPassword = LoginFormValidation.password(password); + const validatedOldPassword = LoginFormValidation.password(password, {validationLevel: "exists"}); + const validatedPassword = LoginFormValidation.password(password); - let templateInstance = Template.instance(); - let errors = {}; + const templateInstance = Template.instance(); + const errors = {}; templateInstance.formMessages.set({}); diff --git a/client/modules/core/helpers/apps.js b/client/modules/core/helpers/apps.js index 3a90c300774..6b98758fcbd 100644 --- a/client/modules/core/helpers/apps.js +++ b/client/modules/core/helpers/apps.js @@ -51,15 +51,12 @@ import { Template } from "meteor/templating"; */ export function Apps(optionHash) { - let fields; - let filter; + const filter = {}; + const registryFilter = {}; let key; let match; let packages; - let reactionApps = []; - let reactionPackages; - let registryFilter; let options = {}; // allow for object or option.hash @@ -76,16 +73,12 @@ export function Apps(optionHash) { options.shopId = Reaction.getShopId(); } - reactionApps = []; - filter = {}; - registryFilter = {}; - // // build filter to only get matching registry elements // for (key in options) { if ({}.hasOwnProperty.call(options, key)) { - let value = options[key]; + const value = options[key]; if (!(key === "enabled" || key === "name" || key === "shopId")) { filter["registry." + key] = value; registryFilter[key] = value; @@ -96,7 +89,7 @@ export function Apps(optionHash) { } // return these fields - fields = { + const fields = { enabled: 1, registry: 1, name: 1, @@ -104,7 +97,7 @@ export function Apps(optionHash) { }; // fetch the packages - reactionPackages = Packages.find(filter, fields).fetch(); + const reactionPackages = Packages.find(filter, fields).fetch(); // apply filters to registry items if (reactionPackages.length) { @@ -112,7 +105,7 @@ export function Apps(optionHash) { if (filter.name && filter.enabled) { packages = (function () { const results = []; - for (let pkg of reactionPackages) { + for (const pkg of reactionPackages) { if (pkg.name === filter.name && pkg.enabled === filter.enabled) { results.push(pkg); } @@ -123,7 +116,7 @@ export function Apps(optionHash) { } else if (filter.name) { packages = (function () { const results = []; - for (let pkg of reactionPackages) { + for (const pkg of reactionPackages) { if (pkg.name === filter.name) { results.push(pkg); } @@ -134,7 +127,7 @@ export function Apps(optionHash) { } else if (filter.enabled) { packages = (function () { const results = []; - for (let pkg of reactionPackages) { + for (const pkg of reactionPackages) { if (pkg.enabled === filter.enabled) { results.push(pkg); } @@ -145,7 +138,7 @@ export function Apps(optionHash) { } else { packages = (function () { const results = []; - for (let pkg of reactionPackages) { + for (const pkg of reactionPackages) { results.push(pkg); } return results; @@ -153,7 +146,7 @@ export function Apps(optionHash) { } // we have all the package app registry entries - for (let app of packages) { + for (const app of packages) { // go through the registry entries and push enabled entries if (app.registry) { for (let registry of app.registry) { @@ -161,7 +154,7 @@ export function Apps(optionHash) { for (key in registryFilter) { // make sure we're dealing with valid keys if ({}.hasOwnProperty.call(registryFilter, key)) { - let value = registryFilter[key]; + const value = registryFilter[key]; if (registry[key] === value) { match += 1; } diff --git a/client/modules/core/helpers/globals.js b/client/modules/core/helpers/globals.js index cccc51d7938..2e2b95285ec 100644 --- a/client/modules/core/helpers/globals.js +++ b/client/modules/core/helpers/globals.js @@ -50,8 +50,8 @@ export function toggleSession(sessionVariable, positiveState) { */ export function locateUser() { function successFunction(position) { - let lat = position.coords.latitude; - let lng = position.coords.longitude; + const lat = position.coords.latitude; + const lng = position.coords.longitude; return Meteor.call("shop/locateAddress", lat, lng, function (error, address) { if (address) { diff --git a/client/modules/core/helpers/permissions.js b/client/modules/core/helpers/permissions.js index 8ab690e55c4..841b71446c6 100644 --- a/client/modules/core/helpers/permissions.js +++ b/client/modules/core/helpers/permissions.js @@ -19,7 +19,7 @@ import { Template } from "meteor/templating"; Template.registerHelper("hasPermission", function (permissions, options) { // default to checking this.userId let userId = Meteor.userId(); - let shopId = Reaction.getShopId(); + const shopId = Reaction.getShopId(); // we don't necessarily need to check here // as these same checks and defaults are // also performed in Reaction.hasPermission diff --git a/client/modules/core/helpers/templates.js b/client/modules/core/helpers/templates.js index 6ad92881189..9d8161aa671 100644 --- a/client/modules/core/helpers/templates.js +++ b/client/modules/core/helpers/templates.js @@ -39,6 +39,7 @@ if (Package.blaze) { return isGuest && !isAnonymous ? user : null; } + return null; }); } @@ -48,15 +49,15 @@ if (Package.blaze) { * @return {Array} returns array of months [value:, label:] */ Template.registerHelper("monthOptions", function () { - let label = i18next.t("app.monthOptions", "Choose month"); - let monthOptions = [{ + const label = i18next.t("app.monthOptions", "Choose month"); + const monthOptions = [{ value: "", label: label }]; - let months = moment.months(); - for (let index in months) { + const months = moment.months(); + for (const index in months) { if ({}.hasOwnProperty.call(months, index)) { - let month = months[index]; + const month = months[index]; monthOptions.push({ value: parseInt(index, 10) + 1, label: month @@ -72,8 +73,8 @@ Template.registerHelper("monthOptions", function () { * @return {Array} returns array of years [value:, label:] */ Template.registerHelper("yearOptions", function () { - let label = i18next.t("app.yearOptions", "Choose year"); - let yearOptions = [{ + const label = i18next.t("app.yearOptions", "Choose year"); + const yearOptions = [{ value: "", label: label }]; @@ -94,13 +95,13 @@ Template.registerHelper("yearOptions", function () { * @return {Array} returns array of timezones [value:, label:] */ Template.registerHelper("timezoneOptions", function () { - let label = i18next.t("app.timezoneOptions", "Choose timezone"); - let timezoneOptions = [{ + const label = i18next.t("app.timezoneOptions", "Choose timezone"); + const timezoneOptions = [{ value: "", label: label }]; - let timezones = moment.tz.names(); - for (let timezone of timezones) { + const timezones = moment.tz.names(); + for (const timezone of timezones) { timezoneOptions.push({ value: timezone, label: timezone @@ -117,7 +118,7 @@ Template.registerHelper("timezoneOptions", function () { * @return {String} returns space formatted string */ Template.registerHelper("camelToSpace", function (str) { - let downCamel = str.replace(/\W+/g, "-").replace(/([a-z\d])([A-Z])/g, "$1 $2"); + const downCamel = str.replace(/\W+/g, "-").replace(/([a-z\d])([A-Z])/g, "$1 $2"); return downCamel.toLowerCase(); }); @@ -187,38 +188,38 @@ Template.registerHelper("siteName", function () { */ Template.registerHelper("condition", function (v1, operator, v2) { switch (operator) { - case "==": - case "eq": - return v1 === v2; - case "!=": - case "neq": - return v1 !== v2; - case "===": - case "ideq": - return v1 === v2; - case "!==": - case "nideq": - return v1 !== v2; - case "&&": - case "and": - return v1 && v2; - case "||": - case "or": - return v1 || v2; - case "<": - case "lt": - return v1 < v2; - case "<=": - case "lte": - return v1 <= v2; - case ">": - case "gt": - return v1 > v2; - case ">=": - case "gte": - return v1 >= v2; - default: - throw new Meteor.Error(`Undefined conditional operator ${operator}`); + case "==": + case "eq": + return v1 === v2; + case "!=": + case "neq": + return v1 !== v2; + case "===": + case "ideq": + return v1 === v2; + case "!==": + case "nideq": + return v1 !== v2; + case "&&": + case "and": + return v1 && v2; + case "||": + case "or": + return v1 || v2; + case "<": + case "lt": + return v1 < v2; + case "<=": + case "lte": + return v1 <= v2; + case ">": + case "gt": + return v1 > v2; + case ">=": + case "gte": + return v1 >= v2; + default: + throw new Meteor.Error(`Undefined conditional operator ${operator}`); } }); @@ -240,8 +241,7 @@ Template.registerHelper("orElse", function (v1, v2) { * @return {Array} returns array[key:,value:] */ Template.registerHelper("key_value", function (context) { - let result; - result = []; + const result = []; _.each(context, function (value, key) { return result.push({ key: key, @@ -259,8 +259,7 @@ Template.registerHelper("key_value", function (context) { * @returns {String} returns formatted Spacebars.SafeString */ Template.registerHelper("nl2br", function (text) { - let nl2br; - nl2br = (text + "").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1" + + const nl2br = (text + "").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1" + "
" + "$2"); return new Spacebars.SafeString(nl2br); }); @@ -277,9 +276,8 @@ Template.registerHelper("nl2br", function (text) { * @return {Date} return formatted date */ Template.registerHelper("dateFormat", function (context, block) { - let f; if (window.moment) { - f = block.hash.format || "MMM DD, YYYY hh:mm:ss A"; + const f = block.hash.format || "MMM DD, YYYY hh:mm:ss A"; return moment(context).format(f); } return context; diff --git a/client/modules/core/main.js b/client/modules/core/main.js index effd6fb9361..28cb259a3f5 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -106,13 +106,13 @@ export default { return true; } // global roles check - let sellerShopPermissions = Roles.getGroupsForUser(userId, "admin"); + const sellerShopPermissions = Roles.getGroupsForUser(userId, "admin"); // we're looking for seller permissions. if (sellerShopPermissions) { // loop through shops roles and check permissions - for (let key in sellerShopPermissions) { + for (const key in sellerShopPermissions) { if (key) { - let shop = sellerShopPermissions[key]; + const shop = sellerShopPermissions[key]; if (Roles.userIsInRole(userId, permissions, shop)) { return true; } @@ -171,17 +171,17 @@ export default { }, hasOwnerAccess() { - let ownerPermissions = ["owner"]; + const ownerPermissions = ["owner"]; return this.hasPermission(ownerPermissions); }, hasAdminAccess() { - let adminPermissions = ["owner", "admin"]; + const adminPermissions = ["owner", "admin"]; return this.hasPermission(adminPermissions); }, hasDashboardAccess() { - let dashboardPermissions = ["owner", "admin", "dashboard"]; + const dashboardPermissions = ["owner", "admin", "dashboard"]; return this.hasPermission(dashboardPermissions); }, @@ -231,7 +231,7 @@ export default { if (viewData) { Session.set("admin/actionView", viewData); } else { - let registryItem = this.getRegistryForCurrentRoute( + const registryItem = this.getRegistryForCurrentRoute( "settings"); if (registryItem) { @@ -271,7 +271,7 @@ export default { const currentRoute = this.Router.current(); const template = currentRoute.route.options.template; // find registry entries for routeName - let reactionApp = Packages.findOne({ + const reactionApp = Packages.findOne({ "registry.name": currentRouteName, "registry.provides": provides }, { @@ -284,7 +284,7 @@ export default { // valid application if (reactionApp) { - let settingsData = _.find(reactionApp.registry, function (item) { + const settingsData = _.find(reactionApp.registry, function (item) { return item.provides === provides && item.template === template; }); return settingsData; @@ -305,9 +305,9 @@ export default { function createCountryCollection(countries) { check(countries, Object); const countryOptions = []; - for (let locale in countries) { + for (const locale in countries) { if ({}.hasOwnProperty.call(countries, locale)) { - let country = countries[locale]; + const country = countries[locale]; countryOptions.push({ label: country.name, value: locale @@ -324,7 +324,7 @@ function createCountryCollection(countries) { return 0; }); - for (let country of countryOptions) { + for (const country of countryOptions) { Countries.insert(country); } return countryOptions; diff --git a/client/modules/core/startup.js b/client/modules/core/startup.js index c343106b9c0..b58c5cb60db 100644 --- a/client/modules/core/startup.js +++ b/client/modules/core/startup.js @@ -27,7 +27,7 @@ if (typeof document.hidden !== "undefined") { Meteor.startup(function () { // warn on insecure exporting of PackageRegistry settings if (typeof PackageRegistry !== "undefined" && PackageRegistry !== null) { - let msg = "PackageRegistry: Insecure export to client."; + const msg = "PackageRegistry: Insecure export to client."; Logger.warn(msg, PackageRegistry); } // init the core diff --git a/client/modules/i18n/helpers.js b/client/modules/i18n/helpers.js index 1b15bb176a1..ba045644783 100644 --- a/client/modules/i18n/helpers.js +++ b/client/modules/i18n/helpers.js @@ -1,9 +1,8 @@ import accounting from "accounting-js"; -import { localeDep, i18nextDep } from "./main"; -import { Reaction, Logger, i18next } from "/client/api"; -import { Session } from "meteor/session"; import { Meteor } from "meteor/meteor"; import { Template } from "meteor/templating"; +import { localeDep, i18nextDep } from "./main"; +import { Reaction, Logger, i18next } from "/client/api"; /** * i18n @@ -25,7 +24,7 @@ Template.registerHelper("i18n", function (i18nKey, i18nMessage) { i18nextDep.depend(); - const message = new Handlebars.SafeString(i18nMessage); + const message = new Spacebars.SafeString(i18nMessage); // returning translated key return i18next.t(i18nKey, {defaultValue: message}); @@ -63,7 +62,7 @@ Template.registerHelper("formatPrice", function (formatPrice) { } // for the cases then we have only one price. It is a number. - let currentPrice = formatPrice.toString(); + const currentPrice = formatPrice.toString(); let price = 0; const prices = ~currentPrice.indexOf(" - ") ? currentPrice.split(" - ") : [currentPrice]; @@ -71,7 +70,7 @@ Template.registerHelper("formatPrice", function (formatPrice) { // basic "for" is faster then "for ...of" for arrays. We need more speed here const len = prices.length; for (let i = 0; i < len; i++) { - let originalPrice = prices[i]; + const originalPrice = prices[i]; try { // we know the locale, but we don"t know exchange rate. In that case we // should return to default shop currency @@ -97,10 +96,10 @@ Reaction.Currency = {}; Reaction.Currency.formatNumber = function (currentPrice) { const locale = Reaction.Locale.get(); let price = currentPrice; - let format = Object.assign({}, locale.currency, { + const format = Object.assign({}, locale.currency, { format: "%v" }); - let shopFormat = Object.assign({}, locale.shopCurrency, { + const shopFormat = Object.assign({}, locale.shopCurrency, { format: "%v" }); @@ -152,7 +151,7 @@ function _formatPrice(price, originalPrice, actualPrice, currentPrice, currency, // For now it should be manually added to fixtures shop data. if (typeof currency.where === "string" && currency.where === "right" && len > 1 && pos === 0) { - let modifiedCurrency = Object.assign({}, currency, { + const modifiedCurrency = Object.assign({}, currency, { symbol: "" }); formattedPrice = accounting.formatMoney(adjustedPrice, modifiedCurrency); diff --git a/client/modules/i18n/main.js b/client/modules/i18n/main.js index fe14e451d13..7a821d0b29f 100644 --- a/client/modules/i18n/main.js +++ b/client/modules/i18n/main.js @@ -41,9 +41,9 @@ export function getBrowserLanguage() { * @return {Object} return schema label object */ function getLabelsFor(schema, name) { - let labels = {}; + const labels = {}; // loop through all the rendered form fields and generate i18n keys - for (let fieldName of schema._schemaKeys) { + for (const fieldName of schema._schemaKeys) { const i18nKey = name.charAt(0).toLowerCase() + name.slice(1) + "." + fieldName .split(".$").join(""); @@ -69,8 +69,8 @@ function getLabelsFor(schema, name) { * @return {Object} returns i18n translated message for schema labels */ function getMessagesFor() { - let messages = {}; - for (let message in SimpleSchema._globalMessages) { + const messages = {}; + for (const message in SimpleSchema._globalMessages) { if ({}.hasOwnProperty.call(SimpleSchema._globalMessages, message)) { const i18nKey = `globalMessages.${message}`; const t = i18next.t(i18nKey); @@ -174,9 +174,9 @@ Tracker.autorun(function () { }, (err, t) => { // someday this should work // see: https://github.com/aldeed/meteor-simple-schema/issues/494 - for (let schema in _.omit(Schemas, "__esModule")) { + for (const schema in _.omit(Schemas, "__esModule")) { if ({}.hasOwnProperty.call(Schemas, schema)) { - let ss = Schemas[schema]; + const ss = Schemas[schema]; ss.labels(getLabelsFor(ss, schema)); ss.messages(getMessagesFor(ss, schema)); } diff --git a/client/modules/i18n/templates/header/i18n.js b/client/modules/i18n/templates/header/i18n.js index 71e86bf85c9..26af4cca63a 100644 --- a/client/modules/i18n/templates/header/i18n.js +++ b/client/modules/i18n/templates/header/i18n.js @@ -8,11 +8,11 @@ import { Session } from "meteor/session"; Template.i18nChooser.helpers({ languages() { - let languages = []; + const languages = []; if (Reaction.Subscriptions.Shops.ready()) { - let shop = Shops.findOne(); + const shop = Shops.findOne(); if (typeof shop === "object" && shop.languages) { - for (let language of shop.languages) { + for (const language of shop.languages) { if (language.enabled === true) { language.translation = "languages." + language.label.toLowerCase(); languages.push(language); diff --git a/client/modules/i18n/templates/i18nSettings.js b/client/modules/i18n/templates/i18nSettings.js index 1b18425bbb6..ff3c21dd945 100644 --- a/client/modules/i18n/templates/i18nSettings.js +++ b/client/modules/i18n/templates/i18nSettings.js @@ -21,9 +21,9 @@ Template.i18nSettings.helpers({ currencyOptions() { const currencies = Shops.findOne().currencies; const currencyOptions = []; - for (let currency in currencies) { + for (const currency in currencies) { if ({}.hasOwnProperty.call(currencies, currency)) { - let structure = currencies[currency]; + const structure = currencies[currency]; currencyOptions.push({ label: currency + " | " + structure.symbol + " | " + structure.format, @@ -36,7 +36,7 @@ Template.i18nSettings.helpers({ uomOptions() { const unitsOfMeasure = Shops.findOne().unitsOfMeasure; const uomOptions = []; - for (let measure of unitsOfMeasure) { + for (const measure of unitsOfMeasure) { uomOptions.push({ label: i18next.t(`uom.${measure.uom}`, {defaultValue: measure.uom}), value: measure.uom @@ -45,10 +45,10 @@ Template.i18nSettings.helpers({ return uomOptions; }, enabledLanguages() { - let languages = []; + const languages = []; const shop = Shops.findOne(); if (typeof shop === "object" && shop.languages) { - for (let language of shop.languages) { + for (const language of shop.languages) { if (language.enabled === true) { languages.push({ label: language.label, @@ -60,10 +60,10 @@ Template.i18nSettings.helpers({ } }, languages() { - let languages = []; + const languages = []; const shop = Shops.findOne(); if (typeof shop === "object" && shop.languages) { - for (let language of shop.languages) { + for (const language of shop.languages) { const i18nKey = "languages." + language.label.toLowerCase(); languages.push({ label: language.label, diff --git a/client/modules/router/main.js b/client/modules/router/main.js index 5d61a2f8e63..a8404548e4b 100644 --- a/client/modules/router/main.js +++ b/client/modules/router/main.js @@ -111,7 +111,7 @@ export function ReactionLayout(options = {}) { // check if router has denied permissions // see: checkRouterPermissions - let unauthorized = {}; + const unauthorized = {}; if (Router.current().unauthorized) { unauthorized.template = "unauthorized"; } @@ -183,12 +183,12 @@ Router.initPackageRoutes = () => { }); // get package registry route configurations - for (let pkg of pkgs) { + for (const pkg of pkgs) { const newRoutes = []; // pkg registry if (pkg.registry) { const registry = Array.from(pkg.registry); - for (let registryItem of registry) { + for (const registryItem of registry) { // registryItems if (registryItem.route) { const { @@ -227,7 +227,7 @@ Router.initPackageRoutes = () => { // add group and routes to routing table // const uniqRoutes = new Set(newRoutes); - for (let route of uniqRoutes) { + for (const route of uniqRoutes) { // allow overriding of prefix in route definitions // define an "absolute" url by excluding "/" if (route.route.substring(0, 1) !== "/") { @@ -271,10 +271,10 @@ Router.initPackageRoutes = () => { * @return {String} returns current router path */ Router.pathFor = (path, options = {}) => { - let params = options.hash || {}; - let query = params.query ? Router._qs.parse(params.query) : {}; + const params = options.hash || {}; + const query = params.query ? Router._qs.parse(params.query) : {}; // prevent undefined param error - for (let i in params) { + for (const i in params) { if (params[i] === null || params[i] === undefined) { params[i] = "/"; } diff --git a/imports/plugins/core/checkout/client/helpers/cart.js b/imports/plugins/core/checkout/client/helpers/cart.js index 83c6d67ec0f..2429a35df81 100644 --- a/imports/plugins/core/checkout/client/helpers/cart.js +++ b/imports/plugins/core/checkout/client/helpers/cart.js @@ -18,7 +18,7 @@ import { Template } from "meteor/templating"; * @return {Object} returns inventory helpers */ Template.registerHelper("cart", function () { - let cartHelpers = { + const cartHelpers = { /** * showCartIconWarning * @return {Boolean} return true if low inventory on any item in cart @@ -35,7 +35,7 @@ Template.registerHelper("cart", function () { */ showLowInventoryWarning() { let item; - let storedCart = Cart.findOne(); + const storedCart = Cart.findOne(); // we're not being picky here - first thing in cart // that is low will trigger a inventory warning if (storedCart && storedCart.items) { @@ -73,7 +73,7 @@ Template.registerHelper("cart", function () { */ Template.registerHelper("cartPayerName", function () { - let cart = Cart.findOne(); + const cart = Cart.findOne(); if (cart) { if (cart.billing) { if (cart.billing[0].address) { diff --git a/imports/plugins/core/checkout/client/methods/cart.js b/imports/plugins/core/checkout/client/methods/cart.js index 0cf423862c4..e2f2b6d8c4b 100644 --- a/imports/plugins/core/checkout/client/methods/cart.js +++ b/imports/plugins/core/checkout/client/methods/cart.js @@ -9,13 +9,13 @@ import { Cart } from "/lib/collections"; Meteor.methods({ "cart/submitPayment": function (paymentMethod) { check(paymentMethod, Reaction.Schemas.PaymentMethod); - let checkoutCart = Cart.findOne({ + const checkoutCart = Cart.findOne({ userId: Meteor.userId() }); - let cart = _.clone(checkoutCart); - let cartId = cart._id; - let invoice = { + const cart = _.clone(checkoutCart); + const cartId = cart._id; + const invoice = { shipping: cart.cartShipping(), subtotal: cart.cartSubTotal(), taxes: cart.cartTaxes(), diff --git a/imports/plugins/core/checkout/client/templates/cartDrawer/cartDrawer.js b/imports/plugins/core/checkout/client/templates/cartDrawer/cartDrawer.js index 0093817ce60..d190d35e2a5 100644 --- a/imports/plugins/core/checkout/client/templates/cartDrawer/cartDrawer.js +++ b/imports/plugins/core/checkout/client/templates/cartDrawer/cartDrawer.js @@ -18,11 +18,11 @@ Template.cartDrawer.helpers({ return null; } - let storedCart = Cart.findOne(); + const storedCart = Cart.findOne(); let count = 0; if (typeof storedCart === "object" && storedCart.items) { - for (let items of storedCart.items) { + for (const items of storedCart.items) { count += items.quantity; } } diff --git a/imports/plugins/core/checkout/client/templates/cartDrawer/cartItems/cartItems.js b/imports/plugins/core/checkout/client/templates/cartDrawer/cartItems/cartItems.js index e533aa22cf2..a60700d9f4b 100644 --- a/imports/plugins/core/checkout/client/templates/cartDrawer/cartItems/cartItems.js +++ b/imports/plugins/core/checkout/client/templates/cartDrawer/cartItems/cartItems.js @@ -13,7 +13,7 @@ Template.cartDrawerItems.helpers({ return Products.findOne(this.productId); }, media: function () { - let product = Products.findOne(this.productId); + const product = Products.findOne(this.productId); let defaultImage = Media.findOne({ "metadata.variantId": this.variants._id }); diff --git a/imports/plugins/core/checkout/client/templates/checkout/completed/completed.js b/imports/plugins/core/checkout/client/templates/checkout/completed/completed.js index 1f2d6770d65..6038efd224a 100644 --- a/imports/plugins/core/checkout/client/templates/checkout/completed/completed.js +++ b/imports/plugins/core/checkout/client/templates/checkout/completed/completed.js @@ -50,7 +50,7 @@ Template.cartCompleted.helpers({ */ Template.cartCompleted.events({ "click #update-order": function () { - let templateInstance = Template.instance(); + const templateInstance = Template.instance(); const email = templateInstance.find("input[name=email]").value; check(email, String); const cartId = Reaction.Router.getQueryParam("_id"); @@ -65,9 +65,9 @@ Template.cartCompleted.events({ * the subscription to get the new cart */ Template.cartCompleted.onCreated(function () { - let sessionId = Session.get("sessionId"); - let userId = Meteor.userId(); - let cartSub = Reaction.Subscriptions.Cart = Meteor.subscribe("Cart", sessionId, userId); + const sessionId = Session.get("sessionId"); + const userId = Meteor.userId(); + const cartSub = Reaction.Subscriptions.Cart = Meteor.subscribe("Cart", sessionId, userId); cartSub.stop(); Reaction.Subscriptions.Cart = Meteor.subscribe("Cart", sessionId, userId); }); diff --git a/imports/plugins/core/checkout/client/templates/checkout/payment/methods/cards.js b/imports/plugins/core/checkout/client/templates/checkout/payment/methods/cards.js index c26bdf3f4ed..a3bc519963f 100644 --- a/imports/plugins/core/checkout/client/templates/checkout/payment/methods/cards.js +++ b/imports/plugins/core/checkout/client/templates/checkout/payment/methods/cards.js @@ -28,10 +28,10 @@ Template.corePaymentMethods.helpers({ }, appDetails: function () { // Provides a fallback to the package icon / label if one is not found for this reaction app - let self = this; + const self = this; if (!(this.icon && this.label)) { - let app = Packages.findOne(this.packageId); - for (let registry of app.registry) { + const app = Packages.findOne(this.packageId); + for (const registry of app.registry) { if (!(registry.provides === "dashboard")) { continue; } diff --git a/imports/plugins/core/checkout/client/templates/checkout/shipping/shipping.js b/imports/plugins/core/checkout/client/templates/checkout/shipping/shipping.js index 59c4582310f..1408e9afe36 100644 --- a/imports/plugins/core/checkout/client/templates/checkout/shipping/shipping.js +++ b/imports/plugins/core/checkout/client/templates/checkout/shipping/shipping.js @@ -8,7 +8,7 @@ import { Template } from "meteor/templating"; // cartShippingMethods to get current shipment methods // until we handle multiple methods, we just use the first function cartShippingMethods(currentCart) { - let cart = currentCart || Cart.findOne(); + const cart = currentCart || Cart.findOne(); if (cart) { if (cart.shipping) { if (cart.shipping[0].shipmentQuotes) { @@ -21,7 +21,7 @@ function cartShippingMethods(currentCart) { // getShipmentMethod to get current shipment method // until we handle multiple methods, we just use the first function getShipmentMethod(currentCart) { - let cart = currentCart || Cart.findOne(); + const cart = currentCart || Cart.findOne(); if (cart) { if (cart.shipping) { if (cart.shipping[0].shipmentMethod) { @@ -58,8 +58,8 @@ Template.coreCheckoutShipping.helpers({ // helper to display currently selected shipmentMethod isSelected: function () { - let self = this; - let shipmentMethod = getShipmentMethod(); + const self = this; + const shipmentMethod = getShipmentMethod(); // if there is already a selected method, set active if (_.isEqual(self.method, shipmentMethod)) { return "active"; @@ -77,8 +77,8 @@ Template.coreCheckoutShipping.events({ "click .list-group-item": function (event) { event.preventDefault(); event.stopPropagation(); - let self = this; - let cart = Cart.findOne(); + const self = this; + const cart = Cart.findOne(); try { Meteor.call("cart/setShipmentMethod", cart._id, self.method); diff --git a/imports/plugins/core/checkout/server/methods/workflow.js b/imports/plugins/core/checkout/server/methods/workflow.js index 5dc2e1ac6a2..b75e232a6db 100644 --- a/imports/plugins/core/checkout/server/methods/workflow.js +++ b/imports/plugins/core/checkout/server/methods/workflow.js @@ -27,7 +27,7 @@ Meteor.methods({ this.unblock(); let currentCart; - let defaultPackageWorkflows = []; + const defaultPackageWorkflows = []; let nextWorkflowStep = { template: "" }; @@ -46,8 +46,8 @@ Meteor.methods({ // exit if a cart doesn't exist. if (!currentCart) return []; // TODO doc this - let currentWorkflowStatus = currentCart.workflow.status; - let packages = Packages.find({ + const currentWorkflowStatus = currentCart.workflow.status; + const packages = Packages.find({ "shopId": Reaction.getShopId(), "layout.workflow": workflow }); @@ -56,14 +56,14 @@ Meteor.methods({ packages.forEach(function (reactionPackage) { // todo fix this hack for not filtering nicely if (!reactionPackage.layout.layout) { - let layouts = _.filter(reactionPackage.layout, { + const layouts = _.filter(reactionPackage.layout, { workflow: workflow }); // for every layout, process the associated workflows _.each(layouts, function (layout) { // audience is the layout permissions if (typeof layout.audience !== "object") { - let defaultRoles = Shops.findOne( + const defaultRoles = Shops.findOne( Reaction.getShopId(), { sort: { priority: 1 @@ -148,7 +148,7 @@ Meteor.methods({ Logger.debug( `######## Condition One #########: initialise the ${currentCart._id} ${workflow}: ${defaultPackageWorkflows[0].template}` ); - let result = Cart.update(currentCart._id, { + const result = Cart.update(currentCart._id, { $set: { "workflow.status": defaultPackageWorkflows[0].template } @@ -322,7 +322,7 @@ Meteor.methods({ const items = order.items.map((item) => { // Add the current status to completed workflows if (item.workflow.status !== "new") { - let workflows = item.workflow.workflow || []; + const workflows = item.workflow.workflow || []; workflows.push(status); item.workflow.workflow = _.uniq(workflows); diff --git a/imports/plugins/core/dashboard/client/templates/import/import.js b/imports/plugins/core/dashboard/client/templates/import/import.js index b81e8ac6d99..f37ce9e9b42 100644 --- a/imports/plugins/core/dashboard/client/templates/import/import.js +++ b/imports/plugins/core/dashboard/client/templates/import/import.js @@ -2,12 +2,12 @@ import { Reaction } from "/client/api"; import { Media, Products } from "/lib/collections"; function uploadHandler(event) { - let shopId = Reaction.getShopId(); - let userId = Meteor.userId(); - let files = event.target.files.files; + const shopId = Reaction.getShopId(); + const userId = Meteor.userId(); + const files = event.target.files.files; for (let i = 0; i < files.length; i++) { - let parts = files[i].name.split("."); + const parts = files[i].name.split("."); let product; if (parts[0]) { product = Products.findOne({ @@ -21,8 +21,7 @@ function uploadHandler(event) { }); } if (product) { - let fileObj; - fileObj = new FS.File(files[i]); + const fileObj = new FS.File(files[i]); fileObj.metadata = { ownerId: userId, productId: product._id, diff --git a/imports/plugins/core/dashboard/client/templates/packages/grid/package.js b/imports/plugins/core/dashboard/client/templates/packages/grid/package.js index 9ea8b476a58..159454a7f7c 100644 --- a/imports/plugins/core/dashboard/client/templates/packages/grid/package.js +++ b/imports/plugins/core/dashboard/client/templates/packages/grid/package.js @@ -39,7 +39,7 @@ Template.gridPackage.helpers({ name: data.package.packageName }); - let controls = []; + const controls = []; if (data.package.priority > 1) { controls.push({ @@ -55,7 +55,7 @@ Template.gridPackage.helpers({ }); } - for (let app of apps) { + for (const app of apps) { controls.push({ icon: app.icon || "fa fa-cog fa-fw", onClick() { diff --git a/imports/plugins/core/dashboard/client/templates/shop/settings/settings.js b/imports/plugins/core/dashboard/client/templates/shop/settings/settings.js index 65844a8ed61..6b7cdcb00e2 100644 --- a/imports/plugins/core/dashboard/client/templates/shop/settings/settings.js +++ b/imports/plugins/core/dashboard/client/templates/shop/settings/settings.js @@ -4,7 +4,7 @@ import { Media, Packages, Shops } from "/lib/collections"; Template.shopBrandImageOption.helpers({ cardProps(data) { - let props = { + const props = { controls: [] }; @@ -110,7 +110,7 @@ Template.shopSettings.helpers({ const shopId = Reaction.getShopId(); return (files) => { - for (let file of files) { + for (const file of files) { file.metadata = { type: "brandAsset", ownerId: userId, @@ -142,7 +142,7 @@ Template.shopSettings.helpers({ }]; if (paymentMethods && _.isArray(paymentMethods)) { - for (let method of paymentMethods) { + for (const method of paymentMethods) { options.push({ label: i18next.t(method.i18nKeyLabel), value: method.packageName diff --git a/imports/plugins/core/layout/client/templates/layout/admin/admin.js b/imports/plugins/core/layout/client/templates/layout/admin/admin.js index a1ed2678aeb..dab2a073c23 100644 --- a/imports/plugins/core/layout/client/templates/layout/admin/admin.js +++ b/imports/plugins/core/layout/client/templates/layout/admin/admin.js @@ -1,10 +1,10 @@ import Drop from "tether-drop"; import { Meteor } from "meteor/meteor"; -import { Session } from "meteor/session"; +import { Blaze } from "meteor/blaze"; import { Template } from "meteor/templating"; import { Reaction, i18next } from "/client/api"; import { Packages } from "/lib/collections"; -import { Blaze } from "meteor/blaze"; + Template.coreAdminLayout.onRendered(function () { $("body").addClass("admin"); @@ -23,10 +23,10 @@ Template.coreAdminLayout.helpers({ container: undefined }); - let items = []; + const items = []; if (_.isArray(shortcuts)) { - for (let shortcut of shortcuts) { + for (const shortcut of shortcuts) { items.push({ type: "link", href: Reaction.Router.pathFor(shortcut.name), @@ -80,9 +80,9 @@ Template.coreAdminLayout.helpers({ if (routeName !== "dashboard") { const registryItems = Reaction.Apps({provides: "settings", container: routeName}); - let buttons = []; + const buttons = []; - for (let item of registryItems) { + for (const item of registryItems) { if (Reaction.hasPermission(item.route, Meteor.userId())) { let icon = item.icon; @@ -104,6 +104,7 @@ Template.coreAdminLayout.helpers({ return buttons; } + return []; }, control: function () { diff --git a/imports/plugins/core/layout/client/templates/layout/alerts/alerts.js b/imports/plugins/core/layout/client/templates/layout/alerts/alerts.js index 33a8e959446..6ee6766af14 100644 --- a/imports/plugins/core/layout/client/templates/layout/alerts/alerts.js +++ b/imports/plugins/core/layout/client/templates/layout/alerts/alerts.js @@ -8,8 +8,8 @@ Template.inlineAlert.onCreated(function () { }); Template.inlineAlert.onRendered(function () { - let alert = this.data; - let $node = $(this.firstNode); + const alert = this.data; + const $node = $(this.firstNode); Meteor.defer(function () { Alerts.collection_.update(alert._id, { diff --git a/imports/plugins/core/layout/client/templates/layout/alerts/reactionAlerts.js b/imports/plugins/core/layout/client/templates/layout/alerts/reactionAlerts.js index 2cfff5b03cd..2e7e26701de 100644 --- a/imports/plugins/core/layout/client/templates/layout/alerts/reactionAlerts.js +++ b/imports/plugins/core/layout/client/templates/layout/alerts/reactionAlerts.js @@ -73,12 +73,12 @@ Object.assign(Alerts, { }); } - let title = titleOrOptions; - let message = messageOrCallback; + const title = titleOrOptions; + const message = messageOrCallback; return swal({ title, - message, + text: message, type: "info", ...options }).then((isConfirm) => { diff --git a/imports/plugins/core/orders/client/templates/list/items.js b/imports/plugins/core/orders/client/templates/list/items.js index 4444216845b..2d5ba1ab10e 100644 --- a/imports/plugins/core/orders/client/templates/list/items.js +++ b/imports/plugins/core/orders/client/templates/list/items.js @@ -28,12 +28,12 @@ Template.ordersListItems.helpers({ items() { const { order } = Template.instance().data; - let combinedItems = []; + const combinedItems = []; if (order) { // Lopp through all items in the order. The items are split into indivital items - for (let orderItem of order.items) { + for (const orderItem of order.items) { // Find an exising item in the combinedItems array const foundItem = combinedItems.find((combinedItem) => { // If and item variant exists, then we return true diff --git a/imports/plugins/core/orders/client/templates/list/ordersList.js b/imports/plugins/core/orders/client/templates/list/ordersList.js index b6bc9968a0f..108ac46300d 100644 --- a/imports/plugins/core/orders/client/templates/list/ordersList.js +++ b/imports/plugins/core/orders/client/templates/list/ordersList.js @@ -30,7 +30,7 @@ Template.dashboardOrdersList.helpers({ return this.shipping[0].shipmentMethod.tracking; }, shopName() { - let shop = Shops.findOne(this.shopId); + const shop = Shops.findOne(this.shopId); return shop !== null ? shop.name : void 0; } }); diff --git a/imports/plugins/core/orders/client/templates/orderPage/orderPage.js b/imports/plugins/core/orders/client/templates/orderPage/orderPage.js index 2b4b4633fbd..3ddb887ab00 100644 --- a/imports/plugins/core/orders/client/templates/orderPage/orderPage.js +++ b/imports/plugins/core/orders/client/templates/orderPage/orderPage.js @@ -27,7 +27,7 @@ Template.orderPage.events({ "click .btn-add-note": function (event, template) { const date = new Date(); const content = template.find("textarea[name=note]").value; - let note = { + const note = { content: content, userId: Meteor.userId(), updatedAt: date diff --git a/imports/plugins/core/orders/client/templates/orders.js b/imports/plugins/core/orders/client/templates/orders.js index 6bf6b091a38..7b82daeb3f9 100644 --- a/imports/plugins/core/orders/client/templates/orders.js +++ b/imports/plugins/core/orders/client/templates/orders.js @@ -21,58 +21,58 @@ const OrderHelper = { switch (filter) { // New orders - case "new": - query = { - "workflow.status": "new" - }; - break; + case "new": + query = { + "workflow.status": "new" + }; + break; // Orders that have yet to be captured & shipped - case "processing": - query = { - "workflow.status": "coreOrderWorkflow/processing" - }; - break; + case "processing": + query = { + "workflow.status": "coreOrderWorkflow/processing" + }; + break; // Orders that have been shipped, based on if the items have been shipped - case "shipped": - query = { - "items.workflow.status": "coreOrderItemWorkflow/shipped" - }; - break; + case "shipped": + query = { + "items.workflow.status": "coreOrderItemWorkflow/shipped" + }; + break; // Orders that are complete, including all items with complete status - case "completed": - query = { - "workflow.status": "coreOrderWorkflow/completed", - "items.workflow.workflow": { - $in: ["coreOrderItemWorkflow/completed"] - } - }; - break; + case "completed": + query = { + "workflow.status": "coreOrderWorkflow/completed", + "items.workflow.workflow": { + $in: ["coreOrderItemWorkflow/completed"] + } + }; + break; // Orders that have been captured, but not yet shipped - case "captured": - query = { - "billing.paymentMethod.status": "completed", - "shipping.shipped": false - }; - break; - - case "canceled": - query = { - "workflow.status": "canceled" - }; - break; + case "captured": + query = { + "billing.paymentMethod.status": "completed", + "shipping.shipped": false + }; + break; + + case "canceled": + query = { + "workflow.status": "canceled" + }; + break; // Orders that have been refunded partially or fully - case "refunded": - query = { - "billing.paymentMethod.status": "captured", - "shipping.shipped": true - }; - break; - default: + case "refunded": + query = { + "billing.paymentMethod.status": "captured", + "shipping.shipped": true + }; + break; + default: } return query; @@ -132,7 +132,7 @@ Template.orders.helpers({ }, currentFilterLabel() { - let foundFilter = _.find(orderFilters, (filter) => { + const foundFilter = _.find(orderFilters, (filter) => { return filter.name === Reaction.Router.getQueryParam("filter"); }); @@ -307,7 +307,7 @@ Template.orderStatusDetail.helpers({ const self = this; const shipment = this.shipping[0]; const shipped = _.every(shipment.items, (shipmentItem) => { - for (let fullItem of self.items) { + for (const fullItem of self.items) { if (fullItem._id === shipmentItem._id) { if (fullItem.workflow) { if (_.isArray(fullItem.workflow.workflow)) { diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingInvoice.js b/imports/plugins/core/orders/client/templates/workflow/shippingInvoice.js index fa576a5d917..2e7d4bc830f 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingInvoice.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingInvoice.js @@ -307,7 +307,7 @@ Template.coreOrderShippingInvoice.helpers({ }, refunds() { - let refunds = Template.instance().refunds.get(); + const refunds = Template.instance().refunds.get(); if (_.isArray(refunds)) { return refunds.reverse(); @@ -364,7 +364,7 @@ Template.coreOrderShippingInvoice.helpers({ const instance = Template.instance(); const order = instance.state.get("order"); - let shipment = _.filter(order.shipping, {_id: currentData.fulfillment._id})[0]; + const shipment = _.filter(order.shipping, {_id: currentData.fulfillment._id})[0]; return shipment; }, @@ -375,8 +375,8 @@ Template.coreOrderShippingInvoice.helpers({ const currentData = Template.currentData(); const shipment = currentData.fulfillment; - let items = _.map(shipment.items, (item) => { - let originalItem = _.find(order.items, { + const items = _.map(shipment.items, (item) => { + const originalItem = _.find(order.items, { _id: item._id }); return _.extend(originalItem, item); @@ -397,7 +397,7 @@ Template.coreOrderShippingInvoice.helpers({ variantId = variantObjectOrId._id; } - let defaultImage = Media.findOne({ + const defaultImage = Media.findOne({ "metadata.variantId": variantId, "metadata.priority": 0 }); diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingSummary.js b/imports/plugins/core/orders/client/templates/workflow/shippingSummary.js index 279a148753e..de1c7443c04 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingSummary.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingSummary.js @@ -6,8 +6,8 @@ import { i18next } from "/client/api"; import { Orders } from "/lib/collections"; Template.coreOrderShippingSummary.onCreated(() => { - let template = Template.instance(); - let currentData = Template.currentData(); + const template = Template.instance(); + const currentData = Template.currentData(); template.orderDep = new Tracker.Dependency; @@ -29,8 +29,8 @@ Template.coreOrderShippingSummary.onCreated(() => { */ Template.coreOrderShippingSummary.onRendered(function () { - let template = Template.instance(); - let order = template.order; + const template = Template.instance(); + const order = template.order; if (order.workflow) { if (order.workflow.status === "coreOrderCreated") { @@ -53,7 +53,7 @@ Template.coreOrderShippingSummary.events({ Template.coreOrderShippingSummary.helpers({ order() { - let template = Template.instance(); + const template = Template.instance(); return template.order; }, shipment() { @@ -69,7 +69,7 @@ Template.coreOrderShippingSummary.helpers({ }, tracking() { - let shipment = Template.instance().order.shipping[0]; + const shipment = Template.instance().order.shipping[0]; if (shipment.tracking) { return shipment.tracking; } @@ -80,7 +80,7 @@ Template.coreOrderShippingSummary.helpers({ const order = Template.instance().order; const shipment = Template.instance().order.shipping[0]; const shipped = _.every(shipment.items, (shipmentItem) => { - for (let fullItem of order.items) { + for (const fullItem of order.items) { if (fullItem._id === shipmentItem._id) { if (fullItem.workflow) { if (_.isArray(fullItem.workflow.workflow)) { diff --git a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js index 1588d2af072..7caf81c0293 100644 --- a/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js +++ b/imports/plugins/core/orders/client/templates/workflow/shippingTracking.js @@ -5,8 +5,8 @@ import { Template } from "meteor/templating"; import { Orders } from "/lib/collections"; Template.coreOrderShippingTracking.onCreated(() => { - let template = Template.instance(); - let currentData = Template.currentData(); + const template = Template.instance(); + const currentData = Template.currentData(); template.orderDep = new Tracker.Dependency; template.showTrackingEditForm = ReactiveVar(false); @@ -30,13 +30,13 @@ Template.coreOrderShippingTracking.onCreated(() => { */ Template.coreOrderShippingTracking.events({ "click [data-event-action=shipmentShipped]": function () { - let template = Template.instance(); + const template = Template.instance(); Meteor.call("orders/shipmentShipped", template.order, template.order.shipping[0]); // Meteor.call("workflow/pushOrderShipmentWorkflow", "coreOrderShipmentWorkflow", "orderShipped", this._id); }, "click [data-event-action=resendNotification]": function () { - let template = Template.instance(); + const template = Template.instance(); Meteor.call("orders/sendNotification", template.order, (err) => { if (err) { Alerts.toast("Server Error: Can't send email notification.", "error"); @@ -110,7 +110,7 @@ Template.coreOrderShippingTracking.helpers({ }, editTracking() { - let template = Template.instance(); + const template = Template.instance(); if (!template.order.shipping[0].tracking || template.showTrackingEditForm.get()) { return true; } @@ -123,8 +123,8 @@ Template.coreOrderShippingTracking.helpers({ return Template.instance().order.shipping[0]; }, shipmentReady() { - let order = Template.instance().order; - let shipment = order.shipping[0]; + const order = Template.instance().order; + const shipment = order.shipping[0]; return shipment.packed && shipment.tracking; } diff --git a/imports/plugins/core/orders/client/templates/workflow/workflow.js b/imports/plugins/core/orders/client/templates/workflow/workflow.js index 71c6f74d2c5..65b747f7db1 100644 --- a/imports/plugins/core/orders/client/templates/workflow/workflow.js +++ b/imports/plugins/core/orders/client/templates/workflow/workflow.js @@ -34,7 +34,7 @@ Template.coreOrderWorkflow.helpers({ * @return {Object|Boolean} An order or false */ order() { - let id = Reaction.Router.getQueryParam("_id"); + const id = Reaction.Router.getQueryParam("_id"); if (id) { return Orders.findOne(id); } @@ -56,7 +56,7 @@ Template.coreOrderWorkflow.helpers({ * @return {String|Boolean} order completion status or false */ isCompleted() { - let order = Template.parentData(1); + const order = Template.parentData(1); if (this.status === true) { return order.workflow.status; } diff --git a/imports/plugins/core/orders/server/startup.js b/imports/plugins/core/orders/server/startup.js index 01892d6f87c..2bf9c2b2ca0 100644 --- a/imports/plugins/core/orders/server/startup.js +++ b/imports/plugins/core/orders/server/startup.js @@ -31,8 +31,8 @@ Orders.before.update((userId, order, fieldNames, modifier) => { if (modifier.$set) { // Updating status of order e.g. "coreOrderWorkflow/processing" if (modifier.$set["workflow.status"]) { - let status = modifier.$set["workflow.status"]; - let workflowMethod = `workflow/${status}`; + const status = modifier.$set["workflow.status"]; + const workflowMethod = `workflow/${status}`; if (Meteor.server.method_handlers[workflowMethod]) { const result = Meteor.call(workflowMethod, { diff --git a/imports/plugins/core/taxes/client/settings/custom.js b/imports/plugins/core/taxes/client/settings/custom.js index 669edf65491..beb1e0b212e 100644 --- a/imports/plugins/core/taxes/client/settings/custom.js +++ b/imports/plugins/core/taxes/client/settings/custom.js @@ -140,7 +140,7 @@ Template.customTaxRates.helpers({ const shop = Shops.findOne(); const instance = Template.instance(); const id = instance.state.get("editingId"); - let tax = Taxes.findOne(id) || {}; + const tax = Taxes.findOne(id) || {}; // enforce a default country that makes sense. if (!tax.country) { if (shop && typeof shop.addressBook === "object") { @@ -161,7 +161,7 @@ Template.customTaxRates.helpers({ value: "RC_NOTAX" }]; - for (let taxCode of taxCodes) { + for (const taxCode of taxCodes) { options.push({ label: i18next.t(taxCode.label), value: taxCode.id diff --git a/imports/plugins/core/taxes/client/settings/settings.js b/imports/plugins/core/taxes/client/settings/settings.js index eea7bd5cc92..4dddbacb2c8 100644 --- a/imports/plugins/core/taxes/client/settings/settings.js +++ b/imports/plugins/core/taxes/client/settings/settings.js @@ -53,7 +53,7 @@ Template.taxSettings.helpers({ value: "none" }]; - for (let taxCode of taxCodes) { + for (const taxCode of taxCodes) { options.push({ label: i18next.t(taxCode.label), value: taxCode.id @@ -104,8 +104,8 @@ Template.taxSettings.events({ * @return {void} */ "click [data-event-action=showSecret]": (event) => { - let button = $(event.currentTarget); - let input = button.closest(".form-group").find("input[name=secret]"); + const button = $(event.currentTarget); + const input = button.closest(".form-group").find("input[name=secret]"); if (input.attr("type") === "password") { input.attr("type", "text"); diff --git a/imports/plugins/core/taxes/server/methods/methods.js b/imports/plugins/core/taxes/server/methods/methods.js index f9d6da9970d..48ed1410d31 100644 --- a/imports/plugins/core/taxes/server/methods/methods.js +++ b/imports/plugins/core/taxes/server/methods/methods.js @@ -111,7 +111,7 @@ export const methods = { let customTaxRate = 0; let totalTax = 0; // lookup custom tax rate - let addressTaxData = Taxes.find( + const addressTaxData = Taxes.find( { $and: [{ $or: [{ @@ -140,7 +140,7 @@ export const methods = { } // calculate line item taxes - for (let items of cartToCalc.items) { + for (const items of cartToCalc.items) { // only processs taxable products if (items.variants.taxable === true) { const subTotal = items.variants.price * items.quantity; diff --git a/imports/plugins/core/ui-navbar/client/components/i18n/i18n.js b/imports/plugins/core/ui-navbar/client/components/i18n/i18n.js index 6ca5613618a..2ee34890b25 100644 --- a/imports/plugins/core/ui-navbar/client/components/i18n/i18n.js +++ b/imports/plugins/core/ui-navbar/client/components/i18n/i18n.js @@ -8,10 +8,10 @@ import { Template } from "meteor/templating"; Template.CoreNavigationLanguage.helpers({ languages: function () { - let languages = []; - let shop = Shops.findOne(); + const languages = []; + const shop = Shops.findOne(); if (typeof shop === "object" && shop.languages) { - for (let language of shop.languages) { + for (const language of shop.languages) { if (language.enabled === true) { language.translation = "languages." + language.label.toLowerCase(); languages.push(language); diff --git a/imports/plugins/core/ui-tagnav/client/components/tagNav/tagNav.js b/imports/plugins/core/ui-tagnav/client/components/tagNav/tagNav.js index f3f1891e08a..311d72a7c59 100644 --- a/imports/plugins/core/ui-tagnav/client/components/tagNav/tagNav.js +++ b/imports/plugins/core/ui-tagnav/client/components/tagNav/tagNav.js @@ -1,7 +1,7 @@ import Sortable from "sortablejs"; -import { TagHelpers } from "/imports/plugins/core/ui-tagnav/client/helpers"; -import { Session } from "meteor/session"; import { Template } from "meteor/templating"; +import { ReactiveDict } from "meteor/reactive-dict"; +import { TagHelpers } from "/imports/plugins/core/ui-tagnav/client/helpers"; import { IconButton } from "/imports/plugins/core/ui/client/components"; const NavbarStates = { @@ -142,13 +142,14 @@ Template.tagNav.onRendered(() => { group: "tags", handle: ".js-tagNav-item", onSort(event) { - let tagIds = instance.data.tags.map(item => { + const tagIds = instance.data.tags.map(item => { if (item) { return item._id; } + return null; }); - let newTagsOrder = instance.moveItem(tagIds, event.oldIndex, event.newIndex); + const newTagsOrder = instance.moveItem(tagIds, event.oldIndex, event.newIndex); if (newTagsOrder) { TagNavHelpers.onTagSort(newTagsOrder, instance.data.parentTag); @@ -159,10 +160,11 @@ Template.tagNav.onRendered(() => { onAdd(event) { const toListId = event.to.dataset.id; const movedTagId = event.item.dataset.id; - let tagIds = instance.data.tags.map(item => { + const tagIds = instance.data.tags.map(item => { if (item) { return item._id; } + return null; }); TagNavHelpers.onTagDragAdd(movedTagId, toListId, event.newIndex, tagIds); @@ -171,7 +173,7 @@ Template.tagNav.onRendered(() => { // Tag removed from list becuase it was dragged to a different list onRemove(event) { const movedTagId = event.item.dataset.id; - let foundTag = _.find(instance.data.tags, (tag) => { + const foundTag = _.find(instance.data.tags, (tag) => { return tag._id === movedTagId; }); diff --git a/imports/plugins/core/ui-tagnav/client/components/tagTree/tagTree.js b/imports/plugins/core/ui-tagnav/client/components/tagTree/tagTree.js index 8ef31ca55d1..c4fd6e7a03e 100644 --- a/imports/plugins/core/ui-tagnav/client/components/tagTree/tagTree.js +++ b/imports/plugins/core/ui-tagnav/client/components/tagTree/tagTree.js @@ -10,13 +10,13 @@ Template.tagTree.onRendered(() => { handle: ".js-drag-handle", draggable: ".rui.grouptag", onSort(event) { - let tagIds = instance.data.subTagGroups.map(item => { + const tagIds = instance.data.subTagGroups.map(item => { if (item) { return item._id; } }); - let newTagsOrder = TagHelpers.moveItem(tagIds, event.oldIndex, event.newIndex); + const newTagsOrder = TagHelpers.moveItem(tagIds, event.oldIndex, event.newIndex); if (newTagsOrder) { if (instance.data.onTagSort) { @@ -29,7 +29,7 @@ Template.tagTree.onRendered(() => { onAdd(event) { const toListId = event.to.dataset.id; const movedTagId = event.item.dataset.id; - let tagIds = instance.data.subTagGroups.map(item => { + const tagIds = instance.data.subTagGroups.map(item => { if (item) { return item._id; } @@ -45,7 +45,7 @@ Template.tagTree.onRendered(() => { const movedTagId = event.item.dataset.id; if (instance.data.onTagRemove) { - let foundTag = _.find(instance.data.subTagGroups, (tag) => { + const foundTag = _.find(instance.data.subTagGroups, (tag) => { return tag._id === movedTagId; }); diff --git a/imports/plugins/core/ui-tagnav/client/helpers/tags.js b/imports/plugins/core/ui-tagnav/client/helpers/tags.js index 7c2a02cd40b..6f5ab67c008 100644 --- a/imports/plugins/core/ui-tagnav/client/helpers/tags.js +++ b/imports/plugins/core/ui-tagnav/client/helpers/tags.js @@ -102,6 +102,10 @@ export const TagHelpers = { }); }, + /* eslint no-unused-vars: 0 */ + // + // TODO review toIndex, ofList variable implementation in tags.js moveTagToNewParent + // moveTagToNewParent(movedTagId, toListId, toIndex, ofList) { if (movedTagId) { if (toListId) { @@ -126,13 +130,14 @@ export const TagHelpers = { return result; } + return 0; }, sortTags(tagIds, parentTag) { if (_.isArray(tagIds)) { if (_.isEmpty(parentTag)) { // Top level tags - for (let tagId of tagIds) { + for (const tagId of tagIds) { Tags.update(tagId, { $set: { position: tagIds.indexOf(tagId) diff --git a/imports/plugins/core/ui/client/components/button/button.js b/imports/plugins/core/ui/client/components/button/button.js index 2e3820c7d19..18ebc117555 100644 --- a/imports/plugins/core/ui/client/components/button/button.js +++ b/imports/plugins/core/ui/client/components/button/button.js @@ -1,8 +1,8 @@ import _ from "lodash"; +import Tooltip from "tether-tooltip"; import { Template } from "meteor/templating"; import { i18next, i18nextDep } from "/client/api"; import { Icon } from "/imports/plugins/core/ui/client/components"; -import Tooltip from "tether-tooltip"; Template.button.onRendered(function () { const buttonElement = this.$("button, a")[0]; @@ -26,6 +26,10 @@ Template.button.onRendered(function () { }); }); +/* eslint no-unused-vars: 1 */ +// +// TODO review Template.button helpers for unused elementProps +// Template.button.helpers({ iconComponent() { return Icon; diff --git a/imports/plugins/core/ui/client/components/button/iconButton.js b/imports/plugins/core/ui/client/components/button/iconButton.js index 72c42ee2b82..657163a71a5 100644 --- a/imports/plugins/core/ui/client/components/button/iconButton.js +++ b/imports/plugins/core/ui/client/components/button/iconButton.js @@ -1,3 +1,7 @@ +/* eslint no-unused-vars: 1 */ +// +// TODO review PropTypes import in iconButton.js +// import React, { Component, PropTypes } from "react"; import classnames from "classnames"; import Button from "./button.jsx"; @@ -15,7 +19,7 @@ class IconButton extends Component { "rui": true, "button": true, "edit": true, - "variant-edit": true, + "variant-edit": true // "btn-success": isEditing }); diff --git a/imports/plugins/core/ui/client/components/tags/tagItem.html b/imports/plugins/core/ui/client/components/tags/tagItem.html index 89ca6cc1863..4332e55df2a 100644 --- a/imports/plugins/core/ui/client/components/tags/tagItem.html +++ b/imports/plugins/core/ui/client/components/tags/tagItem.html @@ -22,12 +22,9 @@
{{> button icon="tag"}} - {{> textfield - name="tag" - onChange=handleTagNameUpdate - placeholder=(i18n "tags.addTag" "Add Tag") - value=tag.name - }} +
+ {{> React AutosuggestInput}} +
{{> button type="submit" icon="plus" status="danger" onClick=handleTagRemove}}
@@ -37,7 +34,9 @@
{{> button icon="bars" className="js-drag-handle" status="default"}} - {{> textfield name="tag" value=tag.name onChange=handleTagNameUpdate}} +
+ {{> React AutosuggestInput}} +
{{#if controls}} {{#each control in controls}} diff --git a/imports/plugins/core/ui/client/components/tags/tagItem.js b/imports/plugins/core/ui/client/components/tags/tagItem.js index fcbcb760ccd..0facd3fb7dd 100644 --- a/imports/plugins/core/ui/client/components/tags/tagItem.js +++ b/imports/plugins/core/ui/client/components/tags/tagItem.js @@ -1,9 +1,62 @@ -import $ from "jquery"; import { Reaction } from "/client/api"; import { Tags } from "/lib/collections"; +import { i18next } from "/client/api"; import classnames from "classnames"; +import Autosuggest from "react-autosuggest"; +import { ReactiveDict } from "meteor/reactive-dict"; +import React from "react"; + +function createAutosuggestInput(templateInstance, options) { + return { + component: Autosuggest, + suggestions: templateInstance.state.get("suggestions"), + getSuggestionValue: getSuggestionValue, + renderSuggestion: renderSuggestion, + onSuggestionsUpdateRequested({ value }) { + templateInstance.state.set("suggestions", getSuggestions(value)); + }, + inputProps: { + placeholder: i18next.t(options.i18nPlaceholderKey, { defaultValue: options.i18nPlaceholderValue}), + value: templateInstance.state.get("inputValue"), + onKeyDown(event) { + // 9 == Tab key + // 13 == Enter Key + if (event.keyCode === 9 || event.keyCode === 13) { + options.onUpdateCallback && options.onUpdateCallback(); + } + }, + onBlur: () => { + options.onUpdateCallback && options.onUpdateCallback(); + }, + onChange(event, { newValue }) { + templateInstance.state.set("suggestion", getSuggestions(newValue)); + templateInstance.state.set("inputValue", newValue); + } + } + }; +} + +function getSuggestions(term) { + const datums = []; + const slug = Reaction.getSlug(term); + Tags.find({ + slug: new RegExp(slug, "i") + }).forEach(function (tag) { + return datums.push({ + label: tag.name + }); + }); + + return datums; +} + +function getSuggestionValue(suggestion) { + return suggestion.label; +} -require("jquery-ui"); +function renderSuggestion(suggestion) { + return React.createElement("span", null, suggestion.label); +} Template.tagItem.helpers({ tagBlankProps() { @@ -29,6 +82,7 @@ Template.tagItem.helpers({ return control.toggleOn; } + return undefined; }, onClick(event) { // Call the original onClick and add the current tag @@ -47,51 +101,47 @@ Template.tagItem.helpers({ }); Template.tagEditable.onCreated(function () { - // this.autorun(() => { - // new SimpleSchema({ - // tag: {type: } - // }) - // }) -}); + this.state = new ReactiveDict(); + this.state.setDefault({ + oldValue: this.data.tag.name, + inputValue: this.data.tag.name, + suggestions: [] + }); -Template.tagEditable.onRendered(function () { - const instance = Template.instance(); - const textInput = instance.$("input")[0]; - - $(textInput).autocomplete({ - delay: 0, - source: function (request, response) { - let datums = []; - let slug = Reaction.getSlug(request.term); - Tags.find({ - slug: new RegExp(slug, "i") - }).forEach(function (tag) { - return datums.push({ - label: tag.name - }); - }); - return response(datums); - }, - select: (selectEvent, ui) => { - if (ui.item.value) { - if (instance.data.onTagUpdate) { - instance.data.onTagUpdate(instance.data.tag._id, ui.item.value); - } - } + this.submitInput = () => { + const value = this.state.get("inputValue").trim(); + + if (this.data.onTagCreate && _.isEmpty(value) === false) { + this.data.onTagCreate(value); } - }); + + this.state.set("inputValue", ""); + }; this.updateTag = () => { - const input = instance.$("input"); - const value = input.val().trim(); + const inputValue = this.state.get("inputValue"); + if (this.state.equals("oldValue", inputValue) === false) { + const value = inputValue.trim(); - if (this.data.onTagUpdate && _.isEmpty(value) === false) { - this.data.onTagUpdate(this.data.tag._id, value); + if (this.data.onTagUpdate && _.isEmpty(value) === false) { + this.data.onTagUpdate(this.data.tag._id, value); + this.state.set("oldValue", inputValue); + } } }; }); Template.tagEditable.helpers({ + AutosuggestInput() { + const instance = Template.instance(); + + return createAutosuggestInput(instance, { + i18nPlaceholderKey: "tags.updateTag", + i18nPlaceholderValue: "Update Tag", + onUpdateCallback: instance.updateTag + }); + }, + className() { const instance = Template.instance(); @@ -120,71 +170,32 @@ Template.tagEditable.helpers({ } }); -Template.tagEditable.events({ - "blur input"(event, instance) { - instance.updateTag(); - }, - - "keydown input"(event, instance) { - // 9 == Tab key - // 13 == Enter Key - if (event.keyCode === 9 || event.keyCode === 13) { - instance.updateTag(); - } - } -}); - -Template.tagBlank.onRendered(function () { - const instance = Template.instance(); - const textInput = instance.$("input")[0]; - - $(textInput).autocomplete({ - delay: 0, - source: function (request, response) { - let datums = []; - let slug = Reaction.getSlug(request.term); - Tags.find({ - slug: new RegExp(slug, "i") - }).forEach(function (tag) { - return datums.push({ - label: tag.name - }); - }); - return response(datums); - }, - select: (selectEvent, ui) => { - if (ui.item.value) { - if (instance.data.onTagUpdate) { - instance.data.onTagUpdate(instance.data.tag._id, ui.item.value); - } - } - } +Template.tagBlank.onCreated(function () { + this.state = new ReactiveDict(); + this.state.setDefault({ + inputValue: "", + suggestions: [] }); this.submitInput = () => { - const input = instance.$("input"); - const value = input.val().trim(); + const value = this.state.get("inputValue").trim(); if (this.data.onTagCreate && _.isEmpty(value) === false) { this.data.onTagCreate(value); } - input.val(""); + this.state.set("inputValue", ""); }; }); -Template.tagBlank.helpers({}); - -Template.tagBlank.events({ - "blur input"(event, instance) { - instance.submitInput(); - }, +Template.tagBlank.helpers({ + AutosuggestInput() { + const instance = Template.instance(); - "keydown input"(event, instance) { - // 9 == Tab key - // 13 == Enter Key - if (event.keyCode === 9 || event.keyCode === 13) { - instance.submitInput(); - } + return createAutosuggestInput(instance, { + i18nPlaceholderKey: "tags.addTag", + i18nPlaceholderValue: "Add Tag", + onUpdateCallback: instance.submitInput + }); } }); diff --git a/imports/plugins/core/ui/client/components/tags/tagList.js b/imports/plugins/core/ui/client/components/tags/tagList.js index fb3a612eb23..f9fc7f36b98 100644 --- a/imports/plugins/core/ui/client/components/tags/tagList.js +++ b/imports/plugins/core/ui/client/components/tags/tagList.js @@ -17,13 +17,13 @@ Template.tagList.onRendered(() => { draggable: ".rui.item.draggable", // filter: ".rui.tag.edit.create", onSort(event) { - let tagIds = instance.data.tags.map(item => { + const tagIds = instance.data.tags.map(item => { if (item) { return item._id; } }); - let newTagsOrder = instance.moveItem(tagIds, event.oldIndex, event.newIndex); + const newTagsOrder = instance.moveItem(tagIds, event.oldIndex, event.newIndex); if (newTagsOrder) { if (instance.data.onTagSort) { @@ -36,7 +36,7 @@ Template.tagList.onRendered(() => { onAdd(event) { const toListId = event.to.dataset.id; const movedTagId = event.item.dataset.id; - let tagIds = instance.data.tags.map(item => { + const tagIds = instance.data.tags.map(item => { if (item) { return item._id; } @@ -52,7 +52,7 @@ Template.tagList.onRendered(() => { const movedTagId = event.item.dataset.id; if (instance.data.onTagRemove) { - let foundTag = _.find(instance.data.tags, (tag) => { + const foundTag = _.find(instance.data.tags, (tag) => { return tag._id === movedTagId; }); diff --git a/imports/plugins/core/ui/client/components/upload/upload.js b/imports/plugins/core/ui/client/components/upload/upload.js index d60ef445e62..02d6a85cd10 100644 --- a/imports/plugins/core/ui/client/components/upload/upload.js +++ b/imports/plugins/core/ui/client/components/upload/upload.js @@ -3,7 +3,7 @@ */ function uploadHandler(event, instance) { - let files = []; + const files = []; FS.Utility.eachFile(event, (file) => { files.push(new FS.File(file)); diff --git a/imports/plugins/core/ui/client/templates/themeEditor/themeEditor.js b/imports/plugins/core/ui/client/templates/themeEditor/themeEditor.js index a94ec9e440c..0c8a156134e 100644 --- a/imports/plugins/core/ui/client/templates/themeEditor/themeEditor.js +++ b/imports/plugins/core/ui/client/templates/themeEditor/themeEditor.js @@ -39,7 +39,7 @@ Template.uiThemeEditor.onCreated(function () { const annotations = {}; - for (let annotation of component.annotations) { + for (const annotation of component.annotations) { if (annotation.rule) { annotations[annotation.rule] = annotation; } @@ -51,7 +51,7 @@ Template.uiThemeEditor.onCreated(function () { this.previewTheme = (theme) => { let output = ""; - for (let component of theme.components) { + for (const component of theme.components) { output += component.styles; } $("#reactionLayoutStyles").text(output); diff --git a/imports/plugins/included/analytics/client/startup.js b/imports/plugins/included/analytics/client/startup.js index 2cab6d0da75..1ded80b1439 100644 --- a/imports/plugins/included/analytics/client/startup.js +++ b/imports/plugins/included/analytics/client/startup.js @@ -2,7 +2,7 @@ import _ from "lodash"; import { Meteor } from "meteor/meteor"; import { Tracker } from "meteor/tracker"; import { AnalyticsEvents, Packages } from "/lib/collections"; -import { Reaction, i18next } from "/client/api"; +import { Reaction, i18next, Logger } from "/client/api"; // Create a queue, but don't obliterate an existing one! analytics = window.analytics = window.analytics || []; @@ -12,9 +12,7 @@ if (analytics.initialize) return; // If the snippet was invoked already show an error. if (analytics.invoked) { - if (window.console && console.error) { - console.error("Segment snippet included twice."); - } + Logger.warn("Segment snippet included twice."); return; } @@ -47,7 +45,7 @@ analytics.methods = [ // stored as the first argument, so we can replay the data. analytics.factory = function (method) { return function () { - let args = Array.prototype.slice.call(arguments); + const args = Array.prototype.slice.call(arguments); args.unshift(method); analytics.push(args); return analytics; @@ -64,7 +62,7 @@ for (let i = 0; i < analytics.methods.length; i++) { // and that will be sure to only ever load it once. analytics.load = function (key) { // Create an async script element based on your key. - let script = document.createElement("script"); + const script = document.createElement("script"); script.type = "text/javascript"; script.async = true; script.src = (document.location.protocol === "https:" ? "https://" : "http://") + @@ -198,6 +196,7 @@ Meteor.startup(function () { if (!Reaction.hasAdminAccess()) { return Alerts.removeType("analytics-not-configured"); } + return null; }); // @@ -207,7 +206,7 @@ Meteor.startup(function () { let $targets = $(e.target).closest("*[data-event-action]"); $targets = $targets.parents("*[data-event-action]").add($targets); return $targets.each(function (index, element) { - let $element = $(element); + const $element = $(element); const analyticsEvent = { eventType: "event", category: $element.data("event-category"), diff --git a/imports/plugins/included/analytics/client/templates/reactionAnalytics.js b/imports/plugins/included/analytics/client/templates/reactionAnalytics.js index 3e441f95bdb..0c9e428ac81 100644 --- a/imports/plugins/included/analytics/client/templates/reactionAnalytics.js +++ b/imports/plugins/included/analytics/client/templates/reactionAnalytics.js @@ -26,7 +26,7 @@ AutoForm.hooks({ return Alerts.toast(i18next.t("admin.settings.analyticsSettingsSaved"), "success"); }, onError(operation, error) { - let msg = error.message || error.reason || "Unknown error"; + const msg = error.message || error.reason || "Unknown error"; return Alerts.toast(`${i18next.t("admin.settings.analyticsSettingsFailed")} ${msg}`, "error"); } } diff --git a/imports/plugins/included/authnet/client/checkout/authnet.js b/imports/plugins/included/authnet/client/checkout/authnet.js index 84343cb0c7d..02da62f04a0 100644 --- a/imports/plugins/included/authnet/client/checkout/authnet.js +++ b/imports/plugins/included/authnet/client/checkout/authnet.js @@ -43,10 +43,10 @@ AutoForm.addHooks("authnet-payment-form", { onSubmit(doc) { // Process form (pre-validated by autoform) submitting = true; - let tpl = this.template; + const tpl = this.template; // regEx in the schema ensures that there will be exactly two names with one space between - let payerNamePieces = doc.payerName.split(" "); - let form = { + const payerNamePieces = doc.payerName.split(" "); + const form = { first_name: payerNamePieces[0], last_name: payerNamePieces[1], number: doc.cardNumber, @@ -77,7 +77,7 @@ AutoForm.addHooks("authnet-payment-form", { handleAuthNetSubmitError(error); uiEnd(tpl, "Resubmit payment"); } else { - let normalizedMode = "authorize"; + const normalizedMode = "authorize"; let normalizedStatus = "failed"; const transId = transaction.transactionId[0].toString(); @@ -86,7 +86,7 @@ AutoForm.addHooks("authnet-payment-form", { normalizedStatus = "created"; } - let paymentMethod = { + const paymentMethod = { processor: "AuthNet", storedCard: storedCard, method: "credit_card", diff --git a/imports/plugins/included/authnet/server/methods/authnet.js b/imports/plugins/included/authnet/server/methods/authnet.js index 726c7ba0aab..bbe81e9c86d 100644 --- a/imports/plugins/included/authnet/server/methods/authnet.js +++ b/imports/plugins/included/authnet/server/methods/authnet.js @@ -12,12 +12,12 @@ import { Packages } from "/lib/collections"; import { PaymentMethod } from "/lib/collections/schemas"; function getAccountOptions() { - let settings = Packages.findOne({ + const settings = Packages.findOne({ name: "reaction-auth-net", shopId: Reaction.getShopId(), enabled: true }).settings; - let ref = Meteor.settings.authnet; + const ref = Meteor.settings.authnet; let options; options = { @@ -148,7 +148,7 @@ Meteor.methods({ "authnet/refund/create": function (paymentMethod, amount) { check(paymentMethod, PaymentMethod); check(amount, Number); - let result = { + const result = { saved: false, error: "Reaction does not yet support direct refund processing from Authorize.net. " + "Please visit their web portal to perform this action." @@ -176,25 +176,25 @@ function getAuthnetService(accountOptions) { } function priorAuthCaptureTransaction(transId, amount, service) { - let body = { + const body = { transactionType: "priorAuthCaptureTransaction", amount: amount, refTransId: transId }; // This call returns a Promise to the cb so we need to use Promise.await - let transactionRequest = service.sendTransactionRequest.call(service, body, function (trans) { + const transactionRequest = service.sendTransactionRequest.call(service, body, function (trans) { return trans; }); return Promise.await(transactionRequest); } function voidTransaction(transId, service) { - let body = { + const body = { transactionType: "voidTransaction", refTransId: transId }; // This call returns a Promise to the cb so we need to use Promise.await - let transactionRequest = service.sendTransactionRequest.call(service, body, function (trans) { + const transactionRequest = service.sendTransactionRequest.call(service, body, function (trans) { return trans; }); return Promise.await(transactionRequest); diff --git a/imports/plugins/included/braintree/client/checkout/braintree.js b/imports/plugins/included/braintree/client/checkout/braintree.js index cf9e8ddde24..fd50a430a5b 100644 --- a/imports/plugins/included/braintree/client/checkout/braintree.js +++ b/imports/plugins/included/braintree/client/checkout/braintree.js @@ -30,7 +30,7 @@ hidePaymentAlert = function () { }; handleBraintreeSubmitError = function (error) { - let serverError = error !== null ? error.message : void 0; + const serverError = error !== null ? error.message : void 0; if (serverError) { return paymentAlert("Server Error " + serverError); } else if (error) { @@ -43,7 +43,7 @@ let submitting = false; submitToBrainTree = function (doc, template) { submitting = true; hidePaymentAlert(); - let cardData = { + const cardData = { name: doc.payerName, number: doc.cardNumber, expirationMonth: doc.expireMonth, @@ -51,8 +51,8 @@ submitToBrainTree = function (doc, template) { cvv2: doc.cvv, type: getCardType(doc.cardNumber) }; - let cartTotal = Cart.findOne().cartTotal(); - let currencyCode = Shops.findOne().currency; + const cartTotal = Cart.findOne().cartTotal(); + const currencyCode = Shops.findOne().currency; Braintree.authorize(cardData, { total: cartTotal, @@ -65,9 +65,9 @@ submitToBrainTree = function (doc, template) { uiEnd(template, "Resubmit payment"); } else { if (results.saved === true) { - let normalizedStatus = normalizeState(results.response.transaction.status); - let normalizedMode = normalizeMode(results.response.transaction.status); - let storedCard = results.response.transaction.creditCard.cardType.toUpperCase() + " " + results.response.transaction.creditCard.last4; + const normalizedStatus = normalizeState(results.response.transaction.status); + const normalizedMode = normalizeMode(results.response.transaction.status); + const storedCard = results.response.transaction.creditCard.cardType.toUpperCase() + " " + results.response.transaction.creditCard.last4; paymentMethod = { processor: "Braintree", storedCard: storedCard, diff --git a/imports/plugins/included/braintree/client/settings/braintree.js b/imports/plugins/included/braintree/client/settings/braintree.js index 6ae583ddf5b..e5762f73aef 100644 --- a/imports/plugins/included/braintree/client/settings/braintree.js +++ b/imports/plugins/included/braintree/client/settings/braintree.js @@ -20,7 +20,7 @@ Template.braintreeSettings.helpers({ Template.braintree.helpers({ packageData: function () { - let packageData = Packages.findOne({ + const packageData = Packages.findOne({ name: "reaction-braintree" }); return packageData; diff --git a/imports/plugins/included/braintree/server/methods/braintreeApi.js b/imports/plugins/included/braintree/server/methods/braintreeApi.js index fe345fad41a..7adbd554351 100644 --- a/imports/plugins/included/braintree/server/methods/braintreeApi.js +++ b/imports/plugins/included/braintree/server/methods/braintreeApi.js @@ -41,7 +41,7 @@ function getSettings(settings, ref, valueName) { function getAccountOptions() { let environment; - let settings = Packages.findOne({ + const settings = Packages.findOne({ name: "reaction-braintree", shopId: Reaction.getShopId(), enabled: true @@ -52,8 +52,8 @@ function getAccountOptions() { environment = "sandbox"; } - let ref = Meteor.settings.braintree; - let options = { + const ref = Meteor.settings.braintree; + const options = { environment: environment, merchantId: getSettings(settings, ref, "merchant_id"), publicKey: getSettings(settings, ref, "public_key"), @@ -66,34 +66,34 @@ function getAccountOptions() { } function getGateway() { - let accountOptions = getAccountOptions(); + const accountOptions = getAccountOptions(); if (accountOptions.environment === "production") { accountOptions.environment = Braintree.Environment.Production; } else { accountOptions.environment = Braintree.Environment.Sandbox; } - let gateway = Braintree.connect(accountOptions); + const gateway = Braintree.connect(accountOptions); return gateway; } getRefundDetails = function (refundId) { check(refundId, String); - let gateway = getGateway(); - let braintreeFind = Meteor.wrapAsync(gateway.transaction.find, gateway.transaction); - let findResults = braintreeFind(refundId); + const gateway = getGateway(); + const braintreeFind = Meteor.wrapAsync(gateway.transaction.find, gateway.transaction); + const findResults = braintreeFind(refundId); return findResults; }; BraintreeApi.apiCall.paymentSubmit = function (paymentSubmitDetails) { - let gateway = getGateway(); - let paymentObj = getPaymentObj(); + const gateway = getGateway(); + const paymentObj = getPaymentObj(); if (paymentSubmitDetails.transactionType === "authorize") { paymentObj.options.submitForSettlement = false; } paymentObj.creditCard = parseCardData(paymentSubmitDetails.cardData); paymentObj.amount = paymentSubmitDetails.paymentData.total; - let fut = new Future(); + const fut = new Future(); gateway.transaction.sale(paymentObj, Meteor.bindEnvironment(function (error, result) { if (error) { fut.return({ @@ -120,9 +120,9 @@ BraintreeApi.apiCall.paymentSubmit = function (paymentSubmitDetails) { BraintreeApi.apiCall.captureCharge = function (paymentCaptureDetails) { - let transactionId = paymentCaptureDetails.transactionId; - let amount = accounting.toFixed(paymentCaptureDetails.amount, 2); - let gateway = getGateway(); + const transactionId = paymentCaptureDetails.transactionId; + const amount = accounting.toFixed(paymentCaptureDetails.amount, 2); + const gateway = getGateway(); const fut = new Future(); if (amount === accounting.toFixed(0, 2)) { @@ -164,9 +164,9 @@ BraintreeApi.apiCall.captureCharge = function (paymentCaptureDetails) { BraintreeApi.apiCall.createRefund = function (refundDetails) { - let transactionId = refundDetails.transactionId; - let amount = refundDetails.amount; - let gateway = getGateway(); + const transactionId = refundDetails.transactionId; + const amount = refundDetails.amount; + const gateway = getGateway(); const fut = new Future(); gateway.transaction.refund(transactionId, amount, Meteor.bindEnvironment(function (error, result) { if (error) { @@ -200,14 +200,14 @@ BraintreeApi.apiCall.createRefund = function (refundDetails) { BraintreeApi.apiCall.listRefunds = function (refundListDetails) { - let transactionId = refundListDetails.transactionId; - let gateway = getGateway(); - let braintreeFind = Meteor.wrapAsync(gateway.transaction.find, gateway.transaction); - let findResults = braintreeFind(transactionId); - let result = []; + const transactionId = refundListDetails.transactionId; + const gateway = getGateway(); + const braintreeFind = Meteor.wrapAsync(gateway.transaction.find, gateway.transaction); + const findResults = braintreeFind(transactionId); + const result = []; if (findResults.refundIds.length > 0) { - for (let refund of findResults.refundIds) { - let refundDetails = getRefundDetails(refund); + for (const refund of findResults.refundIds) { + const refundDetails = getRefundDetails(refund); result.push({ type: "refund", amount: parseFloat(refundDetails.amount), diff --git a/imports/plugins/included/braintree/server/methods/braintreeMethods.js b/imports/plugins/included/braintree/server/methods/braintreeMethods.js index 2e6d2a1d96b..bd9702eb987 100644 --- a/imports/plugins/included/braintree/server/methods/braintreeMethods.js +++ b/imports/plugins/included/braintree/server/methods/braintreeMethods.js @@ -35,7 +35,7 @@ export function paymentSubmit(transactionType, cardData, paymentData) { let result; try { - let paymentSubmitResult = BraintreeApi.apiCall.paymentSubmit(paymentSubmitDetails); + const paymentSubmitResult = BraintreeApi.apiCall.paymentSubmit(paymentSubmitDetails); Logger.debug(paymentSubmitResult); result = paymentSubmitResult; } catch (error) { @@ -69,7 +69,7 @@ export function paymentCapture(paymentMethod) { let result; try { - let paymentCaptureResult = BraintreeApi.apiCall.captureCharge(paymentCaptureDetails); + const paymentCaptureResult = BraintreeApi.apiCall.captureCharge(paymentCaptureDetails); Logger.debug(paymentCaptureResult); result = paymentCaptureResult; } catch (error) { @@ -105,7 +105,7 @@ export function createRefund(paymentMethod, amount) { let result; try { - let refundResult = BraintreeApi.apiCall.createRefund(refundDetails); + const refundResult = BraintreeApi.apiCall.createRefund(refundDetails); Logger.debug(refundResult); result = refundResult; } catch (error) { @@ -138,7 +138,7 @@ export function listRefunds(paymentMethod) { let result; try { - let refundListResult = BraintreeApi.apiCall.listRefunds(refundListDetails); + const refundListResult = BraintreeApi.apiCall.listRefunds(refundListDetails); Logger.debug(refundListResult); result = refundListResult; } catch (error) { diff --git a/imports/plugins/included/braintree/server/methods/braintreeapi-methods-refund.app-test.js b/imports/plugins/included/braintree/server/methods/braintreeapi-methods-refund.app-test.js index b362fa672a8..2da1fc6bfa5 100644 --- a/imports/plugins/included/braintree/server/methods/braintreeapi-methods-refund.app-test.js +++ b/imports/plugins/included/braintree/server/methods/braintreeapi-methods-refund.app-test.js @@ -16,7 +16,7 @@ describe("braintree/refund/create", function () { }); it("Should call braintree/refund/create with the proper parameters and return saved = true", function (done) { - let paymentMethod = { + const paymentMethod = { processor: "Braintree", storedCard: "VISA 4242", method: "Visa", @@ -32,7 +32,7 @@ describe("braintree/refund/create", function () { metadata: {} }; - let braintreeRefundResult = { + const braintreeRefundResult = { saved: true, response: { transaction: { diff --git a/imports/plugins/included/default-theme/client/favicons.js b/imports/plugins/included/default-theme/client/favicons.js index 6a1cb1ceea0..31adbc0a402 100644 --- a/imports/plugins/included/default-theme/client/favicons.js +++ b/imports/plugins/included/default-theme/client/favicons.js @@ -64,7 +64,7 @@ const metaTags = [ */ function addTag(type, details) { let props = ""; - for (let key in details) { + for (const key in details) { if ({}.hasOwnProperty.call(details, key)) { props += `${key}="${details[key]}" `; } diff --git a/imports/plugins/included/default-theme/client/styles/cart/cartIcon.less b/imports/plugins/included/default-theme/client/styles/cart/cartIcon.less index 874f2cfc7fc..ff1b18fd015 100644 --- a/imports/plugins/included/default-theme/client/styles/cart/cartIcon.less +++ b/imports/plugins/included/default-theme/client/styles/cart/cartIcon.less @@ -7,7 +7,7 @@ position: relative; background-color: @cart-icon-bg; height: @navbar-height; - + a i { color: @cart-icon-color; background-color: transparent; @@ -47,21 +47,20 @@ padding: @navbar-padding-vertical; height: @navbar-height; min-width: 225px; - white-space: nowrap; - text-align: center; + max-width: 300px; } .cart-alert-checkout { height: @navbar-height; padding-left: @navbar-padding-vertical; padding-right: @navbar-padding-vertical; min-width: 225px; + max-width: 300px; white-space: nowrap; } } .navbar-cart:hover{ cursor: pointer; - // background-color: @body-bg; text-decoration: none; margin: 0px; padding: 0px; diff --git a/imports/plugins/included/default-theme/client/styles/dashboard/console.less b/imports/plugins/included/default-theme/client/styles/dashboard/console.less index 0db43993269..0c5722c9e2c 100644 --- a/imports/plugins/included/default-theme/client/styles/dashboard/console.less +++ b/imports/plugins/included/default-theme/client/styles/dashboard/console.less @@ -12,7 +12,7 @@ overflow: hidden; .transition(width 300ms cubic-bezier(0.455, 0.03, 0.515, 0.955)); box-shadow: 0 0 40px rgba(0,0,0,.1); - z-index: 1; + z-index: 100; @media screen and (max-width: @screen-xs-max) { transition: top 400ms cubic-bezier(0.645, 0.045, 0.355, 1); diff --git a/imports/plugins/included/default-theme/client/styles/products/productDetail.less b/imports/plugins/included/default-theme/client/styles/products/productDetail.less index d0e8d785107..2f674672c3a 100644 --- a/imports/plugins/included/default-theme/client/styles/products/productDetail.less +++ b/imports/plugins/included/default-theme/client/styles/products/productDetail.less @@ -192,7 +192,7 @@ } .pdp-container .rui.tags > .rui.item input { - width: 0; + width: 100%; } // Add to cart button diff --git a/imports/plugins/included/default-theme/client/styles/tagNav.less b/imports/plugins/included/default-theme/client/styles/tagNav.less index cf78fb7e987..eaab5c5dfdf 100644 --- a/imports/plugins/included/default-theme/client/styles/tagNav.less +++ b/imports/plugins/included/default-theme/client/styles/tagNav.less @@ -168,7 +168,7 @@ .display(flex); .flex(1 1 auto); height: 100%; - overflow-y: auto; + overflow-y: visible; } // -- Vertical @@ -176,6 +176,7 @@ display: block; width: 100%; padding: 20px 0; + overflow-y: auto; } // Single navbar item diff --git a/imports/plugins/included/default-theme/client/styles/tags.less b/imports/plugins/included/default-theme/client/styles/tags.less index 388c85ee17a..f7595048c78 100644 --- a/imports/plugins/included/default-theme/client/styles/tags.less +++ b/imports/plugins/included/default-theme/client/styles/tags.less @@ -13,20 +13,28 @@ } .rui.tag.edit { + height: 33px; padding: 0; } +.rui.tag.edit .autosuggest-wrapper, +.rui.tag.edit .react-autosuggest__container { + width: 100%; + height: 100%; +} + .rui.tag.edit form { display: flex; width: 100%; } .rui.tag.edit input { + height: 100%; padding: @padding-base-vertical @padding-base-horizontal; border-radius: 0; background-color: @white; - border-color: @border-color; + border: 1px solid @border-color; border-left: none; } @@ -65,3 +73,60 @@ html.rtl .rui.tag.edit button:last-child { color: @btn-success-bg; } } + +// Autosuggest + +.react-autosuggest__container { + position: relative; +} + +.react-autosuggest__input {} + +.react-autosuggest__input:focus { + outline: none; +} + +.react-autosuggest__container--open .react-autosuggest__input { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.react-autosuggest__suggestions-container { + display: none; +} + +.react-autosuggest__container--open .react-autosuggest__suggestions-container { + display: block; + position: absolute; + top: 100%; + left: 0; + width: 100%; + min-width: 150px; + border: 1px solid @border-color; + background-color: #fff; + color: @text-color; + font-size: 14px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + z-index: @zindex-navbar; +} + +.react-autosuggest__suggestions-list { + margin: 0; + padding: 0; + list-style-type: none; +} + +.react-autosuggest__suggestions-list li { + padding: 2px 5px; + list-style-type: none; +} + +.react-autosuggest__suggestion { + cursor: pointer; + padding: 10px 20px; +} + +.react-autosuggest__suggestion--focused { + background-color: #ddd; +} diff --git a/imports/plugins/included/example-paymentmethod/client/checkout/example.js b/imports/plugins/included/example-paymentmethod/client/checkout/example.js index 7b48bbb98d0..e9a105f7eee 100644 --- a/imports/plugins/included/example-paymentmethod/client/checkout/example.js +++ b/imports/plugins/included/example-paymentmethod/client/checkout/example.js @@ -23,7 +23,7 @@ function hidePaymentAlert() { } function handleExampleSubmitError(error) { - let serverError = error !== null ? error.message : void 0; + const serverError = error !== null ? error.message : void 0; if (serverError) { return paymentAlert("Oops! " + serverError); } else if (error) { @@ -41,9 +41,9 @@ Template.examplePaymentForm.helpers({ AutoForm.addHooks("example-payment-form", { onSubmit: function (doc) { submitting = true; - let template = this.template; + const template = this.template; hidePaymentAlert(); - let form = { + const form = { name: doc.payerName, number: doc.cardNumber, expireMonth: doc.expireMonth, diff --git a/imports/plugins/included/example-paymentmethod/client/settings/example.js b/imports/plugins/included/example-paymentmethod/client/settings/example.js index fc70f94a798..2bda19b42fa 100644 --- a/imports/plugins/included/example-paymentmethod/client/settings/example.js +++ b/imports/plugins/included/example-paymentmethod/client/settings/example.js @@ -36,11 +36,11 @@ Template.example.events({ AutoForm.hooks({ "example-update-form": { - onSuccess: function (operation, result, template) { + onSuccess: function () { Alerts.removeSeen(); return Alerts.add("Example Payment Method settings saved.", "success"); }, - onError: function (operation, error, template) { + onError: function (operation, error) { Alerts.removeSeen(); return Alerts.add("Example Payment Method settings update failed. " + error, "danger"); } diff --git a/imports/plugins/included/example-paymentmethod/server/methods/example-payment-methods.app-test.js b/imports/plugins/included/example-paymentmethod/server/methods/example-payment-methods.app-test.js index 2a6a5fcbe2b..906f4af85ac 100644 --- a/imports/plugins/included/example-paymentmethod/server/methods/example-payment-methods.app-test.js +++ b/imports/plugins/included/example-paymentmethod/server/methods/example-payment-methods.app-test.js @@ -4,7 +4,7 @@ import { sinon } from "meteor/practicalmeteor:sinon"; import { ExampleApi } from "./exampleapi"; -let paymentMethod = { +const paymentMethod = { processor: "Generic", storedCard: "Visa 4242", status: "captured", @@ -25,7 +25,7 @@ describe("ExampleApi", function () { }); it("should return data from ThirdPartyAPI authorize", function () { - let cardData = { + const cardData = { name: "Test User", number: "4242424242424242", expireMonth: "2", @@ -33,13 +33,13 @@ describe("ExampleApi", function () { cvv2: "123", type: "visa" }; - let paymentData = { + const paymentData = { currency: "USD", total: "19.99" }; - let transactionType = "authorize"; - let transaction = ExampleApi.methods.authorize.call({ + const transactionType = "authorize"; + const transaction = ExampleApi.methods.authorize.call({ transactionType: transactionType, cardData: cardData, paymentData: paymentData @@ -48,9 +48,9 @@ describe("ExampleApi", function () { }); it("should return data from ThirdPartAPI capture", function (done) { - let authorizationId = "abc123"; - let amount = 19.99; - let results = ExampleApi.methods.capture.call({ + const authorizationId = "abc123"; + const amount = 19.99; + const results = ExampleApi.methods.capture.call({ authorizationId: authorizationId, amount: amount }); @@ -73,7 +73,7 @@ describe("Submit payment", function () { it("should call Example API with card and payment data", function () { this.timeout(3000); - let cardData = { + const cardData = { name: "Test User", number: "4242424242424242", expireMonth: "2", @@ -81,18 +81,18 @@ describe("Submit payment", function () { cvv2: "123", type: "visa" }; - let paymentData = { + const paymentData = { currency: "USD", total: "19.99" }; - let authorizeResult = { + const authorizeResult = { saved: true, currency: "USD" }; - let authorizeStub = sandbox.stub(ExampleApi.methods.authorize, "call", () => authorizeResult); - let results = Meteor.call("exampleSubmit", "authorize", cardData, paymentData); + const authorizeStub = sandbox.stub(ExampleApi.methods.authorize, "call", () => authorizeResult); + const results = Meteor.call("exampleSubmit", "authorize", cardData, paymentData); expect(authorizeStub).to.have.been.calledWith({ transactionType: "authorize", cardData: cardData, @@ -102,13 +102,13 @@ describe("Submit payment", function () { }); it("should throw an error if card data is not correct", function () { - let badCardData = { + const badCardData = { name: "Test User", cvv2: "123", type: "visa" }; - let paymentData = { + const paymentData = { currency: "USD", total: "19.99" }; @@ -133,13 +133,13 @@ describe("Capture payment", function () { }); it("should call ExampleApi with transaction ID", function () { - let captureResults = { success: true }; - let authorizationId = "abc1234"; + const captureResults = { success: true }; + const authorizationId = "abc1234"; paymentMethod.transactionId = authorizationId; paymentMethod.amount = 19.99; - let captureStub = sandbox.stub(ExampleApi.methods.capture, "call", () => captureResults); - let results = Meteor.call("example/payment/capture", paymentMethod); + const captureStub = sandbox.stub(ExampleApi.methods.capture, "call", () => captureResults); + const results = Meteor.call("example/payment/capture", paymentMethod); expect(captureStub).to.have.been.calledWith({ authorizationId: authorizationId, amount: 19.99 @@ -169,11 +169,11 @@ describe("Refund", function () { }); it("should call ExampleApi with transaction ID", function () { - let refundResults = { success: true }; - let transactionId = "abc1234"; - let amount = 19.99; + const refundResults = { success: true }; + const transactionId = "abc1234"; + const amount = 19.99; paymentMethod.transactionId = transactionId; - let refundStub = sandbox.stub(ExampleApi.methods.refund, "call", () => refundResults); + const refundStub = sandbox.stub(ExampleApi.methods.refund, "call", () => refundResults); Meteor.call("example/refund/create", paymentMethod, amount); expect(refundStub).to.have.been.calledWith({ transactionId: transactionId, @@ -185,7 +185,7 @@ describe("Refund", function () { sandbox.stub(ExampleApi.methods.refund, "call", function () { throw new Meteor.Error("404", "Not Found"); }); - let transactionId = "abc1234"; + const transactionId = "abc1234"; paymentMethod.transactionId = transactionId; expect(function () { Meteor.call("example/refund/create", paymentMethod, 19.99); @@ -205,11 +205,11 @@ describe("List Refunds", function () { }); it("should call ExampleApi with transaction ID", function () { - let refundResults = { refunds: [] }; + const refundResults = { refunds: [] }; const refundArgs = { transactionId: "abc1234" }; - let refundStub = sandbox.stub(ExampleApi.methods.refunds, "call", () => refundResults); + const refundStub = sandbox.stub(ExampleApi.methods.refunds, "call", () => refundResults); Meteor.call("example/refund/list", paymentMethod); expect(refundStub).to.have.been.calledWith(refundArgs); }); diff --git a/imports/plugins/included/example-paymentmethod/server/methods/example.js b/imports/plugins/included/example-paymentmethod/server/methods/example.js index bf2efa685e5..77248754dc2 100644 --- a/imports/plugins/included/example-paymentmethod/server/methods/example.js +++ b/imports/plugins/included/example-paymentmethod/server/methods/example.js @@ -74,10 +74,10 @@ Meteor.methods({ total: String, currency: String }); - let total = parseFloat(paymentData.total); + const total = parseFloat(paymentData.total); let result; try { - let transaction = ExampleApi.methods.authorize.call({ + const transaction = ExampleApi.methods.authorize.call({ transactionType: transactionType, cardData: cardData, paymentData: paymentData @@ -112,13 +112,13 @@ Meteor.methods({ */ "example/payment/capture": function (paymentData) { check(paymentData, Reaction.Schemas.PaymentMethod); - let authorizationId = paymentData.transactionId; - let amount = paymentData.amount; - let response = ExampleApi.methods.capture.call({ + const authorizationId = paymentData.transactionId; + const amount = paymentData.amount; + const response = ExampleApi.methods.capture.call({ authorizationId: authorizationId, amount: amount }); - let result = { + const result = { saved: true, response: response }; @@ -134,12 +134,12 @@ Meteor.methods({ "example/refund/create": function (paymentMethod, amount) { check(paymentMethod, Reaction.Schemas.PaymentMethod); check(amount, Number); - let { transactionId } = paymentMethod; - let response = ExampleApi.methods.refund.call({ + const { transactionId } = paymentMethod; + const response = ExampleApi.methods.refund.call({ transactionId: transactionId, amount: amount }); - let results = { + const results = { saved: true, response: response }; @@ -157,8 +157,8 @@ Meteor.methods({ const response = ExampleApi.methods.refunds.call({ transactionId: transactionId }); - let result = []; - for (let refund of response.refunds) { + const result = []; + for (const refund of response.refunds) { result.push(refund); } diff --git a/imports/plugins/included/example-paymentmethod/server/methods/exampleapi.js b/imports/plugins/included/example-paymentmethod/server/methods/exampleapi.js index d49025ec068..79e4cd383c1 100644 --- a/imports/plugins/included/example-paymentmethod/server/methods/exampleapi.js +++ b/imports/plugins/included/example-paymentmethod/server/methods/exampleapi.js @@ -6,7 +6,7 @@ ThirdPartyAPI = { authorize: function (transactionType, cardData, paymentData) { if (transactionType === "authorize") { - let results = { + const results = { success: true, id: Random.id(), cardNumber: cardData.number.slice(-4), @@ -78,7 +78,7 @@ ExampleApi.methods.authorize = new ValidatedMethod({ paymentData: { type: paymentDataSchema } }).validator(), run({ transactionType, cardData, paymentData }) { - let results = ThirdPartyAPI.authorize(transactionType, cardData, paymentData); + const results = ThirdPartyAPI.authorize(transactionType, cardData, paymentData); return results; } }); @@ -91,9 +91,9 @@ ExampleApi.methods.capture = new ValidatedMethod({ amount: { type: Number, decimal: true } }).validator(), run(args) { - let transactionId = args.authorizationId; - let amount = args.amount; - let results = ThirdPartyAPI.capture(transactionId, amount); + const transactionId = args.authorizationId; + const amount = args.amount; + const results = ThirdPartyAPI.capture(transactionId, amount); return results; } }); @@ -106,9 +106,9 @@ ExampleApi.methods.refund = new ValidatedMethod({ amount: { type: Number, decimal: true } }).validator(), run(args) { - let transactionId = args.transactionId; - let amount = args.amount; - let results = ThirdPartyAPI.refund(transactionId, amount); + const transactionId = args.transactionId; + const amount = args.amount; + const results = ThirdPartyAPI.refund(transactionId, amount); return results; } }); @@ -120,8 +120,8 @@ ExampleApi.methods.refunds = new ValidatedMethod({ transactionId: { type: String } }).validator(), run(args) { - let { transactionId } = args; - let results = ThirdPartyAPI.listRefunds(transactionId); + const { transactionId } = args; + const results = ThirdPartyAPI.listRefunds(transactionId); return results; } }); diff --git a/imports/plugins/included/inventory/server/hooks/hooks.js b/imports/plugins/included/inventory/server/hooks/hooks.js index cd72e533933..b7762475b79 100644 --- a/imports/plugins/included/inventory/server/hooks/hooks.js +++ b/imports/plugins/included/inventory/server/hooks/hooks.js @@ -93,9 +93,9 @@ Products.after.insert((userId, doc) => { function markInventoryShipped(doc) { const order = Orders.findOne(doc._id); const orderItems = order.items; - let cartItems = []; - for (let orderItem of orderItems) { - let cartItem = { + const cartItems = []; + for (const orderItem of orderItems) { + const cartItem = { _id: orderItem.cartItemId, shopId: orderItem.shopId, quantity: orderItem.quantity, @@ -110,9 +110,9 @@ function markInventoryShipped(doc) { function markInventorySold(doc) { const orderItems = doc.items; - let cartItems = []; - for (let orderItem of orderItems) { - let cartItem = { + const cartItems = []; + for (const orderItem of orderItems) { + const cartItem = { _id: orderItem.cartItemId, shopId: orderItem.shopId, quantity: orderItem.quantity, diff --git a/imports/plugins/included/inventory/server/hooks/inventory-hooks.app-test.js b/imports/plugins/included/inventory/server/hooks/inventory-hooks.app-test.js index 39de0143d1f..55d50e55abf 100644 --- a/imports/plugins/included/inventory/server/hooks/inventory-hooks.app-test.js +++ b/imports/plugins/included/inventory/server/hooks/inventory-hooks.app-test.js @@ -70,8 +70,8 @@ describe("Inventory Hooks", function () { sandbox.stub(Reaction, "getShopId", function () { return cart.shopId; }); - let shop = getShop(); - let product = cart.items[0]; + const shop = getShop(); + const product = cart.items[0]; const inventoryItem = Inventory.insert({ productId: product.productId, variantId: product.variants._id, @@ -91,7 +91,7 @@ describe("Inventory Hooks", function () { }); spyOnMethod("copyCartToOrder", cart.userId); Meteor.call("cart/copyCartToOrder", cart._id); - let updatedInventoryItem = Inventory.findOne({ + const updatedInventoryItem = Inventory.findOne({ productId: product.productId, variantId: product.variants._id, shopId: shop._id, @@ -114,8 +114,8 @@ describe("Inventory Hooks", function () { sandbox.stub(Reaction, "getShopId", function () { return cart.shopId; }); - let shop = getShop(); - let product = cart.items[0]; + const shop = getShop(); + const product = cart.items[0]; const inventoryItem = Inventory.insert({ productId: product.productId, variantId: product.variants._id, diff --git a/imports/plugins/included/inventory/server/methods/inventory.app-test.js b/imports/plugins/included/inventory/server/methods/inventory.app-test.js index 0957bade4cb..0b94a63126e 100644 --- a/imports/plugins/included/inventory/server/methods/inventory.app-test.js +++ b/imports/plugins/included/inventory/server/methods/inventory.app-test.js @@ -66,16 +66,16 @@ describe("inventory method", function () { // register inventory (that we'll should delete on variant removal) sandbox.stub(Reaction, "hasPermission", () => true); // checking our option quantity. It should be greater than zero. - let qty = options[1].inventoryQuantity; + const qty = options[1].inventoryQuantity; expect(qty).to.be.above(0); // before spec we're cleared collection, so we need to insert all docs // again and make sure quantity will be equal with `qty` Meteor.call("inventory/register", options[1]); - let midQty = Inventory.find({ variantId: options[1]._id }).count(); + const midQty = Inventory.find({ variantId: options[1]._id }).count(); expect(midQty).to.equal(qty); // then we are removing option and docs should be automatically removed Meteor.call("products/deleteVariant", options[1]._id); - let newQty = Inventory.find({ variantId: options[1]._id }).count(); + const newQty = Inventory.find({ variantId: options[1]._id }).count(); expect(newQty).to.not.equal(qty); expect(newQty).to.equal(0); }); diff --git a/imports/plugins/included/inventory/server/methods/inventory.js b/imports/plugins/included/inventory/server/methods/inventory.js index 5752885d05f..7e114916850 100644 --- a/imports/plugins/included/inventory/server/methods/inventory.js +++ b/imports/plugins/included/inventory/server/methods/inventory.js @@ -23,18 +23,18 @@ export function registerInventory(product) { const variants = Catalog.getVariants(productId); // we'll check each variant to see if it has been fully registered - for (let variant of variants) { - let inventory = Inventory.find({ + for (const variant of variants) { + const inventory = Inventory.find({ productId: productId, variantId: variant._id, shopId: product.shopId }); // we'll return this as well - let inventoryVariantCount = inventory.count(); + const inventoryVariantCount = inventory.count(); // if the variant exists already we're remove from the inventoryVariants // so that we don't process it as an insert if (inventoryVariantCount < variant.inventoryQuantity) { - let newQty = variant.inventoryQuantity || 0; + const newQty = variant.inventoryQuantity || 0; let i = inventoryVariantCount + 1; Logger.info( @@ -45,7 +45,7 @@ export function registerInventory(product) { const batch = Inventory. _collection.rawCollection().initializeUnorderedBulkOp(); while (i <= newQty) { - let id = Inventory._makeNewID(); + const id = Inventory._makeNewID(); batch.insert({ _id: id, productId: productId, @@ -61,9 +61,9 @@ export function registerInventory(product) { } // took from: http://guide.meteor.com/collections.html#bulk-data-changes - let execute = Meteor.wrapAsync(batch.execute, batch); - let inventoryItem = execute(); - let inserted = inventoryItem.nInserted; + const execute = Meteor.wrapAsync(batch.execute, batch); + const inventoryItem = execute(); + const inserted = inventoryItem.nInserted; if (!inserted) { // or maybe `inventory.length === 0`? // throw new Meteor.Error("Inventory Anomaly Detected. Abort! Abort!"); @@ -155,7 +155,7 @@ Meteor.methods({ results = itemCount; // delete latest inventory "status:new" records - for (let inventoryItem of removeInventory) { + for (const inventoryItem of removeInventory) { results -= Meteor.call("inventory/remove", inventoryItem); // we could add handling for the case when aren't enough "new" items } diff --git a/imports/plugins/included/inventory/server/methods/statusChanges.js b/imports/plugins/included/inventory/server/methods/statusChanges.js index eba446ec1af..47d360a7a6e 100644 --- a/imports/plugins/included/inventory/server/methods/statusChanges.js +++ b/imports/plugins/included/inventory/server/methods/statusChanges.js @@ -4,7 +4,7 @@ import { Inventory } from "/lib/collections"; import * as Schemas from "/lib/collections/schemas"; import { Logger, Reaction } from "/server/api"; -// Disabled for now, needs more testing. +// TODO statusChanges DDP limiting Disabled for now, needs more testing. // // Define a rate limiting rule that matches update attempts by non-admin users // const addReserveRule = { @@ -63,9 +63,9 @@ Meteor.methods({ Logger.info(`Moving Inventory items from ${defaultStatus} to ${reservationStatus}`); // update inventory status for cartItems - for (let item of cartItems) { + for (const item of cartItems) { // check of existing reserved inventory for this cart - let existingReservations = Inventory.find({ + const existingReservations = Inventory.find({ productId: item.productId, variantId: item.variants._id, shopId: item.shopId, @@ -73,7 +73,7 @@ Meteor.methods({ }); // define a new reservation - let availableInventory = Inventory.find({ + const availableInventory = Inventory.find({ "productId": item.productId, "variantId": item.variants._id, "shopId": item.shopId, @@ -90,7 +90,7 @@ Meteor.methods({ // if we don't have existing inventory we create backorders if (totalRequiredQty > availableInventoryQty) { // TODO put in a dashboard setting to allow backorder or altenate handler to be used - let backOrderQty = Number(totalRequiredQty - availableInventoryQty - existingReservationQty); + const backOrderQty = Number(totalRequiredQty - availableInventoryQty - existingReservationQty); Logger.info(`no inventory found, create ${backOrderQty} ${backorderStatus}`); // define a new reservation const reservation = { @@ -164,13 +164,13 @@ Meteor.methods({ // } // optional workflow status or default to "new" - let newStatus = status || "new"; - let oldStatus = currentStatus || "reserved"; + const newStatus = status || "new"; + const oldStatus = currentStatus || "reserved"; // remove each cart item in inventory - for (let item of cartItems) { + for (const item of cartItems) { // check of existing reserved inventory for this cart - let existingReservations = Inventory.find({ + const existingReservations = Inventory.find({ "productId": item.productId, "variantId": item.variants._id, "shopId": item.shopId, @@ -242,7 +242,7 @@ Meteor.methods({ return 0; } - // TODO: need to look carefully and understand is it possible ho have a + // TODO inventory/backorder need to look carefully and understand is it possible ho have a // negative `backOrderQty` value here? // check basic user permissions @@ -251,7 +251,7 @@ Meteor.methods({ // } // set defaults - let newReservation = reservation; + const newReservation = reservation; if (!newReservation.workflow) { newReservation.workflow = { status: "backorder" @@ -260,29 +260,41 @@ Meteor.methods({ // insert backorder let i = 0; - const batch = Inventory. - _collection.rawCollection().initializeUnorderedBulkOp(); - while (i < backOrderQty) { - let id = Inventory._makeNewID(); - batch.insert(Object.assign({ _id: id }, newReservation)); - i++; - } - const execute = Meteor.wrapAsync(batch.execute, batch); - const inventoryBackorder = execute(); - const inserted = inventoryBackorder.nInserted; - Logger.info( - `created ${inserted} backorder records for product ${ - newReservation.productId}, variant ${newReservation.variantId}`); + // check if we support bulk operations + const currentBatch = Inventory._collection.rawCollection().currentBatch; + + if (currentBatch && currentBatch.operations && currentBatch.operations.length > 0) { + const batch = Inventory._collection.rawCollection().initializeUnorderedBulkOp(); + if (batch) { + while (i < backOrderQty) { + const id = Inventory._makeNewID(); + batch.insert(Object.assign({ _id: id }, newReservation)); + i++; + } - return inserted; + const execute = Meteor.wrapAsync(batch.execute, batch); + const inventoryBackorder = execute(); + const inserted = inventoryBackorder.nInserted; + Logger.info(`created ${inserted} backorder records for product ${newReservation.productId}, variant ${newReservation.variantId}`); + return inserted; + } + } + // + // TODO implement a backup inventory/backorder method if bulk operations fail. + // + Logger.error("skipped bulk operations backorder updates."); + return null; }, // // send low stock warnings // "inventory/lowStock": function (product) { check(product, Schemas.Product); - // WIP placeholder + // + // TODO implement inventory/lowstock calculations + // placeholder is here to give plugins a place to hook into + // Logger.info("inventory/lowStock"); }, /** diff --git a/imports/plugins/included/inventory/server/startup/init.js b/imports/plugins/included/inventory/server/startup/init.js index f6ed711bf4a..74f1db49859 100644 --- a/imports/plugins/included/inventory/server/startup/init.js +++ b/imports/plugins/included/inventory/server/startup/init.js @@ -8,7 +8,7 @@ Hooks.Events.add("afterCoreInit", () => { const inventory = Inventory.find().count(); if (!inventory) { const products = Products.find().fetch(); - for (let product of products) { + for (const product of products) { Logger.info(`Registering product ${product.title}`); registerInventory(product); } diff --git a/imports/plugins/included/jobcontrol/server/jobs/cleanup.js b/imports/plugins/included/jobcontrol/server/jobs/cleanup.js index 8cee46593fd..0b075c67812 100644 --- a/imports/plugins/included/jobcontrol/server/jobs/cleanup.js +++ b/imports/plugins/included/jobcontrol/server/jobs/cleanup.js @@ -44,7 +44,7 @@ export default function () { workTimeout: 60 * 1000 }, (job, callback) => { - let current = new Date(); + const current = new Date(); // todo: set this interval in the admin UI current.setMinutes(current.getMinutes() - 5); const ids = getJobIds(current); diff --git a/imports/plugins/included/launchdock-connect/client/templates/dashboard.js b/imports/plugins/included/launchdock-connect/client/templates/dashboard.js index d197e6ee125..890ffc76682 100644 --- a/imports/plugins/included/launchdock-connect/client/templates/dashboard.js +++ b/imports/plugins/included/launchdock-connect/client/templates/dashboard.js @@ -76,7 +76,7 @@ Template.launchdockDashboard.helpers({ let daySuffix; if (stack) { - let startDate = stack.createdAt; + const startDate = stack.createdAt; ends = new Date(); ends.setDate(startDate.getDate() + 30); const now = new Date(); @@ -118,7 +118,7 @@ Template.launchdockDashboard.helpers({ yearlyPaymentDate() { const today = new Date(); - let nextDue = new Date(); + const nextDue = new Date(); nextDue.setDate(today.getDate() + 365); return moment(nextDue).format("LL"); @@ -154,7 +154,7 @@ Template.launchdockDashboard.events({ } const today = new Date(); - let nextDue = new Date(); + const nextDue = new Date(); nextDue.setDate(today.getDate() + daysFromNow); t.$(".price").text(dueToday); diff --git a/imports/plugins/included/paypal/client/lib/paypalRestApi.js b/imports/plugins/included/paypal/client/lib/paypalRestApi.js index 35cb712b418..7a63eafd89e 100644 --- a/imports/plugins/included/paypal/client/lib/paypalRestApi.js +++ b/imports/plugins/included/paypal/client/lib/paypalRestApi.js @@ -6,7 +6,7 @@ import { Logger } from "/client/api"; export const PaypalClientAPI = { load: _.once(function () { - let script = document.createElement("script"); + const script = document.createElement("script"); script.type = "text/javascript"; script.async = true; script.src = "//www.paypalobjects.com/api/checkout.js"; diff --git a/imports/plugins/included/paypal/client/templates/checkout/checkoutButton.js b/imports/plugins/included/paypal/client/templates/checkout/checkoutButton.js index ca2d369e01b..4f62c879280 100644 --- a/imports/plugins/included/paypal/client/templates/checkout/checkoutButton.js +++ b/imports/plugins/included/paypal/client/templates/checkout/checkoutButton.js @@ -33,20 +33,20 @@ function doSetup(element, expressCheckoutSettings) { */ function checkout() { paypal.checkout.initXO(); - let cart = Cart.findOne(); + const cart = Cart.findOne(); if (!cart) { return undefined; } return Meteor.call("getExpressCheckoutToken", cart._id, function (error, token) { if (error) { - let msg = (error !== null ? error.error : void 0) || i18next.t("checkoutPayment.processingError", "There was a problem with your payment."); + const msg = (error !== null ? error.error : void 0) || i18next.t("checkoutPayment.processingError", "There was a problem with your payment."); Alerts.add(msg, "danger", { placement: "paymentMethod" }); return paypal.checkout.closeFlow(); } - let url = paypal.checkout.urlPrefix + token; + const url = paypal.checkout.urlPrefix + token; return paypal.checkout.startFlow(url); }); } diff --git a/imports/plugins/included/paypal/client/templates/checkout/payflowForm.js b/imports/plugins/included/paypal/client/templates/checkout/payflowForm.js index 840fd54fc36..f7265eb0060 100644 --- a/imports/plugins/included/paypal/client/templates/checkout/payflowForm.js +++ b/imports/plugins/included/paypal/client/templates/checkout/payflowForm.js @@ -32,16 +32,16 @@ function getError(error, detailSubpart) { } function handlePaypalSubmitError(error) { - let results = []; - let singleError = getError(error, "error_description"); - let serverError = getError(error, "message"); - let errors = getError(error, "response") || []; + const results = []; + const singleError = getError(error, "error_description"); + const serverError = getError(error, "message"); + const errors = getError(error, "response") || []; if (singleError) { return paymentAlert("Oops! " + singleError); } else if (errors.length) { for (let i = 0, len = errors.length; i < len; i++) { - let thisError = errors[i]; - let formattedError = "Oops! " + thisError.issue + ": " + thisError.field.split(/[. ]+/).pop().replace(/_/g, " "); + const thisError = errors[i]; + const formattedError = "Oops! " + thisError.issue + ": " + thisError.field.split(/[. ]+/).pop().replace(/_/g, " "); results.push(paymentAlert(formattedError)); } return results; @@ -67,9 +67,9 @@ Template.paypalPayflowForm.helpers({ AutoForm.addHooks("paypal-payment-form", { onSubmit: function (doc) { hidePaymentAlert(); - let template = this.template; - let payerNamePieces = doc.payerName.split(" "); - let form = { + const template = this.template; + const payerNamePieces = doc.payerName.split(" "); + const form = { first_name: payerNamePieces[0], last_name: payerNamePieces[1], number: doc.cardNumber, @@ -78,7 +78,7 @@ AutoForm.addHooks("paypal-payment-form", { cvv2: doc.cvv, type: Reaction.getCardType(doc.cardNumber) }; - let storedCard = form.type.charAt(0).toUpperCase() + form.type.slice(1) + " " + doc.cardNumber.slice(-4); + const storedCard = form.type.charAt(0).toUpperCase() + form.type.slice(1) + " " + doc.cardNumber.slice(-4); Paypal.authorize(form, { total: Cart.findOne().cartTotal(), currency: Shops.findOne().currency @@ -89,47 +89,47 @@ AutoForm.addHooks("paypal-payment-form", { uiEnd(template, "Resubmit payment"); } else { if (transaction.saved === true) { - let normalizedStatus = (function () { + const normalizedStatus = (function () { switch (transaction.response.state) { - case "created": - return "created"; - case "approved": - return "created"; - case "failed": - return "failed"; - case "canceled": - return "canceled"; - case "expired": - return "expired"; - case "pending": - return "pending"; - default: - return "failed"; + case "created": + return "created"; + case "approved": + return "created"; + case "failed": + return "failed"; + case "canceled": + return "canceled"; + case "expired": + return "expired"; + case "pending": + return "pending"; + default: + return "failed"; } })(); - let normalizedMode = (function () { + const normalizedMode = (function () { switch (transaction.response.intent) { - case "sale": - return "capture"; - case "authorize": - return "authorize"; - case "order": - return "capture"; - default: - return "capture"; + case "sale": + return "capture"; + case "authorize": + return "authorize"; + case "order": + return "capture"; + default: + return "capture"; } })(); // just auth, not transaction - let transactionId = transaction.response.id; + const transactionId = transaction.response.id; // when auth and transaction let authId; if (typeof transaction.response.transactions[0].related_resources[0] === "object") { authId = transaction.response.transactions[0].related_resources[0].authorization.id; } - let paymentMethod = { + const paymentMethod = { processor: "PayflowPro", storedCard: storedCard, method: transaction.response.payer.payment_method, diff --git a/imports/plugins/included/paypal/client/templates/checkout/paymentForm.js b/imports/plugins/included/paypal/client/templates/checkout/paymentForm.js index 1a31e2c3286..f9d45f4ef18 100644 --- a/imports/plugins/included/paypal/client/templates/checkout/paymentForm.js +++ b/imports/plugins/included/paypal/client/templates/checkout/paymentForm.js @@ -17,11 +17,11 @@ Template.paypalPaymentForm.onCreated(function () { Template.paypalPaymentForm.helpers({ expressCheckoutEnabled: function () { - let expressCheckoutSettings = Session.get("expressCheckoutSettings"); + const expressCheckoutSettings = Session.get("expressCheckoutSettings"); return expressCheckoutSettings !== undefined ? expressCheckoutSettings.enabled : void 0; }, payflowEnabled: function () { - let payflowSettings = Session.get("payflowSettings"); + const payflowSettings = Session.get("payflowSettings"); return payflowSettings !== undefined ? payflowSettings.enabled : void 0; } }); diff --git a/imports/plugins/included/paypal/client/templates/checkout/return/done.js b/imports/plugins/included/paypal/client/templates/checkout/return/done.js index fb4b050d09e..ae83047ebb8 100644 --- a/imports/plugins/included/paypal/client/templates/checkout/return/done.js +++ b/imports/plugins/included/paypal/client/templates/checkout/return/done.js @@ -1,11 +1,10 @@ -import _ from "lodash"; -import { Reaction } from "/client/api"; -import { Cart } from "/lib/collections"; -import Logger from "/client/modules/logger"; import { Meteor } from "meteor/meteor"; import { Session } from "meteor/session"; import { Template } from "meteor/templating"; import { Tracker } from "meteor/tracker"; +import { Reaction } from "/client/api"; +import { Cart } from "/lib/collections"; +import Logger from "/client/modules/logger"; // This template handles receiving the token from Paypal, recording it and moving on the checkout @@ -22,7 +21,7 @@ function showError(error) { } function buildPaymentMethod(result, status, mode) { - let paymentMethod = { + const paymentMethod = { processor: "PaypalExpress", method: "Paypal Express Checkout", transactionId: result.TRANSACTIONID, @@ -47,7 +46,6 @@ Template.paypalDone.helpers({ } }); - Template.paypalDone.onCreated(function () { const payerId = Reaction.Router.getQueryParam("PayerID"); const token = Reaction.Router.getQueryParam("token"); @@ -56,7 +54,7 @@ Template.paypalDone.onCreated(function () { // wait for cart to be ready Tracker.autorun(function (c) { if (Reaction.Subscriptions.Cart.ready()) { - let cart = Cart.findOne(); + const cart = Cart.findOne(); if (!cart) { Logger.warn("Could not find valid cart"); return; @@ -89,10 +87,10 @@ Template.paypalDone.onCreated(function () { } const paymentMethod = buildPaymentMethod(result, status, mode); - Meteor.call("cart/submitPayment", paymentMethod, function (error, result) { - if (!result && error) { - Logger.warn(error, "Error received during submitting Payment via Paypal"); - showError(error); + Meteor.call("cart/submitPayment", paymentMethod, function (payError, payResult) { + if (!payResult && payError) { + Logger.warn(payError, "Error received during submitting Payment via Paypal"); + showError(payError); Session.set("guestCheckoutFlow", true); } }); diff --git a/imports/plugins/included/paypal/lib/api/paypal.js b/imports/plugins/included/paypal/lib/api/paypal.js index 7f6003a9f1d..02a941a7585 100644 --- a/imports/plugins/included/paypal/lib/api/paypal.js +++ b/imports/plugins/included/paypal/lib/api/paypal.js @@ -9,7 +9,7 @@ import { Packages } from "/lib/collections"; export const Paypal = { payflowAccountOptions: function () { - let settings = Packages.findOne({ + const settings = Packages.findOne({ name: "reaction-paypal", shopId: ReactionCore.getShopId(), enabled: true @@ -20,8 +20,8 @@ export const Paypal = { } else { mode = "sandbox"; } - let ref = Meteor.settings.paypal; - let options = { + const ref = Meteor.settings.paypal; + const options = { mode: mode, enabled: getSettings(settings, ref, "payflow_enabled"), client_id: getSettings(settings, ref, "client_id"), @@ -35,7 +35,7 @@ export const Paypal = { expressCheckoutAccountOptions: function () { const prefix = getSlug(ReactionCore.getShopName().toLowerCase()); const shopId = ReactionCore.getShopId(); - let settings = Packages.findOne({ + const settings = Packages.findOne({ name: "reaction-paypal", shopId: shopId, enabled: true @@ -46,9 +46,9 @@ export const Paypal = { } else { mode = "sandbox"; } - let ref = Meteor.settings.paypal; + const ref = Meteor.settings.paypal; - let options = { + const options = { enabled: settings !== null ? settings.express_enabled : void 0, mode: mode, username: getSettings(settings, ref, "username"), @@ -69,7 +69,7 @@ export const Paypal = { Meteor.call("payflowpro/payment/submit", "authorize", cardInfo, paymentInfo, callback); }, capture: function (transactionId, amount, callback) { - let captureDetails = { + const captureDetails = { amount: { currency: "USD", // todo should this be locale.currency total: parseFloat(amount, 10) diff --git a/imports/plugins/included/paypal/server/methods/express.js b/imports/plugins/included/paypal/server/methods/express.js index 895c893f08e..3ff590db953 100644 --- a/imports/plugins/included/paypal/server/methods/express.js +++ b/imports/plugins/included/paypal/server/methods/express.js @@ -22,18 +22,18 @@ Meteor.methods({ "getExpressCheckoutToken": function (cartId) { check(cartId, String); this.unblock(); - let cart = Cart.findOne(cartId); + const cart = Cart.findOne(cartId); if (!cart) { throw new Meteor.Error("Bad cart ID"); } - let shop = Shops.findOne(cart.shopId); + const shop = Shops.findOne(cart.shopId); if (!shop) { throw new Meteor.Error("Bad shop ID"); } - let amount = Number(cart.cartTotal()); - let description = shop.name + " Ref: " + cartId; - let currency = shop.currency; - let options = Paypal.expressCheckoutAccountOptions(); + const amount = Number(cart.cartTotal()); + const description = shop.name + " Ref: " + cartId; + const currency = shop.currency; + const options = Paypal.expressCheckoutAccountOptions(); let response; try { @@ -63,7 +63,7 @@ Meteor.methods({ if (!response || response.statusCode !== 200) { throw new Meteor.Error("Bad response from PayPal"); } - let parsedResponse = parseResponse(response); + const parsedResponse = parseResponse(response); if (parsedResponse.ACK !== "Success") { throw new Meteor.Error("ACK " + parsedResponse.ACK + ": " + parsedResponse.L_LONGMESSAGE0); } @@ -82,15 +82,15 @@ Meteor.methods({ check(token, String); check(payerId, String); this.unblock(); - let cart = Cart.findOne(cartId); + const cart = Cart.findOne(cartId); if (!cart) { throw new Meteor.Error("Bad cart ID"); } - let amount = Number(cart.cartTotal()); - let shop = Shops.findOne(cart.shopId); - let currency = shop.currency; - let options = Paypal.expressCheckoutAccountOptions(); - let captureAtAuth = getSetting(cart.shopId, "express_auth_and_capture"); + const amount = Number(cart.cartTotal()); + const shop = Shops.findOne(cart.shopId); + const currency = shop.currency; + const options = Paypal.expressCheckoutAccountOptions(); + const captureAtAuth = getSetting(cart.shopId, "express_auth_and_capture"); let paymentAction; if (captureAtAuth) { paymentAction = "Sale"; @@ -119,7 +119,7 @@ Meteor.methods({ if (!response || response.statusCode !== 200) { throw new Meteor.Error("Bad response from PayPal"); } - let parsedResponse = parseResponse(response); + const parsedResponse = parseResponse(response); if (parsedResponse.ACK !== "Success") { throw new Meteor.Error("ACK " + @@ -135,8 +135,8 @@ Meteor.methods({ * @return {Object} Express Checkout settings */ "getExpressCheckoutSettings": function () { - let settings = Paypal.expressCheckoutAccountOptions(); - let expressCheckoutSettings = { + const settings = Paypal.expressCheckoutAccountOptions(); + const expressCheckoutSettings = { merchantId: settings.merchantId, mode: settings.mode, enabled: settings.enabled @@ -153,10 +153,10 @@ Meteor.methods({ "paypalexpress/payment/capture": function (paymentMethod) { check(paymentMethod, Reaction.Schemas.PaymentMethod); this.unblock(); - let options = Paypal.expressCheckoutAccountOptions(); - let amount = accounting.toFixed(paymentMethod.amount, 2); - let authorizationId = paymentMethod.transactions[0].TRANSACTIONID; - let currencycode = paymentMethod.transactions[0].CURRENCYCODE; + const options = Paypal.expressCheckoutAccountOptions(); + const amount = accounting.toFixed(paymentMethod.amount, 2); + const authorizationId = paymentMethod.transactions[0].TRANSACTIONID; + const currencycode = paymentMethod.transactions[0].CURRENCYCODE; let response; // 100% discounts are not valid when using PayPal Express @@ -201,13 +201,13 @@ Meteor.methods({ throw new Meteor.Error("Bad Response from Paypal during Capture"); } - let parsedResponse = parseResponse(response); + const parsedResponse = parseResponse(response); if (parsedResponse.ACK !== "Success") { throw new Meteor.Error("ACK " + parsedResponse.ACK + ": " + parsedResponse.L_LONGMESSAGE0); } - let result = { + const result = { saved: true, authorizationId: parsedResponse.AUTHORIZATIONID, transactionId: parsedResponse.TRANSACTIONID, @@ -261,17 +261,17 @@ Meteor.methods({ throw new Meteor.Error("Bad Response from Paypal during Refund Creation"); } - let parsedResponse = parseResponse(response); + const parsedResponse = parseResponse(response); if (parsedResponse.ACK !== "Success") { throw new Meteor.Error("ACK " + parsedResponse.ACK + ": " + parsedResponse.L_LONGMESSAGE0); } - let amountFormatted = { + const amountFormatted = { total: amount, currency: currencycode }; - let result = { + const result = { saved: true, type: "refund", created: new Date(), @@ -297,8 +297,8 @@ Meteor.methods({ check(paymentMethod, Reaction.Schemas.PaymentMethod); this.unblock(); - let options = Paypal.expressCheckoutAccountOptions(); - let transactionId = paymentMethod.transactionId; + const options = Paypal.expressCheckoutAccountOptions(); + const transactionId = paymentMethod.transactionId; let response; try { @@ -322,23 +322,23 @@ Meteor.methods({ throw new Meteor.Error("Bad Response from Paypal during refund list"); } - let parsedResponse = parseResponse(response); + const parsedResponse = parseResponse(response); if (parsedResponse.ACK !== "Success") { throw new Meteor.Error("ACK " + parsedResponse.ACK + ": " + parsedResponse.L_LONGMESSAGE0); } - let result = parseRefundReponse(parsedResponse); + const result = parseRefundReponse(parsedResponse); return result; } }); parseResponse = function (response) { - let result = {}; - let pieces = response.content.split("&"); + const result = {}; + const pieces = response.content.split("&"); pieces.forEach(function (piece) { - let subpieces = piece.split("="); - let decodedResult = result[subpieces[0]] = decodeURIComponent(subpieces[1]); + const subpieces = piece.split("="); + const decodedResult = result[subpieces[0]] = decodeURIComponent(subpieces[1]); return decodedResult; }); return result; @@ -350,20 +350,20 @@ parseResponse = function (response) { * @return {Object} Refunds, normalized to an Array */ parseRefundReponse = function (response) { - let paypalArray = []; + const paypalArray = []; for (let i = 0; i < 101; i++) { - let timeStampKey = "L_TIMESTAMP" + i; - let timestamp = response[timeStampKey]; - let typeKey = "L_TYPE" + i; - let transactionType = response[typeKey]; - let amountKey = "L_AMT" + i; - let amount = response[amountKey]; - let currencyCodeKey = "L_CURRENCYCODE" + i; - let currencyCode = response[currencyCodeKey]; + const timeStampKey = "L_TIMESTAMP" + i; + const timestamp = response[timeStampKey]; + const typeKey = "L_TYPE" + i; + const transactionType = response[typeKey]; + const amountKey = "L_AMT" + i; + const amount = response[amountKey]; + const currencyCodeKey = "L_CURRENCYCODE" + i; + const currencyCode = response[currencyCodeKey]; if (timestamp !== undefined && transactionType === "Refund") { - let responseObject = { + const responseObject = { created: moment(timestamp).valueOf(), type: "refund", amount: Math.abs(Number(amount, 10)), @@ -377,7 +377,7 @@ parseRefundReponse = function (response) { }; getSetting = function (shopId, parameter) { - let settings = Packages.findOne({ + const settings = Packages.findOne({ name: "reaction-paypal", shopId: shopId, enabled: true diff --git a/imports/plugins/included/paypal/server/methods/payflowpro-methods-refund.app-test.js b/imports/plugins/included/paypal/server/methods/payflowpro-methods-refund.app-test.js index 8b4c5847fe1..ac5a13444d6 100644 --- a/imports/plugins/included/paypal/server/methods/payflowpro-methods-refund.app-test.js +++ b/imports/plugins/included/paypal/server/methods/payflowpro-methods-refund.app-test.js @@ -16,7 +16,7 @@ describe("payflowpro/refund/create", function () { }); it("Should call payflowpro/refund/create with the proper parameters and return saved = true", function (done) { - let paymentMethod = { + const paymentMethod = { processor: "PayflowPro", storedCard: "Visa 0322", method: "credit_card", @@ -39,7 +39,7 @@ describe("payflowpro/refund/create", function () { }; - let payflowproRefundResult = { + const payflowproRefundResult = { saved: true, type: "refund", created: "2016-08-15T05:58:14Z", diff --git a/imports/plugins/included/paypal/server/methods/payflowproApi.js b/imports/plugins/included/paypal/server/methods/payflowproApi.js index 3f353a1df77..49e41b79edb 100644 --- a/imports/plugins/included/paypal/server/methods/payflowproApi.js +++ b/imports/plugins/included/paypal/server/methods/payflowproApi.js @@ -13,7 +13,7 @@ PayflowproApi.apiCall = {}; PayflowproApi.apiCall.paymentSubmit = function (paymentSubmitDetails) { PayFlow.configure(Paypal.payflowAccountOptions()); - let paymentObj = Paypal.paymentObj(); + const paymentObj = Paypal.paymentObj(); paymentObj.intent = paymentSubmitDetails.transactionType; paymentObj.payer.funding_instruments.push(Paypal.parseCardData(paymentSubmitDetails.cardData)); paymentObj.transactions.push(Paypal.parsePaymentData(paymentSubmitDetails.paymentData)); @@ -43,7 +43,7 @@ PayflowproApi.apiCall.captureCharge = function (paymentCaptureDetails) { const shop = Shops.findOne(Reaction.getShopId()); const wrappedFunc = Meteor.wrapAsync(PayFlow.authorization.capture, PayFlow.authorization); const wrappedFuncVoid = Meteor.wrapAsync(PayFlow.authorization.void, PayFlow.authorization); - let captureTotal = Math.round(parseFloat(paymentCaptureDetails.amount) * 100) / 100; + const captureTotal = Math.round(parseFloat(paymentCaptureDetails.amount) * 100) / 100; const captureDetails = { amount: { currency: shop.currency, @@ -99,12 +99,12 @@ PayflowproApi.apiCall.captureCharge = function (paymentCaptureDetails) { PayflowproApi.apiCall.createRefund = function (refundDetails) { PayFlow.configure(Paypal.payflowAccountOptions()); - let createRefund = Meteor.wrapAsync(PayFlow.capture.refund, PayFlow.capture); + const createRefund = Meteor.wrapAsync(PayFlow.capture.refund, PayFlow.capture); let result; try { Logger.debug("payflowpro/refund/create: paymentMethod.metadata.captureId", refundDetails.captureId); - let response = createRefund(refundDetails.captureId, { + const response = createRefund(refundDetails.captureId, { amount: { total: refundDetails.amount, currency: "USD" @@ -132,20 +132,20 @@ PayflowproApi.apiCall.createRefund = function (refundDetails) { PayflowproApi.apiCall.listRefunds = function (refundListDetails) { PayFlow.configure(Paypal.payflowAccountOptions()); - let listPayments = Meteor.wrapAsync(PayFlow.payment.get, PayFlow.payment); + const listPayments = Meteor.wrapAsync(PayFlow.payment.get, PayFlow.payment); let result = []; // todo: review parentPaymentId vs authorizationId, are they both correct? // added authorizationId without fully understanding the intent of parentPaymentId // let authId = paymentMethod.metadata.parentPaymentId || paymentMethod.metadata.authorizationId; - let authId = refundListDetails.transactionId; + const authId = refundListDetails.transactionId; if (authId) { Logger.debug("payflowpro/refund/list: paymentMethod.metadata.parentPaymentId", authId); try { - let response = listPayments(authId); + const response = listPayments(authId); - for (let transaction of response.transactions) { - for (let resource of transaction.related_resources) { + for (const transaction of response.transactions) { + for (const resource of transaction.related_resources) { if (_.isObject(resource.refund)) { if (resource.refund.state === "completed") { result.push({ diff --git a/imports/plugins/included/paypal/server/methods/payflowproMethods.js b/imports/plugins/included/paypal/server/methods/payflowproMethods.js index 4322b545dee..b814af2952a 100644 --- a/imports/plugins/included/paypal/server/methods/payflowproMethods.js +++ b/imports/plugins/included/paypal/server/methods/payflowproMethods.js @@ -27,7 +27,7 @@ export function paymentSubmit(transactionType, cardData, paymentData) { let result; try { - let refundResult = PayflowproApi.apiCall.paymentSubmit(paymentSubmitDetails); + const refundResult = PayflowproApi.apiCall.paymentSubmit(paymentSubmitDetails); Logger.info(refundResult); result = refundResult; } catch (error) { @@ -60,7 +60,7 @@ export function paymentCapture(paymentMethod) { let result; try { - let refundResult = PayflowproApi.apiCall.captureCharge(paymentCaptureDetails); + const refundResult = PayflowproApi.apiCall.captureCharge(paymentCaptureDetails); Logger.info(refundResult); result = refundResult; } catch (error) { @@ -95,7 +95,7 @@ export function createRefund(paymentMethod, amount) { let result; try { - let refundResult = PayflowproApi.apiCall.createRefund(refundDetails); + const refundResult = PayflowproApi.apiCall.createRefund(refundDetails); Logger.info(refundResult); result = refundResult; } catch (error) { @@ -128,7 +128,7 @@ export function listRefunds(paymentMethod) { let result; try { - let refundResult = PayflowproApi.apiCall.listRefunds(refundListDetails); + const refundResult = PayflowproApi.apiCall.listRefunds(refundListDetails); Logger.info(refundResult); result = refundResult; } catch (error) { @@ -145,8 +145,8 @@ export function listRefunds(paymentMethod) { export function getSettings() { - let settings = Paypal.payflowAccountOptions(); - let payflowSettings = { + const settings = Paypal.payflowAccountOptions(); + const payflowSettings = { mode: settings.mode, enabled: settings.enabled }; diff --git a/imports/plugins/included/product-variant/client/index.js b/imports/plugins/included/product-variant/client/index.js index 17487ab136f..d487d2f3ad0 100644 --- a/imports/plugins/included/product-variant/client/index.js +++ b/imports/plugins/included/product-variant/client/index.js @@ -16,8 +16,6 @@ import "./templates/products/productDetail/productImageGallery.html"; import "./templates/products/productDetail/productImageGallery.js"; import "./templates/products/productDetail/social.html"; import "./templates/products/productDetail/social.js"; -import "./templates/products/productDetail/tags.html"; -import "./templates/products/productDetail/tags.js"; import "./templates/products/productGrid/content.html"; import "./templates/products/productGrid/content.js"; diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/edit.js b/imports/plugins/included/product-variant/client/templates/products/productDetail/edit.js index 1a439db00dc..05671053c21 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/edit.js +++ b/imports/plugins/included/product-variant/client/templates/products/productDetail/edit.js @@ -11,7 +11,7 @@ import { Template } from "meteor/templating"; Template.productDetailEdit.helpers({ i18nPlaceholder: function () { - let i18nKey = `productDetailEdit.${this.field}`; + const i18nKey = `productDetailEdit.${this.field}`; if (i18next.t(i18nKey) === i18nKey) { Logger.info(`returning empty placeholder productDetailEdit: ${i18nKey} no i18n key found.`); } else { @@ -83,7 +83,7 @@ Template.productDetailEdit.events({ Template.productDetailField.events({ "click .product-detail-field": function () { if (Reaction.hasPermission("createProduct")) { - let fieldClass = "editing-" + this.field; + const fieldClass = "editing-" + this.field; Session.set(fieldClass, true); // Tracker.flush(); return $(`.${this.field}-edit-input`).focus(); diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/productDetail.js b/imports/plugins/included/product-variant/client/templates/products/productDetail/productDetail.js index ff3b3b3b3a2..96ea86b453e 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/productDetail.js +++ b/imports/plugins/included/product-variant/client/templates/products/productDetail/productDetail.js @@ -9,10 +9,6 @@ import { Session } from "meteor/session"; import { Template } from "meteor/templating"; import { EditButton } from "/imports/plugins/core/ui/client/components"; -// load modules -require("jquery-ui"); - - Template.productDetail.onCreated(function () { this.state = new ReactiveDict(); this.state.setDefault({ @@ -183,7 +179,7 @@ Template.productDetail.helpers({ return null; }, tags: function () { - let product = ReactionProduct.selectedProduct(); + const product = ReactionProduct.selectedProduct(); if (product) { if (product.hashtags) { return _.map(product.hashtags, function (id) { @@ -236,7 +232,7 @@ Template.productDetail.events({ "click #price": function () { let formName; if (Reaction.hasPermission("createProduct")) { - let variant = ReactionProduct.selectedVariant(); + const variant = ReactionProduct.selectedVariant(); if (!variant) { return; } @@ -257,12 +253,11 @@ Template.productDetail.events({ return event.stopPropagation(); }, "change #add-to-cart-quantity": function (event, template) { - let currentVariant; - let qtyField; - let quantity; event.preventDefault(); event.stopPropagation(); - currentVariant = ReactionProduct.selectedVariant(); + let qtyField; + let quantity; + const currentVariant = ReactionProduct.selectedVariant(); if (currentVariant) { qtyField = template.$('input[name="addToCartQty"]'); quantity = qtyField.val(); @@ -278,8 +273,8 @@ Template.productDetail.events({ let productId; let qtyField; let quantity; - let currentVariant = ReactionProduct.selectedVariant(); - let currentProduct = ReactionProduct.selectedProduct(); + const currentVariant = ReactionProduct.selectedVariant(); + const currentProduct = ReactionProduct.selectedProduct(); if (currentVariant) { if (currentVariant.ancestors.length === 1) { @@ -341,15 +336,36 @@ Template.productDetail.events({ scrollTop: 0 }, 0); // slide out label - let addToCartText = i18next.t("productDetail.addedToCart"); - let addToCartTitle = currentVariant.title || ""; + const addToCartText = i18next.t("productDetail.addedToCart"); + const addToCartTitle = currentVariant.title || ""; $(".cart-alert-text").text(`${quantity} ${addToCartTitle} ${addToCartText}`); - return $(".cart-alert").toggle("slide", { - direction: i18next.t("languageDirection") === "rtl" ? "left" : "right", - width: currentVariant.title.length + 50 + "px" - }, 600).delay(4000).toggle("slide", { - direction: i18next.t("languageDirection") === "rtl" ? "left" : "right" - }); + + // Grab and cache the width of the alert to be used in animation + const alertWidth = $(".cart-alert").width(); + const direction = i18next.t("languageDirection") === "rtl" ? "left" : "right"; + const oppositeDirection = i18next.t("languageDirection") === "rtl" ? "right" : "left"; + + // Animate + return $(".cart-alert") + .show() + .css({ + [oppositeDirection]: "auto", + [direction]: -alertWidth + }) + .animate({ + [oppositeDirection]: "auto", + [direction]: 0 + }, 600) + .delay(4000) + .animate({ + [oppositeDirection]: "auto", + [direction]: -alertWidth + }, { + duration: 600, + complete() { + $(".cart-alert").hide(); + } + }); } } else { Alerts.inline("Select an option before adding to cart", "warning", { diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/productImageGallery.js b/imports/plugins/included/product-variant/client/templates/products/productDetail/productImageGallery.js index 0f5ce195422..64e09ebb694 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/productImageGallery.js +++ b/imports/plugins/included/product-variant/client/templates/products/productDetail/productImageGallery.js @@ -5,9 +5,8 @@ import { Media } from "/lib/collections"; import { Meteor } from "meteor/meteor"; import { Session } from "meteor/session"; import { Template } from "meteor/templating"; +import Sortable from "sortablejs"; -// load modules -require("jquery-ui"); /** * productImageGallery helpers */ @@ -21,7 +20,7 @@ function uploadHandler(event) { // and it `Blob`s which is our event.target.files. // There is a way to do this: http://stackoverflow.com/a/24003932. but it's too // tricky - let productId = ReactionProduct.selectedProductId(); + const productId = ReactionProduct.selectedProductId(); const variant = ReactionProduct.selectedVariant(); if (typeof variant !== "object") { return Alerts.add("Please, create new Variant first.", "danger", { @@ -29,8 +28,8 @@ function uploadHandler(event) { }); } const variantId = variant._id; - let shopId = ReactionProduct.selectedProduct().shopId || Reaction.getShopId(); - let userId = Meteor.userId(); + const shopId = ReactionProduct.selectedProduct().shopId || Reaction.getShopId(); + const userId = Meteor.userId(); let count = Media.find({ "metadata.variantId": variantId }).count(); @@ -60,24 +59,17 @@ function uploadHandler(event) { * updateImagePriorities method */ function updateImagePriorities() { - const sortedMedias = _.map($(".gallery").sortable("toArray", { - attribute: "data-index" - }), function (index) { - return { - mediaId: index - }; - }); - - const results = []; - sortedMedias.forEach((image, index) => { - results.push(Media.update(image.mediaId, { - $set: { - "metadata.priority": index - } - })); - }); - - return results; + $(".gallery > .gallery-image") + .toArray() + .map((element, index) => { + const mediaId = element.getAttribute("data-index"); + + Media.update(mediaId, { + $set: { + "metadata.priority": index + } + }); + }); } /** @@ -87,7 +79,7 @@ function updateImagePriorities() { Template.productImageGallery.helpers({ media: function () { let mediaArray = []; - let variant = ReactionProduct.selectedVariant(); + const variant = ReactionProduct.selectedVariant(); if (variant) { mediaArray = Media.find({ @@ -110,28 +102,16 @@ Template.productImageGallery.helpers({ */ Template.productImageGallery.onRendered(function () { - return this.autorun(function () { + this.autorun(function () { let $gallery; if (Reaction.hasAdminAccess()) { - $gallery = $(".gallery"); - return $gallery.sortable({ - cursor: "move", - opacity: 0.3, - placeholder: "sortable", - forcePlaceholderSize: true, - update: function () { - let variant; - if (typeof variant !== "object") { - variant = ReactionProduct.selectedVariant(); - } - variant.medias = []; - return updateImagePriorities(); - }, - start: function (event, ui) { - ui.placeholder.html("Drop image to reorder"); - ui.placeholder.css("padding-top", "30px"); - ui.placeholder.css("border", "1px dashed #ccc"); - return ui.placeholder.css("border-radius", "6px"); + $gallery = $(".gallery")[0]; + + this.sortable = Sortable.create($gallery, { + group: "gallery", + handle: ".gallery-image", + onUpdate() { + updateImagePriorities(); } }); } @@ -150,8 +130,8 @@ Template.productImageGallery.events({ return undefined; } if (!Reaction.hasPermission("createProduct")) { - let first = $(".gallery li:nth-child(1)"); - let target = $(event.currentTarget); + const first = $(".gallery li:nth-child(1)"); + const target = $(event.currentTarget); if ($(target).data("index") !== first.data("index")) { return $(".gallery li:nth-child(1)").fadeOut(400, function () { $(this).replaceWith(target); diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/tags.html b/imports/plugins/included/product-variant/client/templates/products/productDetail/tags.html deleted file mode 100644 index a08f1629433..00000000000 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/tags.html +++ /dev/null @@ -1,51 +0,0 @@ - - - diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/tags.js b/imports/plugins/included/product-variant/client/templates/products/productDetail/tags.js deleted file mode 100644 index 2a72c11d933..00000000000 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/tags.js +++ /dev/null @@ -1,110 +0,0 @@ -import { $ } from "meteor/jquery"; -import { ReactionProduct } from "/lib/api"; -import { Reaction } from "/client/api"; -import { Tags } from "/lib/collections"; - -// load modules -require("jquery-ui"); - -Template.productDetailTags.helpers({ - tags: function () { - const instance = this; - return instance.tags; - }, - currentHashTag: function () { - let product = ReactionProduct.selectedProduct(); - if (product) { - if (product.handle) { - if (this.handle === product.handle.toLowerCase() || Reaction.getSlug(product.handle) === this.slug) { - return true; - } - } - } - } -}); - -Template.productTagInputForm.helpers({ - hashtagMark: function () { - const product = ReactionProduct.selectedProduct(); - if (product) { - if (product.handle) { - if (this.handle === product.handle.toLowerCase() || Reaction.getSlug(product.handle) === this.slug) { - return "fa-bookmark"; - } - } - return "fa-bookmark-o"; - } - } -}); - -Template.productTagInputForm.events({ - "click .tag-input-hashtag": function () { - return Meteor.call("products/setHandleTag", ReactionProduct.selectedProductId(), this._id, - function (error, result) { - if (result) { - return Reaction.Router.go("product", { - handle: result - }); - } - }); - }, - "click .tag-input-group-remove": function () { - return Meteor.call("products/removeProductTag", ReactionProduct.selectedProductId(), - this._id); - }, - "click .tags-input-select": function (event) { - return $(event.currentTarget).autocomplete({ - delay: 0, - autoFocus: true, - source: function (request, response) { - let datums = []; - let slug = Reaction.getSlug(request.term); - Tags.find({ - slug: new RegExp(slug, "i") - }).forEach(function (tag) { - return datums.push({ - label: tag.name - }); - }); - return response(datums); - } - }); - }, - "focusout .tags-input-select": function (event, template) { - let val = $(event.currentTarget).val(); - if (val) { - return Meteor.call("products/updateProductTags", ReactionProduct.selectedProductId(), - val, this._id, - function (error) { - template.$(".tags-submit-new").val("").focus(); - if (error) { - Alerts.toast("Tag already exists, or is empty.", "error"); - return false; - } - }); - } - }, - "mousedown .tag-input-group-handle": function () { - return $(".tag-edit-list").sortable("refresh"); - } -}); - -Template.productTagInputForm.onRendered(function () { - return $(".tag-edit-list").sortable({ - items: "> li", - handle: ".tag-input-group-handle", - update: function () { - let hashtagsList = []; - let uiPositions = $(this).sortable("toArray", { - attribute: "data-tag-id" - }); - for (let tag of uiPositions) { - if (_.isEmpty(tag) === false) { - hashtagsList.push(tag); - } - } - return Meteor.call("products/updateProductField", - ReactionProduct.selectedProductId(), "hashtags", _.uniq(hashtagsList)); - } - }); -}); diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variant.js b/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variant.js index f3387b325fa..89cc359b65d 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variant.js +++ b/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variant.js @@ -1,14 +1,9 @@ -import { $ } from "meteor/jquery"; import { Reaction } from "/client/api"; import { ReactionProduct } from "/lib/api"; import { EditButton } from "/imports/plugins/core/ui/client/components"; -import { Meteor } from "meteor/meteor"; import { Session } from "meteor/session"; import { Template } from "meteor/templating"; -// load modules -require("jquery-ui"); - // Duplicated in variantList/variantList.js function variantIsSelected(variantId) { const current = ReactionProduct.selectedVariant(); @@ -113,41 +108,3 @@ Template.variant.events({ } } }); - -/** - * variant onRendered - */ - -Template.variant.onRendered(function () { - return this.autorun(function () { - let variantSort; - if (Reaction.hasPermission("createProduct")) { - variantSort = $(".variant-list"); - return variantSort.sortable({ - items: "> li.variant-list-item", - cursor: "move", - opacity: 0.3, - helper: "clone", - placeholder: "variant-sortable", - forcePlaceholderSize: true, - axis: "y", - update: function () { - const uiPositions = $(this).sortable("toArray", { - attribute: "data-id" - }); - Meteor.defer(function () { - Meteor.call("products/updateVariantsPosition", uiPositions); - }); - }, - start: function (event, ui) { - ui.placeholder.height(ui.helper.height()); - ui.placeholder.html("Drop variant to reorder"); - ui.placeholder.css("padding-top", ui.helper.height() / - 3); - ui.placeholder.css("border", "1px dashed #ccc"); - return ui.placeholder.css("border-radius", "6px"); - } - }); - } - }); -}); diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantForm/childVariant.js b/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantForm/childVariant.js index ec3ebc552fb..1d9cb8f3a2d 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantForm/childVariant.js +++ b/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantForm/childVariant.js @@ -60,7 +60,7 @@ Template.childVariantForm.helpers({ const variantId = currentData._id; return (files) => { - for (let file of files) { + for (const file of files) { file.metadata = { variantId, productId, @@ -112,7 +112,7 @@ Template.childVariantForm.events({ }); return ReactionProduct.setCurrentVariant(variant._id); }, - "click .js-child-varaint-heading": function(event, instance) { + "click .js-child-varaint-heading": function (event, instance) { const selectedProduct = ReactionProduct.selectedProduct(); const variantId = instance.data._id; diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantForm/variantForm.js b/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantForm/variantForm.js index 033a687a878..262be4973ae 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantForm/variantForm.js +++ b/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantForm/variantForm.js @@ -92,10 +92,10 @@ Template.variantForm.events({ // this should really move into a method // if (field === "taxable" || field === "inventoryManagement" || field === "inventoryPolicy") { - let value = $(event.currentTarget).prop("checked"); + const value = $(event.currentTarget).prop("checked"); if (ReactionProduct.checkChildVariants(template.data._id) > 0) { const childVariants = ReactionProduct.getVariants(template.data._id); - for (let child of childVariants) { + for (const child of childVariants) { Meteor.call("products/updateProductField", child._id, field, value, error => { if (error) { @@ -105,28 +105,22 @@ Template.variantForm.events({ } } } - // template.$(formId).submit(); // ReactionProduct.setCurrentVariant(template.data._id); - // - // - // }, "click .btn-child-variant-form": function (event, template) { - let productId; event.stopPropagation(); event.preventDefault(); - productId = ReactionProduct.selectedProductId(); + const productId = ReactionProduct.selectedProductId(); if (!productId) { return; } Meteor.call("products/createVariant", template.data._id); }, "click .btn-clone-variant": function (event, template) { - let productId; event.stopPropagation(); event.preventDefault(); - productId = ReactionProduct.selectedProductId(); + const productId = ReactionProduct.selectedProductId(); if (!productId) { return; } diff --git a/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantList/variantList.js b/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantList/variantList.js index 8dcec58ed1c..6308136de6a 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantList/variantList.js +++ b/imports/plugins/included/product-variant/client/templates/products/productDetail/variants/variantList/variantList.js @@ -1,10 +1,11 @@ -import { Reaction, i18next } from "/client/api"; +import { Reaction } from "/client/api"; import { ReactionProduct } from "/lib/api"; import { Products, Media } from "/lib/collections"; import { EditButton } from "/imports/plugins/core/ui/client/components"; import { Meteor } from "meteor/meteor"; import { Session } from "meteor/session"; import { Template } from "meteor/templating"; +import Sortable from "sortablejs"; function variantIsSelected(variantId) { const current = ReactionProduct.selectedVariant(); @@ -26,6 +27,39 @@ function variantIsInActionView(variantId) { return false; } +/** + * variant onRendered + */ + +Template.variantList.onRendered(function () { + const instance = this; + + return this.autorun(function () { + if (Reaction.hasPermission("createProduct")) { + const variantSort = $(".variant-list")[0]; + + this.sortable = Sortable.create(variantSort, { + group: "variant-list", + handle: ".variant-list-item", + onUpdate() { + const positions = instance.$(".variant-list-item") + .toArray() + .map((element) => { + return element.getAttribute("data-id"); + }); + + Meteor.defer(function () { + Meteor.call("products/updateVariantsPosition", positions); + }); + + Tracker.flush(); + } + }); + } + }); +}); + + /** * variantList helpers */ @@ -46,17 +80,17 @@ Template.variantList.helpers({ const variants = ReactionProduct.getTopVariants(); if (variants.length) { // calculate inventory total for all variants - for (let variant of variants) { + for (const variant of variants) { if (variant.inventoryManagement) { - let qty = ReactionProduct.getVariantQuantity(variant); + const qty = ReactionProduct.getVariantQuantity(variant); if (typeof qty === "number") { inventoryTotal += qty; } } } // calculate percentage of total inventory of this product - for (let variant of variants) { - let qty = ReactionProduct.getVariantQuantity(variant); + for (const variant of variants) { + const qty = ReactionProduct.getVariantQuantity(variant); variant.inventoryTotal = inventoryTotal; if (variant.inventoryManagement && inventoryTotal) { variant.inventoryPercentage = parseInt(qty / inventoryTotal * 100, 10); diff --git a/imports/plugins/included/product-variant/client/templates/products/productGrid/item.js b/imports/plugins/included/product-variant/client/templates/products/productGrid/item.js index 632ce41d684..e8dbdd8417e 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productGrid/item.js +++ b/imports/plugins/included/product-variant/client/templates/products/productGrid/item.js @@ -9,9 +9,6 @@ import Logger from "/client/modules/logger"; import { ReactionProduct } from "/lib/api"; import { Media } from "/lib/collections"; -// load modules -require("jquery-ui"); - /** * productGridItems helpers */ @@ -64,12 +61,12 @@ Template.productGridItems.helpers({ const positions = this.positions && this.positions[tag] || {}; const weight = positions.weight || 0; switch (weight) { - case 1: - return "product-medium"; - case 2: - return "product-large"; - default: - return "product-small"; + case 1: + return "product-medium"; + case 2: + return "product-large"; + default: + return "product-small"; } }, isSelected: function () { @@ -178,42 +175,3 @@ Template.productGridItems.events({ return Tracker.flush(); } }); - -Template.productGridItems.onRendered(function () { - if (Reaction.hasPermission("createProduct")) { - let productSort = $(".product-grid-list"); - - productSort.sortable({ - items: "> li.product-grid-item", - cursor: "move", - opacity: 0.5, - revert: true, - scroll: false, - update: function (event, ui) { - let productId = ui.item[0].id; - let uiPositions = $(this).sortable("toArray", { - attribute: "data-id" - }); - let index = _.indexOf(uiPositions, productId); - let _i; - let _len; - const tag = ReactionProduct.getTag(); - for (index = _i = 0, _len = uiPositions.length; _i < _len; index = ++_i) { - productId = uiPositions[index]; - let position = { - position: index, - updatedAt: new Date() - }; - Meteor.call("products/updateProductPosition", productId, position, tag, - error => { - if (error) { - Logger.warn(error); - throw new Meteor.Error(403, error); - } - }); - } - return Tracker.flush(); - } - }); - } -}); diff --git a/imports/plugins/included/product-variant/client/templates/products/productGrid/productGrid.js b/imports/plugins/included/product-variant/client/templates/products/productGrid/productGrid.js index edaffa1ed52..2a495d0f66a 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productGrid/productGrid.js +++ b/imports/plugins/included/product-variant/client/templates/products/productGrid/productGrid.js @@ -2,6 +2,9 @@ import _ from "lodash"; import { Session } from "meteor/session"; import { Template } from "meteor/templating"; import { Reaction } from "/client/api"; +import Logger from "/client/modules/logger"; +import { ReactionProduct } from "/lib/api"; +import Sortable from "sortablejs"; /** * productGrid helpers @@ -11,6 +14,42 @@ Template.productGrid.onCreated(function () { Session.set("productGrid/selectedProducts", []); }); +Template.productGrid.onRendered(function () { + const instance = this; + + if (Reaction.hasPermission("createProduct")) { + const productSort = $(".product-grid-list")[0]; + + this.sortable = Sortable.create(productSort, { + group: "products", + handle: ".product-grid-item", + onUpdate() { + const tag = ReactionProduct.getTag(); + + instance.$(".product-grid-item") + .toArray() + .map((element, index) => { + const productId = element.getAttribute("id"); + const position = { + position: index, + updatedAt: new Date() + }; + + Meteor.call("products/updateProductPosition", productId, position, tag, + error => { + if (error) { + Logger.warn(error); + throw new Meteor.Error(403, error); + } + }); + }); + + Tracker.flush(); + } + }); + } +}); + Template.productGrid.events({ "click [data-event-action=loadMoreProducts]": (event) => { event.preventDefault(); @@ -27,12 +66,12 @@ Template.productGrid.events({ Session.set("productGrid/selectedProducts", _.uniq(selectedProducts)); - let productCursor = Template.currentData().products; + const productCursor = Template.currentData().products; if (productCursor) { const products = productCursor.fetch(); - let filteredProducts = _.filter(products, (product) => { + const filteredProducts = _.filter(products, (product) => { return _.includes(selectedProducts, product._id); }); diff --git a/imports/plugins/included/product-variant/client/templates/products/productList/productList.js b/imports/plugins/included/product-variant/client/templates/products/productList/productList.js index 24298e4a5c9..3c339c97d07 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productList/productList.js +++ b/imports/plugins/included/product-variant/client/templates/products/productList/productList.js @@ -13,7 +13,7 @@ Template.productList.helpers({ let defaultImage; const variants = getTopVariants(); if (variants.length > 0) { - let variantId = variants[0]._id; + const variantId = variants[0]._id; defaultImage = Media.findOne({ "metadata.variantId": variantId, "metadata.priority": 0 diff --git a/imports/plugins/included/product-variant/client/templates/products/productSettings/productSettings.js b/imports/plugins/included/product-variant/client/templates/products/productSettings/productSettings.js index 32d1a75c18c..202d4cdf041 100644 --- a/imports/plugins/included/product-variant/client/templates/products/productSettings/productSettings.js +++ b/imports/plugins/included/product-variant/client/templates/products/productSettings/productSettings.js @@ -38,9 +38,9 @@ Template.productSettings.helpers({ const products = instance.state.get("products"); const tag = ReactionProduct.getTag(); - for (let product of products) { - let positions = product.positions && product.positions[tag] || {}; - let currentWeight = positions.weight || 0; + for (const product of products) { + const positions = product.positions && product.positions[tag] || {}; + const currentWeight = positions.weight || 0; if (currentWeight === weight) { return "active"; } @@ -54,6 +54,7 @@ Template.productSettingsGridItem.helpers({ if (this._id) { return ReactionProduct.getProductPriceRange(this._id).range; } + return null; }, media: function () { @@ -84,12 +85,12 @@ Template.productSettingsGridItem.helpers({ const positions = this.positions && this.positions[tag] || {}; const weight = positions.weight || 0; switch (weight) { - case 1: - return "product-medium"; - case 2: - return "product-large"; - default: - return "product-small"; + case 1: + return "product-medium"; + case 2: + return "product-large"; + default: + return "product-small"; } }, @@ -132,12 +133,16 @@ Template.productSettings.events({ "click [data-event-action=changeProductWeight]": function (event) { event.preventDefault(); const tag = ReactionProduct.getTag(); - for (let product of this.products) { - let weight = $(event.currentTarget).data("event-data") || 0; - let positions = { + for (const product of this.products) { + const weight = $(event.currentTarget).data("event-data") || 0; + const positions = { weight: weight, updatedAt: new Date() }; + /* eslint no-loop-func: 1 */ + // + // TODO review Template.productSettings events for no-loop-func + // Meteor.call("products/updateProductPosition", product._id, positions, tag, (error) => { if (error) { diff --git a/imports/plugins/included/product-variant/client/templates/products/products.js b/imports/plugins/included/product-variant/client/templates/products/products.js index fd447e72e2b..01d20befe42 100644 --- a/imports/plugins/included/product-variant/client/templates/products/products.js +++ b/imports/plugins/included/product-variant/client/templates/products/products.js @@ -14,7 +14,7 @@ import { ITEMS_INCREMENT } from "/client/config/defaults"; */ function loadMoreProducts() { let threshold; - let target = $("#productScrollLimitLoader"); + const target = $("#productScrollLimitLoader"); let scrollContainer = $("#reactionAppContainer"); if (scrollContainer.length === 0) { diff --git a/imports/plugins/included/shipping/client/templates/shipping.js b/imports/plugins/included/shipping/client/templates/shipping.js index 39e8a2e85fe..9db54d7ac11 100644 --- a/imports/plugins/included/shipping/client/templates/shipping.js +++ b/imports/plugins/included/shipping/client/templates/shipping.js @@ -154,19 +154,19 @@ Template.shippingProviderTable.helpers({ return Shipping.find(); }, selectedShippingMethod() { - let session = Session.get("selectedShippingMethod"); + const session = Session.get("selectedShippingMethod"); if (_.isEqual(this, session)) { return this; } }, selectedAddShippingMethod() { - let session = Session.get("selectedAddShippingMethod"); + const session = Session.get("selectedAddShippingMethod"); if (_.isEqual(this, session)) { return this; } }, selectedShippingProvider() { - let session = Session.get("selectedShippingProvider"); + const session = Session.get("selectedShippingProvider"); if (_.isEqual(this, session)) { return this; } @@ -267,7 +267,7 @@ AutoForm.hooks({ "shipping-method-edit-form": { onSubmit(insertDoc, updateDoc, currentDoc) { let error; - let providerId = Template.instance().parentTemplate(4).$(".delete-shipping-method").data("provider-id"); + const providerId = Template.instance().parentTemplate(4).$(".delete-shipping-method").data("provider-id"); try { _.extend(insertDoc, { _id: currentDoc._id }); Meteor.call("updateShippingMethods", providerId, currentDoc._id, insertDoc); diff --git a/imports/plugins/included/shipping/server/methods.js b/imports/plugins/included/shipping/server/methods.js index 233c64de7ed..8c95cedadd8 100644 --- a/imports/plugins/included/shipping/server/methods.js +++ b/imports/plugins/included/shipping/server/methods.js @@ -24,10 +24,10 @@ Meteor.methods({ /** * updateShippingMethods * @summary update Shipping methods for a provider - * @param {String} providerId - * @param {String} methodId + * @param {String} providerId providerId + * @param {String} methodId methodId * @param {Object} updateMethod - updated method itself - * @return update result + * @return {Number} update result */ updateShippingMethods: function (providerId, methodId, updateMethod) { check(providerId, String); @@ -58,11 +58,11 @@ Meteor.methods({ } return Shipping.update({ - '_id': providerId, - 'methods': removeDoc + _id: providerId, + methods: removeDoc }, { $pull: { - 'methods': removeDoc + methods: removeDoc } }); }, @@ -88,7 +88,7 @@ Meteor.methods({ throw new Meteor.Error(403, "Access Denied"); } return Shipping.update({ - '_id': currentDoc + _id: currentDoc }, updateDoc); } }); diff --git a/imports/plugins/included/social/client/templates/apps/facebook.js b/imports/plugins/included/social/client/templates/apps/facebook.js index 0b89e368558..d076dac2861 100644 --- a/imports/plugins/included/social/client/templates/apps/facebook.js +++ b/imports/plugins/included/social/client/templates/apps/facebook.js @@ -1,94 +1,105 @@ -Template.facebook.onRendered(function() { - var ref; - if (this.data.placement === 'footer' && (((ref = this.data.apps.facebook) != null ? ref.profilePage : void 0) != null)) { - return this.$('.facebook-share').attr('href', this.data.apps.facebook.profilePage); - } else { - this.autorun(function() { - var base, data, description, href, media, ref1, summary, template, title, url; - template = Template.instance(); - data = Template.currentData(); - $('meta[property^="og:"]').remove(); - description = ((ref1 = data.apps.facebook) != null ? ref1.description : void 0) || $('.product-detail-field.description').text(); - url = data.url || location.origin + location.pathname; - title = data.title || document.title; - $('', { - property: 'og:type', - content: 'article' - }).appendTo('head'); - $('', { - property: 'og:site_name', - content: location.hostname - }).appendTo('head'); - $('', { - property: 'og:url', - content: url - }).appendTo('head'); - $('', { - property: 'og:title', - content: title - }).appendTo('head'); - $('', { - property: 'og:description', - content: description - }).appendTo('head'); - if (data.media) { - if (!/^http(s?):\/\/+/.test(data.media)) { - media = location.origin + data.media; - } - $('', { - property: 'og:image', - content: media - }).appendTo('head'); - } - if (data.apps.facebook.appId != null) { - return template.$('.facebook-share').click(function(e) { - e.preventDefault(); - return FB.ui({ - method: 'share', - display: 'popup', - href: url - }, function(response) {}); - }); - } else { - url = encodeURIComponent(url); - base = "https://www.facebook.com/sharer/sharer.php"; - title = encodeURIComponent(title); - summary = encodeURIComponent(description); - href = base + "?s=100&p[url]=" + url + "&p[title]=" + title + "&p[summary]=" + summary; - if (data.media) { - href += "&p[images][0]=" + encodeURIComponent(media); - } - return template.$(".facebook-share").attr("href", href); - } - }); +/* eslint no-cond-assign: 1 */ +// +// TODO facebook social templates need review to ensure proper use of reaction layouts +// +Template.facebook.onRendered(function () { + let ref; + if (this.data.placement === "footer" && (((ref = this.data.apps.facebook) !== null ? ref.profilePage : void 0) !== null)) { + return this.$(".facebook-share").attr("href", this.data.apps.facebook.profilePage); } + // + // autorun and insert fb + // + this.autorun(function () { + let media; + let ref1; + const template = Template.instance(); + const data = Template.currentData(); + $('meta[property^="og:"]').remove(); + const description = ((ref1 = data.apps.facebook) !== null ? ref1.description : void 0) || $(".product-detail-field.description").text(); + let url = data.url || location.origin + location.pathname; + let title = data.title || document.title; + $("", { + property: "og:type", + content: "article" + }).appendTo("head"); + $("", { + property: "og:site_name", + content: location.hostname + }).appendTo("head"); + $("", { + property: "og:url", + content: url + }).appendTo("head"); + $("", { + property: "og:title", + content: title + }).appendTo("head"); + $("", { + property: "og:description", + content: description + }).appendTo("head"); + if (data.media) { + if (!/^http(s?):\/\/+/.test(data.media)) { + media = location.origin + data.media; + } + $("", { + property: "og:image", + content: media + }).appendTo("head"); + } + /* eslint no-unused-vars: 1 */ + // + // TODO review Template.facebook.onRendered for FB response + // believe this object is declared by FB so the + // lint error should be ignored + // + if (data.apps.facebook.appId !== null) { + return template.$(".facebook-share").click(function (e) { + e.preventDefault(); + return FB.ui({ + method: "share", + display: "popup", + href: url + }, function (response) {}); + }); + } + // else return + url = encodeURIComponent(url); + title = encodeURIComponent(title); + const base = "https://www.facebook.com/sharer/sharer.php"; + const summary = encodeURIComponent(description); + let href = base + "?s=100&p[url]=" + url + "&p[title]=" + title + "&p[summary]=" + summary; + if (data.media) { + href += "&p[images][0]=" + encodeURIComponent(media); + } + return template.$(".facebook-share").attr("href", href); + }); }); -Template.facebook.onCreated(function() { - var apps, isEnabled; - apps = Template.currentData().apps; - isEnabled = 'facebook' in apps && apps.facebook.enabled; +Template.facebook.onCreated(function () { + const apps = Template.currentData().apps; + const isEnabled = "facebook" in apps && apps.facebook.enabled; if (isEnabled) { - $('
').appendTo('body'); - window.fbAsyncInit = function() { + $('
').appendTo("body"); + window.fbAsyncInit = function () { return FB.init({ appId: apps.facebook.appId, xfbml: true, - version: 'v2.1' + version: "v2.1" }); }; - (function(d, s, id) { - var fjs, js; - js = void 0; - fjs = d.getElementsByTagName(s)[0]; + (function (d, s, id) { + let js = void 0; + const fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) { return; } js = d.createElement(s); js.id = id; - js.src = '//connect.facebook.net/en_US/sdk.js'; + js.src = "//connect.facebook.net/en_US/sdk.js"; fjs.parentNode.insertBefore(js, fjs); - })(document, 'script', 'facebook-jssdk'); + })(document, "script", "facebook-jssdk"); } return isEnabled; }); diff --git a/imports/plugins/included/social/client/templates/apps/googleplus.js b/imports/plugins/included/social/client/templates/apps/googleplus.js index 2fe902f18de..d877891aa3a 100644 --- a/imports/plugins/included/social/client/templates/apps/googleplus.js +++ b/imports/plugins/included/social/client/templates/apps/googleplus.js @@ -1,48 +1,53 @@ -Template.googleplus.onRendered(function() { - var ref; - if (this.data.placement === 'footer' && (((ref = this.data.apps.googleplus) != null ? ref.profilePage : void 0) != null)) { - return this.$('.googleplus-share').attr('href', this.data.apps.googleplus.profilePage); - } else { - return this.autorun(function() { - var data, description, href, itemtype, media, ref1, ref2, template, title, url; - template = Template.instance(); - data = Template.currentData(); - $('meta[itemscope]').remove(); - description = ((ref1 = data.apps.googleplus) != null ? ref1.description : void 0) || $('.product-detail-field.description').text(); - url = data.url || location.origin + location.pathname; - title = data.title; - itemtype = ((ref2 = data.apps.googleplus) != null ? ref2.itemtype : void 0) || 'Article'; - $('html').attr('itemscope', '').attr('itemtype', "http://schema.org/" + itemtype); - $('', { - itemprop: 'name', - content: location.hostname - }).appendTo('head'); - $('', { - itemprop: 'url', - content: url - }).appendTo('head'); - $('', { - itemprop: 'description', - content: description - }).appendTo('head'); - if (data.media) { - if (!/^http(s?):\/\/+/.test(data.media)) { - media = location.origin + data.media; - } - $('', { - itemprop: 'image', - content: media - }).appendTo('head'); - } - href = "https://plus.google.com/share?url=" + url; - return template.$(".googleplus-share").attr("href", href); - }); +/* eslint no-cond-assign: 1 */ +// +// TODO google social templates need review to ensure proper use of reaction layouts +// +Template.googleplus.onRendered(function () { + let ref; + if (this.data.placement === "footer" && (((ref = this.data.apps.googleplus) !== null ? ref.profilePage : void 0) !== null)) { + return this.$(".googleplus-share").attr("href", this.data.apps.googleplus.profilePage); } + return this.autorun(function () { + let media; + let ref1; + let ref2; + const template = Template.instance(); + const data = Template.currentData(); + $("meta[itemscope]").remove(); + const description = ((ref1 = data.apps.googleplus) !== null ? ref1.description : void 0) || $(".product-detail-field.description").text(); + const url = data.url || location.origin + location.pathname; + // const title = data.title; + const itemtype = ((ref2 = data.apps.googleplus) !== null ? ref2.itemtype : void 0) || "Article"; + $("html").attr("itemscope", "").attr("itemtype", "http://schema.org/" + itemtype); + $("", { + itemprop: "name", + content: location.hostname + }).appendTo("head"); + $("", { + itemprop: "url", + content: url + }).appendTo("head"); + $("", { + itemprop: "description", + content: description + }).appendTo("head"); + if (data.media) { + if (!/^http(s?):\/\/+/.test(data.media)) { + media = location.origin + data.media; + } + $("", { + itemprop: "image", + content: media + }).appendTo("head"); + } + const href = "https://plus.google.com/share?url=" + url; + return template.$(".googleplus-share").attr("href", href); + }); }); Template.googleplus.events({ - 'click a': function(event, template) { + "click a": function (event) { event.preventDefault(); - return window.open(Template.instance().$('.googleplus-share').attr('href'), 'googleplus_window', 'width=750, height=650'); + return window.open(Template.instance().$(".googleplus-share").attr("href"), "googleplus_window", "width=750, height=650"); } }); diff --git a/imports/plugins/included/social/client/templates/apps/pinterest.js b/imports/plugins/included/social/client/templates/apps/pinterest.js index ca6b062f315..2c7a91f586e 100644 --- a/imports/plugins/included/social/client/templates/apps/pinterest.js +++ b/imports/plugins/included/social/client/templates/apps/pinterest.js @@ -1,36 +1,39 @@ -Template.pinterest.onRendered(function() { - var ref; - if (this.data.placement === 'footer' && (((ref = this.data.apps.pinterest) != null ? ref.profilePage : void 0) != null)) { - return this.$('.pinterest-share').attr('href', this.data.apps.pinterest.profilePage); - } else { - - /* - Pinterest requires three parameters: - url: desired url - media: image being shared - description: image description - */ - return this.autorun(function() { - var data, description, href, media, preferred_url, ref1, template, url; - template = Template.instance(); - data = Template.currentData(); - preferred_url = data.url || location.origin + location.pathname; - url = encodeURIComponent(preferred_url); - if (data.media) { - if (!/^http(s?):\/\/+/.test(data.media)) { - media = location.origin + data.media; - } - } - description = encodeURIComponent(((ref1 = data.apps.pinterest) != null ? ref1.description : void 0) || $('.product-detail-field.description').text()); - href = "http://www.pinterest.com/pin/create/button/?url=" + url + "&media=" + media + "&description=" + description; - return template.$('.pinterest-share').attr('href', href); - }); +/* eslint no-cond-assign: 1 */ +// +// TODO pinterest social templates need review to ensure proper use of reaction layouts +// +Template.pinterest.onRendered(function () { + let ref; + if (this.data.placement === "footer" && (((ref = this.data.apps.pinterest) !== null ? ref.profilePage : void 0) !== null)) { + return this.$(".pinterest-share").attr("href", this.data.apps.pinterest.profilePage); } + /* + Pinterest requires three parameters: + url: desired url + media: image being shared + description: image description + */ + return this.autorun(function () { + let media; + let ref1; + const template = Template.instance(); + const data = Template.currentData(); + const preferredUrl = data.url || location.origin + location.pathname; + const url = encodeURIComponent(preferredUrl); + if (data.media) { + if (!/^http(s?):\/\/+/.test(data.media)) { + media = location.origin + data.media; + } + } + const description = encodeURIComponent(((ref1 = data.apps.pinterest) !== null ? ref1.description : void 0) || $(".product-detail-field.description").text()); + const href = "http://www.pinterest.com/pin/create/button/?url=" + url + "&media=" + media + "&description=" + description; + return template.$(".pinterest-share").attr("href", href); + }); }); Template.pinterest.events({ - 'click a': function(event, template) { + "click a": function (event) { event.preventDefault(); - return window.open(Template.instance().$('.pinterest-share').attr('href'), 'pinterest_window', 'width=750, height=650'); + return window.open(Template.instance().$(".pinterest-share").attr("href"), "pinterest_window", "width=750, height=650"); } }); diff --git a/imports/plugins/included/social/client/templates/apps/twitter.js b/imports/plugins/included/social/client/templates/apps/twitter.js index a0ce37a56e5..73f5ad254bc 100644 --- a/imports/plugins/included/social/client/templates/apps/twitter.js +++ b/imports/plugins/included/social/client/templates/apps/twitter.js @@ -1,61 +1,68 @@ -Template.twitter.onRendered(function() { - var ref; - if (this.data.placement === 'footer' && (((ref = this.data.apps.twitter) != null ? ref.profilePage : void 0) != null)) { - return this.$('.twitter-share').attr('href', this.data.apps.twitter.profilePage); - } else { - return this.autorun(function() { - var base, data, description, href, media, preferred_url, ref1, ref2, template, text, url; - template = Template.instance(); - data = Template.currentData(); - $('meta[property^="twitter:"]').remove(); - $('', { - property: 'twitter:card', - content: 'summary' - }).appendTo('head'); - if (data.apps.twitter.username) { - $('', { - property: 'twitter:creator', - content: data.apps.twitter.username - }).appendTo('head'); - } - description = ((ref1 = data.apps.twitter) != null ? ref1.description : void 0) || $('.product-detail-field.description').text(); - $('', { - property: 'twitter:url', - content: location.origin + location.pathname - }).appendTo('head'); - $('', { - property: 'twitter:title', - content: "" + data.title - }).appendTo('head'); - $('', { - property: 'twitter:description', - content: description - }).appendTo('head'); - if (data.media) { - if (!/^http(s?):\/\/+/.test(data.media)) { - media = location.origin + data.media; - $('', { - property: 'twitter:image', - content: data.media - }).appendTo('head'); - } - } - preferred_url = data.url || location.origin + location.pathname; - url = encodeURIComponent(preferred_url); - base = "https://twitter.com/intent/tweet"; - text = encodeURIComponent(((ref2 = data.apps.twitter) != null ? ref2.title : void 0) || data.title); - href = base + "?url=" + url + "&text=" + text; - if (data.apps.twitter.username) { - href += "&via=" + data.apps.twitter.username; - } - return template.$(".twitter-share").attr("href", href); - }); +/* eslint no-cond-assign: 1 */ +// +// TODO twitter social templates need review to ensure proper use of reaction layouts +// +Template.twitter.onRendered(function () { + let ref; + if (this.data.placement === "footer" && (((ref = this.data.apps.twitter) !== null ? ref.profilePage : void 0) !== null)) { + return this.$(".twitter-share").attr("href", this.data.apps.twitter.profilePage); } + // + // return twitter + // + return this.autorun(function () { + const template = Template.instance(); + const data = Template.currentData(); + $('meta[property^="twitter:"]').remove(); + $("", { + property: "twitter:card", + content: "summary" + }).appendTo("head"); + if (data.apps.twitter.username) { + $("", { + property: "twitter:creator", + content: data.apps.twitter.username + }).appendTo("head"); + } + let ref1; + const description = ((ref1 = data.apps.twitter) !== null ? ref1.description : void 0) || $(".product-detail-field.description").text(); + $("", { + property: "twitter:url", + content: location.origin + location.pathname + }).appendTo("head"); + $("", { + property: "twitter:title", + content: "" + data.title + }).appendTo("head"); + $("", { + property: "twitter:description", + content: description + }).appendTo("head"); + if (data.media) { + if (!/^http(s?):\/\/+/.test(data.media)) { + // let media = location.origin + data.media; + $("", { + property: "twitter:image", + content: data.media + }).appendTo("head"); + } + } + const preferredUrl = data.url || location.origin + location.pathname; + const url = encodeURIComponent(preferredUrl); + const base = "https://twitter.com/intent/tweet"; + let ref2; + const text = encodeURIComponent(((ref2 = data.apps.twitter) !== null ? ref2.title : void 0) || data.title); + let href = base + "?url=" + url + "&text=" + text; + if (data.apps.twitter.username) { + href += "&via=" + data.apps.twitter.username; + } + return template.$(".twitter-share").attr("href", href); + }); }); Template.twitter.events({ - 'click a': function(event, template) { + "click a": function (event) { event.preventDefault(); - return window.open(Template.instance().$('.twitter-share').attr('href'), 'twitter_window', 'width=750, height=650'); + return window.open(Template.instance().$(".twitter-share").attr("href"), "twitter_window", "width=750, height=650"); } }); diff --git a/imports/plugins/included/social/client/templates/social.js b/imports/plugins/included/social/client/templates/social.js index 46e29d87c37..61b5271b3a6 100644 --- a/imports/plugins/included/social/client/templates/social.js +++ b/imports/plugins/included/social/client/templates/social.js @@ -3,7 +3,7 @@ import { Packages } from "/lib/collections"; import { merge } from "lodash"; Template.reactionSocial.onCreated(function () { - let self = this; + const self = this; return this.autorun(function () { const subscription = Reaction.Subscriptions.Packages; if (subscription.ready()) { @@ -34,7 +34,7 @@ Template.reactionSocial.helpers({ const appsOrder = socialSettings.appsOrder; for (let i = 0; i < appsOrder.length; i++) { - let app = appsOrder[i]; + const app = appsOrder[i]; if (typeof socialSettings.apps[app] === "object" && socialSettings.apps[app].enabled) { diff --git a/imports/plugins/included/stripe/client/checkout/stripe.js b/imports/plugins/included/stripe/client/checkout/stripe.js index 152edc743a9..32bbd75be51 100644 --- a/imports/plugins/included/stripe/client/checkout/stripe.js +++ b/imports/plugins/included/stripe/client/checkout/stripe.js @@ -71,26 +71,26 @@ AutoForm.addHooks("stripe-payment-form", { uiEnd(template, "Resubmit payment"); } else { if (transaction.saved === true) { - let normalizedStatus = (function () { + const normalizedStatus = (function () { switch (false) { - case !(!transaction.response.captured && !transaction.response.failure_code): - return "created"; - case !(transaction.response.captured === true && !transaction.response.failure_code): - return "settled"; - case !transaction.response.failure_code: - return "failed"; - default: - return "failed"; + case !(!transaction.response.captured && !transaction.response.failure_code): + return "created"; + case !(transaction.response.captured === true && !transaction.response.failure_code): + return "settled"; + case !transaction.response.failure_code: + return "failed"; + default: + return "failed"; } })(); const normalizedMode = (function () { switch (false) { - case !(!transaction.response.captured && !transaction.response.failure_code): - return "authorize"; - case !transaction.response.captured: - return "capture"; - default: - return "capture"; + case !(!transaction.response.captured && !transaction.response.failure_code): + return "authorize"; + case !transaction.response.captured: + return "capture"; + default: + return "capture"; } })(); paymentMethod = { diff --git a/imports/plugins/included/stripe/server/methods/stripe.js b/imports/plugins/included/stripe/server/methods/stripe.js index 5dcaf9dd023..41385eb74da 100644 --- a/imports/plugins/included/stripe/server/methods/stripe.js +++ b/imports/plugins/included/stripe/server/methods/stripe.js @@ -100,7 +100,7 @@ Meteor.methods({ currency: String }); - let chargeObj = { + const chargeObj = { amount: "", currency: "", card: {}, @@ -182,7 +182,7 @@ Meteor.methods({ let result; try { - let refundResult = StripeApi.methods.createRefund.call({ refundDetails }); + const refundResult = StripeApi.methods.createRefund.call({ refundDetails }); Logger.info(refundResult); if (refundResult.object === "refund") { result = { @@ -218,7 +218,7 @@ Meteor.methods({ try { const refunds = StripeApi.methods.listRefunds.call({transactionId: paymentMethod.transactionId}); result = []; - for (let refund of refunds.data) { + for (const refund of refunds.data) { result.push({ type: refund.object, amount: refund.amount / 100, diff --git a/imports/plugins/included/stripe/server/methods/stripeapi-integrationtest.app-test.js b/imports/plugins/included/stripe/server/methods/stripeapi-integrationtest.app-test.js index 507cf6e7b14..6410d327075 100644 --- a/imports/plugins/included/stripe/server/methods/stripeapi-integrationtest.app-test.js +++ b/imports/plugins/included/stripe/server/methods/stripeapi-integrationtest.app-test.js @@ -7,15 +7,15 @@ import { StripeApi } from "./stripeapi"; describe.skip("StripeAPI createCharge function", function () { it("should return a result with status = success", function (done) { - let apiKey = ""; - let cardObject = { + const apiKey = ""; + const cardObject = { number: "4242424242424242", name: "Test User", cvc: "345", exp_month: "02", exp_year: "2019" }; - let chargeObject = { + const chargeObject = { amount: 1999, currency: "USD", card: cardObject, @@ -27,7 +27,7 @@ describe.skip("StripeAPI createCharge function", function () { apiKey: apiKey }); - let result = StripeApi.methods.createCharge.run({ chargeObj: chargeObject, apiKey: apiKey }); + const result = StripeApi.methods.createCharge.run({ chargeObj: chargeObject, apiKey: apiKey }); expect(result.status).to.equal("succeeded"); done(); }); @@ -35,15 +35,15 @@ describe.skip("StripeAPI createCharge function", function () { describe.skip("StripeAPI captureCharge function", function () { it("should return a result with status = success", function (done) { - let apiKey = ""; - let cardObject = { + const apiKey = ""; + const cardObject = { number: "4242424242424242", name: "Test User", cvc: "345", exp_month: "02", exp_year: "2019" }; - let chargeObject = { + const chargeObject = { amount: 1999, currency: "USD", card: cardObject, @@ -54,7 +54,7 @@ describe.skip("StripeAPI captureCharge function", function () { const captureDetails = { amount: 1999 }; - let result = StripeApi.methods.captureCharge.call({ + const result = StripeApi.methods.captureCharge.call({ transactionId: transactionId, captureDetails: captureDetails, apiKey: apiKey @@ -66,15 +66,15 @@ describe.skip("StripeAPI captureCharge function", function () { describe.skip("StripeAPI createRefund function", function () { it("should return a result with object = refund", function (done) { - let apiKey = ""; - let cardObject = { + const apiKey = ""; + const cardObject = { number: "4242424242424242", name: "Test User", cvc: "345", exp_month: "02", exp_year: "2019" }; - let chargeObject = { + const chargeObject = { amount: 1999, currency: "USD", card: cardObject, @@ -82,7 +82,7 @@ describe.skip("StripeAPI createRefund function", function () { }; const chargeResult = StripeApi.methods.createCharge.call({ chargeObj: chargeObject, apiKey: apiKey }); - let refundDetails = { + const refundDetails = { charge: chargeResult.id, amount: 1999, reason: "requested_by_customer" @@ -99,15 +99,15 @@ describe.skip("StripeAPI createRefund function", function () { describe.skip("StripeAPI listRefund function", function () { it("should return a list of refunds", function (done) { - let apiKey = ""; - let cardObject = { + const apiKey = ""; + const cardObject = { number: "4242424242424242", name: "Test User", cvc: "345", exp_month: "02", exp_year: "2019" }; - let chargeObject = { + const chargeObject = { amount: 1999, currency: "USD", card: cardObject, @@ -115,7 +115,7 @@ describe.skip("StripeAPI listRefund function", function () { }; const chargeResult = StripeApi.methods.createCharge.call({ chargeObj: chargeObject, apiKey: apiKey }); - let refundDetails = { + const refundDetails = { charge: chargeResult.id, amount: 1999, reason: "requested_by_customer" diff --git a/imports/plugins/included/stripe/server/methods/stripeapi-methods-capture.app-test.js b/imports/plugins/included/stripe/server/methods/stripeapi-methods-capture.app-test.js index b8babba73a2..4ceb2a4202a 100644 --- a/imports/plugins/included/stripe/server/methods/stripeapi-methods-capture.app-test.js +++ b/imports/plugins/included/stripe/server/methods/stripeapi-methods-capture.app-test.js @@ -4,7 +4,7 @@ import { expect } from "meteor/practicalmeteor:chai"; import { sinon } from "meteor/practicalmeteor:sinon"; import { StripeApi } from "./stripeapi"; -let stripeCaptureResult = { +const stripeCaptureResult = { id: "ch_17hZ4wBXXkbZQs3xL5JhlSgS", object: "charge", amount: 1999, @@ -78,7 +78,7 @@ describe("stripe/payment/capture", function () { }); it("should call StripeApi.methods.captureCharge with the proper parameters and return saved = true", function (done) { - let paymentMethod = { + const paymentMethod = { processor: "Stripe", storedCard: "Visa 4242", method: "credit", @@ -125,7 +125,7 @@ describe("stripe/payment/capture", function () { }); it("should should return a match error if transactionId is not available", function (done) { - let paymentMethod = { + const paymentMethod = { processor: "Stripe", storedCard: "Visa 4242", method: "credit", diff --git a/imports/plugins/included/stripe/server/methods/stripeapi-methods-charge.app-test.js b/imports/plugins/included/stripe/server/methods/stripeapi-methods-charge.app-test.js index b1cec24c466..e154b33159c 100644 --- a/imports/plugins/included/stripe/server/methods/stripeapi-methods-charge.app-test.js +++ b/imports/plugins/included/stripe/server/methods/stripeapi-methods-charge.app-test.js @@ -4,7 +4,7 @@ import { sinon } from "meteor/practicalmeteor:sinon"; import { StripeApi } from "./stripeapi"; import { Stripe } from "../../lib/api"; -let stripeChargeResult = { +const stripeChargeResult = { id: "ch_17hA8DBXXkbZQs3xENUmN9bZ", object: "charge", amount: 2298, @@ -59,7 +59,7 @@ describe("Stripe.authorize", function () { sandbox.stub(StripeApi.methods.createCharge, "call", function () { return stripeChargeResult; }); - let cardData = { + const cardData = { cvv2: "345", expire_month: "4", expire_year: "2019", @@ -67,8 +67,8 @@ describe("Stripe.authorize", function () { number: "4242424242424242", type: "visa" }; - let total = "22.98"; - let currency = "USD"; + const total = "22.98"; + const currency = "USD"; let chargeResult = null; Stripe.authorize(cardData, {total: total, currency: currency}, function (error, result) { chargeResult = result; @@ -90,7 +90,7 @@ describe("Stripe.authorize", function () { }); it("should properly charge a card when using a currency besides USD", function () { - let form = { + const form = { cvv2: "345", expire_month: "4", expire_year: "2019", @@ -98,8 +98,8 @@ describe("Stripe.authorize", function () { number: "4242424242424242", type: "visa" }; - let total = "22.98"; - let currency = "EUR"; + const total = "22.98"; + const currency = "EUR"; sandbox.stub(StripeApi.methods.createCharge, "call", function () { return stripeChargeResult; @@ -140,7 +140,7 @@ describe("Stripe.authorize", function () { }); it("should return saved = false when card is declined", function () { - let form = { + const form = { cvv2: "345", expire_month: "4", expire_year: "2019", @@ -148,10 +148,10 @@ describe("Stripe.authorize", function () { number: "4000000000000002", type: "visa" }; - let total = "22.98"; - let currency = "EUR"; + const total = "22.98"; + const currency = "EUR"; - let stripeDeclineResult = + const stripeDeclineResult = { result: null, error: { @@ -216,7 +216,7 @@ describe("Stripe.authorize", function () { it("should return saved = false when an expired card is returned", function () { // Note that this test number makes the Stripe API return this error, it is // not looking at the actual expiration date. - let form = { + const form = { cvv2: "345", expire_month: "4", expire_year: "2019", @@ -224,10 +224,10 @@ describe("Stripe.authorize", function () { number: "4000000000000069", type: "visa" }; - let total = "22.98"; - let currency = "USD"; + const total = "22.98"; + const currency = "USD"; - let stripeExpiredCardResult = + const stripeExpiredCardResult = { result: null, error: { diff --git a/imports/plugins/included/stripe/server/methods/stripeapi-methods-refund.app-test.js b/imports/plugins/included/stripe/server/methods/stripeapi-methods-refund.app-test.js index 7be8a78b3bf..54a75562ab6 100644 --- a/imports/plugins/included/stripe/server/methods/stripeapi-methods-refund.app-test.js +++ b/imports/plugins/included/stripe/server/methods/stripeapi-methods-refund.app-test.js @@ -16,7 +16,7 @@ describe("stripe/refund/create", function () { }); it("should call StripeApi.methods.createRefund with the proper parameters and return saved = true", function (done) { - let paymentMethod = { + const paymentMethod = { processor: "Stripe", storedCard: "Visa 4242", method: "credit", @@ -29,7 +29,7 @@ describe("stripe/refund/create", function () { metadata: {} }; - let stripeRefundResult = { + const stripeRefundResult = { id: "re_17hZzSBXXkbZQs3xgmmEeOci", object: "refund", amount: 1999, diff --git a/imports/plugins/included/stripe/server/methods/stripeapi-methods-refundlist.app-test.js b/imports/plugins/included/stripe/server/methods/stripeapi-methods-refundlist.app-test.js index 75218ae356e..39728db4836 100644 --- a/imports/plugins/included/stripe/server/methods/stripeapi-methods-refundlist.app-test.js +++ b/imports/plugins/included/stripe/server/methods/stripeapi-methods-refundlist.app-test.js @@ -17,7 +17,7 @@ describe("stripe/refunds/list", function () { it("should call StripeApi.methods.listRefunds with the proper parameters and return a properly" + "formatted list of refunds", function (done) { - let paymentMethod = { + const paymentMethod = { processor: "Stripe", storedCard: "Visa 4242", method: "credit", @@ -32,7 +32,7 @@ describe("stripe/refunds/list", function () { metadata: {} }; - let stripeRefundListResult = { + const stripeRefundListResult = { object: "list", data: [ { diff --git a/imports/plugins/included/taxes-avalara/server/hooks/hooks.js b/imports/plugins/included/taxes-avalara/server/hooks/hooks.js index 00f9d04088c..50dac205abd 100644 --- a/imports/plugins/included/taxes-avalara/server/hooks/hooks.js +++ b/imports/plugins/included/taxes-avalara/server/hooks/hooks.js @@ -16,7 +16,7 @@ import Avalara from "avalara-taxrates"; // should we just use HTTP. // MethodHooks.after("taxes/calculate", function (options) { - let result = options.result || {}; + const result = options.result || {}; const cartId = options.arguments[0]; const cartToCalc = Cart.findOne(cartId); const shopId = cartToCalc.shopId; @@ -37,7 +37,7 @@ MethodHooks.after("taxes/calculate", function (options) { // maybe refactor to a core calculation let totalTax = 0; let taxRate = 0; - for (let items of cartToCalc.items) { + for (const items of cartToCalc.items) { // only processs taxable products if (items.variants.taxable === true) { const subTotal = items.variants.price * items.quantity; diff --git a/imports/plugins/included/taxes-taxcloud/server/hooks/hooks.js b/imports/plugins/included/taxes-taxcloud/server/hooks/hooks.js index 8417d901876..d56625a6283 100644 --- a/imports/plugins/included/taxes-taxcloud/server/hooks/hooks.js +++ b/imports/plugins/included/taxes-taxcloud/server/hooks/hooks.js @@ -11,7 +11,7 @@ import { Shops, Cart, Packages } from "/lib/collections"; // load order of plugins // MethodHooks.after("taxes/calculate", function (options) { - let result = options.result || {}; + const result = options.result || {}; let origin = {}; const cartId = options.arguments[0]; @@ -24,7 +24,7 @@ MethodHooks.after("taxes/calculate", function (options) { }); // check if package is configured - if (pkg && pkg.settings.taxcloud) { + if (shop && pkg && pkg.settings.taxcloud) { const apiKey = pkg.settings.taxcloud.apiKey; const apiLoginId = pkg.settings.taxcloud.apiLoginId; @@ -46,7 +46,7 @@ MethodHooks.after("taxes/calculate", function (options) { if (!apiKey || !apiLoginId) { Logger.warn("TaxCloud API Key is required."); } - if (typeof cartToCalc.shipping !== "undefined") { + if (typeof cartToCalc.shipping !== "undefined" && cartToCalc.items) { const shippingAddress = cartToCalc.shipping[0].address; if (shippingAddress) { @@ -62,7 +62,7 @@ MethodHooks.after("taxes/calculate", function (options) { // format cart items to TaxCloud structure let index = 0; - for (let items of cartToCalc.items) { + for (const items of cartToCalc.items) { // only processs taxable products if (items.variants.taxable === true) { const item = { @@ -100,7 +100,7 @@ MethodHooks.after("taxes/calculate", function (options) { // ResponseType 3 is a successful call. if (!error && response.data.ResponseType === 3) { let totalTax = 0; - for (let item of response.data.CartItemsResponse) { + for (const item of response.data.CartItemsResponse) { totalTax += item.TaxAmount; } // don't run this calculation if there isn't tax. diff --git a/imports/plugins/included/taxes-taxjar/server/hooks/hooks.js b/imports/plugins/included/taxes-taxjar/server/hooks/hooks.js index cfedc12df52..909761c5c41 100644 --- a/imports/plugins/included/taxes-taxjar/server/hooks/hooks.js +++ b/imports/plugins/included/taxes-taxjar/server/hooks/hooks.js @@ -3,7 +3,7 @@ import { Packages } from "/lib/collections"; // // Meteor.after to call after MethodHooks.after("taxes/calculate", function (options) { - let result = options.result || {}; + const result = options.result || {}; const pkg = Packages.findOne({ name: "taxes-taxjar", shopId: Reaction.getShopId() diff --git a/lib/api/account-validation.js b/lib/api/account-validation.js index 4b8bcc18aa5..337c8214c4b 100644 --- a/lib/api/account-validation.js +++ b/lib/api/account-validation.js @@ -66,7 +66,7 @@ const validationMethods = { check(options, Match.OptionalOrNull(Object)); const passwordOptions = options || {}; - let errors = []; + const errors = []; // Only check if a password has been entered at all. // This is usefull for the login forms diff --git a/lib/api/catalog.js b/lib/api/catalog.js index de183108d1a..ca150cdcd02 100644 --- a/lib/api/catalog.js +++ b/lib/api/catalog.js @@ -10,9 +10,9 @@ export default Catalog = { */ setProduct(currentProductId, currentVariantId) { let productId = currentProductId; - let variantId = currentVariantId; + const variantId = currentVariantId; if (!productId.match(/^[A-Za-z0-9]{17}$/)) { - let product = Products.findOne({ + const product = Products.findOne({ handle: productId.toLowerCase() }); if (product) { @@ -42,19 +42,19 @@ export default Catalog = { // if we have variants we have a price range. // this processing will default on the server if (variants.length > 0) { - let variantPrices = []; + const variantPrices = []; variants.forEach(variant => { - let range = this.getVariantPriceRange(variant._id); + const range = this.getVariantPriceRange(variant._id); if (typeof range === "string") { - let firstPrice = parseFloat(range.substr(0, range.indexOf(" "))); - let lastPrice = parseFloat(range.substr(range.lastIndexOf(" ") + 1)); + const firstPrice = parseFloat(range.substr(0, range.indexOf(" "))); + const lastPrice = parseFloat(range.substr(range.lastIndexOf(" ") + 1)); variantPrices.push(firstPrice, lastPrice); } else { variantPrices.push(range); } }); - let priceMin = _.min(variantPrices); - let priceMax = _.max(variantPrices); + const priceMin = _.min(variantPrices); + const priceMax = _.max(variantPrices); let priceRange = `${priceMin} - ${priceMax}`; // if we don't have a range if (priceMin === priceMax) { diff --git a/lib/api/helpers.js b/lib/api/helpers.js index 0b8b4a046bf..a8f55693c15 100644 --- a/lib/api/helpers.js +++ b/lib/api/helpers.js @@ -3,6 +3,10 @@ import { Meteor } from "meteor/meteor"; import { FlowRouter } from "meteor/kadira:flow-router-ssr"; import { Shops } from "/lib/collections"; +/* eslint no-unused-vars: 0 */ +// +// TODO review this slugify import in lib/api/helpers +// if (Meteor.isServer) { import { slugify } from "transliteration"; } diff --git a/lib/api/products.js b/lib/api/products.js index 4b3a9620525..562d17d71e0 100644 --- a/lib/api/products.js +++ b/lib/api/products.js @@ -32,7 +32,7 @@ ReactionProduct.setCurrentVariant = (variantId) => { if (!variantId) { return; } - let currentId = ReactionProduct.selectedVariantId(); + const currentId = ReactionProduct.selectedVariantId(); if (currentId === variantId) { return; } @@ -116,6 +116,7 @@ ReactionProduct.selectedVariant = function () { if (typeof id === "string") { return Products.findOne(id); } + return []; }; /** @@ -128,6 +129,7 @@ ReactionProduct.selectedProduct = function () { if (typeof id === "string") { return Products.findOne(id); } + return []; }; /** @@ -214,7 +216,7 @@ ReactionProduct.maybeDeleteProduct = maybeDeleteProduct = (product) => { }, (isConfirm) => { if (isConfirm) { Meteor.call("products/deleteProduct", productIds, function (error, result) { - let id = "product"; + const id = "product"; if (error || !result) { Alerts.toast(`There was an error deleting ${title}`, "error", { i18nKey: "productDetail.productDeleteError" @@ -282,7 +284,7 @@ ReactionProduct.getProductsByTag = function (tag) { let newRelatedTags; let relatedTag; let relatedTags; - let selector = {}; + const selector = {}; if (tag) { hashtags = []; @@ -300,7 +302,7 @@ ReactionProduct.getProductsByTag = function (tag) { $in: hashtags }; } - let cursor = Products.find(selector); + const cursor = Products.find(selector); return cursor; }; @@ -312,7 +314,11 @@ ReactionProduct.getProductsByTag = function (tag) { */ ReactionProduct.publishProduct = function (productOrArray) { const products = !_.isArray(productOrArray) ? [productOrArray] : productOrArray; - for (let product of products) { + /* eslint no-loop-func: 1 */ + // + // TODO review process for publishing arrays of product + // + for (const product of products) { Meteor.call("products/publishProduct", product._id, (error, result) => { if (error) { Alerts.add(error, "danger", { diff --git a/lib/api/router/metadata.js b/lib/api/router/metadata.js index 032c9df5ab3..e7f20e51c7b 100644 --- a/lib/api/router/metadata.js +++ b/lib/api/router/metadata.js @@ -13,9 +13,9 @@ export const MetaData = { const params = context.params; const product = ReactionProduct.selectedProduct(); const shop = Shops.findOne(getShopId()); - let meta = []; + const meta = []; let title = ""; - let keywords = []; + const keywords = []; // case helper const titleCase = (param) => { @@ -81,7 +81,7 @@ export const MetaData = { } if (product && product.metafields) { - for (let key of product.metafields) { + for (const key of product.metafields) { keywords.push(key.value); } } diff --git a/lib/collections/collections.js b/lib/collections/collections.js index 98a616e5501..7f9cef70acf 100644 --- a/lib/collections/collections.js +++ b/lib/collections/collections.js @@ -39,7 +39,7 @@ Assets.attachSchema(Schemas.Assets); */ export const Cart = new Mongo.Collection("Cart", { transform(cart) { - let newInstance = Object.create(cartTransform); + const newInstance = Object.create(cartTransform); return _.extend(newInstance, cart); } }); @@ -71,7 +71,7 @@ export const Orders = new Mongo.Collection("Orders", { order.itemCount = () => { let count = 0; if (order && Array.isArray(order.items)) { - for (let items of order.items) { + for (const items of order.items) { count += items.quantity; } } diff --git a/lib/collections/helpers.js b/lib/collections/helpers.js index 5a7b5469a01..a5db3a3073e 100644 --- a/lib/collections/helpers.js +++ b/lib/collections/helpers.js @@ -64,13 +64,13 @@ export const cartTransform = { cartTotal() { let subTotal = getSummary(this.items, ["quantity"], ["variants", "price"]); // add taxTotals - let taxTotal = parseFloat((subTotal * this.tax).toFixed(2)); + const taxTotal = parseFloat((subTotal * this.tax).toFixed(2)); if (typeof taxTotal === "number" && taxTotal > 0) { subTotal += taxTotal; } // shipping totals - let shippingTotal = parseFloat(getSummary(this.shipping, ["shipmentMethod", "rate"])); + const shippingTotal = parseFloat(getSummary(this.shipping, ["shipmentMethod", "rate"])); if (typeof shippingTotal === "number" && shippingTotal > 0) { subTotal += shippingTotal; } diff --git a/lib/collections/schemas/analytics.js b/lib/collections/schemas/analytics.js index 83eff9f78fa..29e4ade7641 100644 --- a/lib/collections/schemas/analytics.js +++ b/lib/collections/schemas/analytics.js @@ -5,26 +5,26 @@ import { PackageConfig } from "./registry"; import { shopIdAutoValue } from "./helpers"; export const AnalyticsEvents = new SimpleSchema({ - eventType: { + "eventType": { type: String }, - category: { + "category": { type: String, optional: true }, - action: { + "action": { type: String, optional: true }, - label: { + "label": { type: String, optional: true }, - value: { + "value": { type: String, optional: true }, - user: { + "user": { type: Object, optional: true }, @@ -43,20 +43,20 @@ export const AnalyticsEvents = new SimpleSchema({ return Roles.userIsInRole(Meteor.user(), "anonymous", getShopId()); } }, - shopId: { + "shopId": { type: String, regEx: SimpleSchema.RegEx.Id, autoValue: shopIdAutoValue, label: "AnalyticsEvents shopId" }, - createdAt: { + "createdAt": { type: Date, autoValue: function () { return new Date; } }, // Any additional data - data: { + "data": { type: Object, blackbox: true, optional: true diff --git a/package.json b/package.json index a9bb0ddfdd2..c8d7efd1da6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "reaction", "description": "Reaction is a modern reactive, real-time event driven ecommerce platform.", - "version": "0.15.0", + "version": "0.15.1", "main": "main.js", "directories": { "test": "tests" @@ -25,6 +25,7 @@ "autoprefixer": "^6.3.7", "autosize": "^3.0.17", "avalara-taxrates": "^1.0.1", + "bcrypt": "^0.8.7", "bootstrap": "^3.3.7", "braintree": "^1.41.0", "bunyan": "^1.8.1", @@ -40,9 +41,8 @@ "i18next-browser-languagedetector": "^1.0.0", "i18next-localstorage-cache": "^0.3.0", "i18next-sprintf-postprocessor": "^0.2.2", - "jquery": "^2.2.4", + "jquery": "^3.1.0", "jquery-i18next": "^1.0.1", - "jquery-ui": "1.10.5", "lodash": "^4.14.2", "meteor-node-stubs": "^0.2.3", "moment": "^2.14.1", @@ -54,12 +54,13 @@ "postcss-js": "^0.1.3", "react": "^15.3.0", "react-addons-pure-render-mixin": "^15.3.0", + "react-autosuggest": "^5.1.0", "react-color": "^2.2.1", "react-dom": "^15.3.0", "react-textarea-autosize": "^4.0.4", "sortablejs": "^1.4.2", "stripe": "^4.9.0", - "sweetalert2": "^3.3.8", + "sweetalert2": "^4.1.7", "swiper": "^3.3.1", "tether-drop": "^1.4.2", "tether-tooltip": "^1.2.0", @@ -68,8 +69,8 @@ }, "devDependencies": { "babel-eslint": "^6.1.2", - "eslint": "^2.13.1", - "eslint-plugin-react": "^5.2.2" + "eslint": "^3.3.1", + "eslint-plugin-react": "^6.1.2" }, "postcss": { "plugins": { diff --git a/private/data/i18n/en.json b/private/data/i18n/en.json index 45cf09ca914..dc70739d825 100644 --- a/private/data/i18n/en.json +++ b/private/data/i18n/en.json @@ -33,9 +33,9 @@ "catalogLabel": "Catalog", "catalogTitle": "Catalog", "catalogDescription": "Product Catalog", - "coreLabel": "Core", + "coreLabel": "Settings", "coreTitle": "Dashboard", - "coreDescription": "Reaction core shop configuration", + "coreDescription": "Reaction configuration", "examplePaymentProviderLabel": "Example Payment", "examplePaymentProviderDescription": "Example Payment Method", "i18NLabel": "i18n", @@ -236,6 +236,7 @@ }, "tags": { "addTag": "Add Tag", + "updateTag": "Update Tag", "addGroupTag": "Add Group Tag", "addSubTag": "Add Sub Tag", "removeTag": "Remove Tag", diff --git a/server/api/core/assignRoles.js b/server/api/core/assignRoles.js index c1724dc6ea9..bdbc76e47f7 100644 --- a/server/api/core/assignRoles.js +++ b/server/api/core/assignRoles.js @@ -50,7 +50,7 @@ export function assignOwnerRoles(shopId, pkgName, registry) { if (registry) { // for each registry item define and push roles - for (let registryItem of registry) { + for (const registryItem of registry) { // packages don't need to define specific permission routes., // the routeName will be used as default roleName for each route. // todo: check dependency on this. @@ -62,7 +62,7 @@ export function assignOwnerRoles(shopId, pkgName, registry) { // Get all defined permissions, add them to an array // define permissions if you need to check custom permission if (registryItem.permissions) { - for (let permission of registryItem.permissions) { + for (const permission of registryItem.permissions) { defaultRoles.push(permission.permission); } } @@ -81,7 +81,7 @@ export function assignOwnerRoles(shopId, pkgName, registry) { return; } // assign this package permission to each existing owner. - for (let account of shopOwners) { + for (const account of shopOwners) { owners.push(account._id); } // we don't use accounts/addUserPermissions here because we may not yet have permissions diff --git a/server/api/core/core.js b/server/api/core/core.js index 2aedc2ba008..42352890500 100644 --- a/server/api/core/core.js +++ b/server/api/core/core.js @@ -39,7 +39,7 @@ export default { Packages: {}, registerPackage(packageInfo) { - let registeredPackage = this.Packages[packageInfo.name] = + const registeredPackage = this.Packages[packageInfo.name] = packageInfo; return registeredPackage; }, @@ -87,14 +87,14 @@ export default { } // global roles check - let sellerShopPermissions = Roles.getGroupsForUser(userId, "admin"); + const sellerShopPermissions = Roles.getGroupsForUser(userId, "admin"); // we're looking for seller permissions. if (sellerShopPermissions) { // loop through shops roles and check permissions - for (let key in sellerShopPermissions) { + for (const key in sellerShopPermissions) { if (key) { - let shop = sellerShopPermissions[key]; + const shop = sellerShopPermissions[key]; if (Roles.userIsInRole(userId, permissions, shop)) { return true; } @@ -137,13 +137,13 @@ export default { let settingsUrl = Meteor.settings.MAIL_URL; if (user && password && host && port) { - let mailString = `smtp://${user}:${password}@${host}:${port}/`; + const mailString = `smtp://${user}:${password}@${host}:${port}/`; const mailUrl = processUrl = settingsUrl = mailString; process.env.MAIL_URL = mailUrl; return mailUrl; } else if (shopMail && shopMail.user && shopMail.password && shopMail.host && shopMail.port) { - let mailString = + const mailString = `smtp://${shopMail.user}:${shopMail.password}@${shopMail.host}:${shopMail.port}/`; const mailUrl = processUrl = settingsUrl = mailString; process.env.MAIL_URL = mailUrl; @@ -328,7 +328,7 @@ export default { // we don't need to do any further permission configuration // it is taken care of in the assignOwnerRoles const packages = Packages.find().fetch(); - for (let pkg of packages) { + for (const pkg of packages) { this.assignOwnerRoles(shopId, pkg.name, pkg.registry); } @@ -378,7 +378,7 @@ export default { Logger.warn("Skipped loading settings from reaction.json."); Logger.debug(error, "loadSettings reaction.json not loaded."); } - let layouts = []; + const layouts = []; // for each shop, we're loading packages in a unique registry _.each(this.Packages, (config, pkgName) => { return Shops.find().forEach((shop) => { @@ -421,7 +421,7 @@ export default { // don't already exist in Shops if (combinedSettings.layout) { // filter out layout Templates - for (let pkg of combinedSettings.layout) { + for (const pkg of combinedSettings.layout) { if (pkg.layout) { layouts.push(pkg); } diff --git a/server/api/core/import.js b/server/api/core/import.js index 5d1990ceeaf..2db5985fc44 100644 --- a/server/api/core/import.js +++ b/server/api/core/import.js @@ -71,11 +71,11 @@ Import.indication = function (field, collection, probability) { Import.identify = function (document) { check(document, Object); - let probabilities = {}; + const probabilities = {}; for (key of Object.keys(document)) { if (this._indications[key]) { - let collection = this._name(this._indications[key].collection); + const collection = this._name(this._indications[key].collection); probabilities[collection] = probabilities[collection] || 1.0 * this._indications[ key].probability; } @@ -89,7 +89,7 @@ Import.identify = function (document) { let max = 0.0; let name; for (key of Object.keys(probabilities)) { - let probability = total / probabilities[key]; + const probability = total / probabilities[key]; if (probability > max) { max = probability; name = key; @@ -113,16 +113,16 @@ Import.identify = function (document) { Import.commit = function (collection) { check(collection, Mongo.Collection); // Construct a collection identifier. - let name = this._name(collection); + const name = this._name(collection); // Only commit if the buffer isn't empty (otherwise it'll throw). if (this._count[name]) { this.buffer(collection).execute(function (error, result) { // Inserted document counts don't affect the modified document count, so we // throw everythin together. - let nImported = result.nModified + result.nInserted + result.nUpserted; - let nTouched = result.nMatched + result.nInserted + result.nUpserted; - let nRemoved = result.nRemoved; + const nImported = result.nModified + result.nInserted + result.nUpserted; + const nTouched = result.nMatched + result.nInserted + result.nUpserted; + const nRemoved = result.nRemoved; // Log some information about the import. if (nTouched) { let message = ""; @@ -141,11 +141,11 @@ Import.commit = function (collection) { // Log any errors returned. let message = ""; message += "Error while importing to " + name; - let writeErrors = result.getWriteErrors(); + const writeErrors = result.getWriteErrors(); for (let i = 0; i < writeErrors.length; i++) { Logger.warn(message + ": " + writeErrors[i].errmsg); } - let writeConcernError = result.getWriteConcernError(); + const writeConcernError = result.getWriteConcernError(); if (writeConcernError) { Logger.warn(message + ": " + writeConcernError.errmsg); } @@ -163,7 +163,7 @@ Import.commit = function (collection) { */ Import.flush = function (collection) { if (!collection) { - for (let name of Object.keys(this._buffers)) { + for (const name of Object.keys(this._buffers)) { this.commit(Collections[name]); } return; @@ -211,7 +211,7 @@ Import.buffer = function (collection) { } // Construct a buffer identifier. - let name = this._name(collection); + const name = this._name(collection); // Construct a new buffer if necessary. if (this._buffers[name]) { @@ -338,7 +338,7 @@ function doRightJoinNoIntersection(leftSet, rightSet) { } else { rightJoin = {}; } - let findRightOnlyProperties = function () { + const findRightOnlyProperties = () => { return Object.keys(rightSet).filter(function (key) { if (typeof(rightSet[key]) === "object" && !Array.isArray(rightSet[key])) { @@ -350,7 +350,7 @@ function doRightJoinNoIntersection(leftSet, rightSet) { }); }; - for (let key of findRightOnlyProperties()) { + for (const key of findRightOnlyProperties()) { if (typeof(rightSet[key]) === "object") { // subobject or array if (leftSet.hasOwnProperty(key) && (typeof(leftSet[key]) !== "object" || @@ -361,12 +361,12 @@ function doRightJoinNoIntersection(leftSet, rightSet) { "congruent! Offending key: " + key ); } - let rightSubJoin = doRightJoinNoIntersection( + const rightSubJoin = doRightJoinNoIntersection( leftSet.hasOwnProperty(key) ? leftSet[key] : {}, rightSet[key] ); - let obj = {}; + const obj = {}; if (rightSubJoin === null) { obj[key] = null; } else if (Object.keys(rightSubJoin).length !== 0 || @@ -380,7 +380,7 @@ function doRightJoinNoIntersection(leftSet, rightSet) { if (Array.isArray(rightSet)) { rightJoin.push(rightSet[key]); } else { - let obj = {}; + const obj = {}; obj[key] = rightSet[key]; rightJoin = Object.assign(rightJoin, obj); } @@ -401,7 +401,7 @@ Import.object = function (collection, key, object) { check(key, Object); check(object, Object); - let selector = object; + const selector = object; // enforce strings instead of Mongo.ObjectId if (!collection.findOne(key) && !object._id) key._id = Random.id(); @@ -409,7 +409,7 @@ Import.object = function (collection, key, object) { const importObject = Hooks.Events.run(`onImport${this._name(collection)}`, object); // Clone object for cleaning - let cleanedObject = Object.assign({}, importObject); + const cleanedObject = Object.assign({}, importObject); // Cleaning the object adds default values from schema, if value doesn't exist collection.simpleSchema(importObject).clean(cleanedObject); @@ -418,10 +418,10 @@ Import.object = function (collection, key, object) { // Disjoint importObject and cleanedObject again // to prevent `Cannot update '' and '' at the same time` errors - let defaultValuesObject = doRightJoinNoIntersection(importObject, cleanedObject); + const defaultValuesObject = doRightJoinNoIntersection(importObject, cleanedObject); // Upsert the object. - let find = this.buffer(collection).find(key); + const find = this.buffer(collection).find(key); if (Object.keys(defaultValuesObject).length === 0) { find.upsert().update({ $set: importObject @@ -452,10 +452,10 @@ Import.process = function (json, keys, callback) { check(keys, Array); check(callback, Function); - let array = EJSON.parse(json); + const array = EJSON.parse(json); for (let i = 0; i < array.length; i++) { - let key = {}; + const key = {}; for (let j = 0; j < keys.length; j++) { key[keys[j]] = array[i][keys[j]]; } diff --git a/server/api/core/loadSettings.js b/server/api/core/loadSettings.js index edd314e8576..bf0fa95c61b 100644 --- a/server/api/core/loadSettings.js +++ b/server/api/core/loadSettings.js @@ -24,7 +24,7 @@ export function loadSettings(json) { let service; let services; let settings; - let validatedJson = EJSON.parse(json); + const validatedJson = EJSON.parse(json); // validate json and error out if not an array if (!_.isArray(validatedJson[0])) { @@ -34,8 +34,8 @@ export function loadSettings(json) { } // loop settings and upsert packages. - for (let pkg of validatedJson) { - for (let item of pkg) { + for (const pkg of validatedJson) { + for (const item of pkg) { exists = Packages.findOne({ name: item.name }); diff --git a/server/api/core/setDomain.js b/server/api/core/setDomain.js index 986827463be..95bafee1344 100644 --- a/server/api/core/setDomain.js +++ b/server/api/core/setDomain.js @@ -8,8 +8,8 @@ import { Logger } from "/server/api"; * @return {String} domain name stripped from requestUrl */ export function getRegistryDomain(requestUrl) { - let url = requestUrl || process.env.ROOT_URL; - let domain = url.match(/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i)[1]; + const url = requestUrl || process.env.ROOT_URL; + const domain = url.match(/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i)[1]; return domain; } @@ -28,7 +28,7 @@ export function setDomain() { Logger.error("Failed to determine default shop.", _error); } // if the server domain changes, update shop - let domain = getRegistryDomain(); + const domain = getRegistryDomain(); if (currentDomain && currentDomain !== domain) { Logger.info("Updating domain to " + domain); Shops.update({ diff --git a/server/api/core/ui.js b/server/api/core/ui.js index 8ebd89b29ab..4d43ac5cd7c 100644 --- a/server/api/core/ui.js +++ b/server/api/core/ui.js @@ -30,7 +30,7 @@ function themeToCSS(theme) { check(theme, Object); let output = ""; - for (let component of theme.components) { + for (const component of theme.components) { output += component.styles; } @@ -48,7 +48,7 @@ function updateStyles(data) { "components.name": data.component.name }, { $set: { - [`components.$.styles`]: result.css + ["components.$.styles"]: result.css } }); } diff --git a/server/api/geocoder.js b/server/api/geocoder.js index 83cb1693c5d..499817c257c 100644 --- a/server/api/geocoder.js +++ b/server/api/geocoder.js @@ -16,13 +16,16 @@ import { Meteor } from "meteor/meteor"; if (typeof Meteor.wrapAsync === "undefined") { Meteor.wrapAsync = Meteor._wrapAsync; } - +/* eslint func-style: 1 */ +// +// TODO review GeoCoder export construction +// // init geocoder export const GeoCoder = function geoCoderConstructor(options) { let extra; - let self = this; + const self = this; // fetch shop settings for api auth credentials - let shopSettings = Packages.findOne({ + const shopSettings = Packages.findOne({ shopId: Reaction.getShopId(), name: "core" }, { @@ -48,7 +51,7 @@ export const GeoCoder = function geoCoderConstructor(options) { }; function gc(address, options, callback) { - let g = require("node-geocoder")(options.geocoderProvider, options.httpAdapter, + const g = require("node-geocoder")(options.geocoderProvider, options.httpAdapter, options.extra); g.geocode(address, callback); } @@ -68,7 +71,7 @@ GeoCoder.prototype.geocode = function geoCoderGeocode(address, callback) { }; function rv(lat, lng, options, callback) { - let g = require("node-geocoder")(options.geocoderProvider, options.httpAdapter, + const g = require("node-geocoder")(options.geocoderProvider, options.httpAdapter, options.extra); g.reverse({ lat: lat, diff --git a/server/api/method-hooks.js b/server/api/method-hooks.js index 058923faab0..e7f56454814 100644 --- a/server/api/method-hooks.js +++ b/server/api/method-hooks.js @@ -73,7 +73,7 @@ MethodHooks._initializeHook = function (mapping, methodName, hookFunction) { mapping[methodName].push(hookFunction); // Initialize a wrapper for the given method name. Idempotent, it will not erase existing handlers. - let method = MethodHooks._handlers[methodName]; + const method = MethodHooks._handlers[methodName]; // If no method is found, or a wrapper already exists, return if (!method || MethodHooks._wrappers[methodName]) { return; @@ -84,11 +84,12 @@ MethodHooks._initializeHook = function (mapping, methodName, hookFunction) { MethodHooks._wrappers[methodName] = function () { // Get arguments you can mutate - let args = _.toArray(arguments); + const args = _.toArray(arguments); let beforeResult; // Call the before hooks - let beforeHooks = MethodHooks._beforeHooks[methodName]; - _.each(beforeHooks, function (beforeHook, hooksProcessed) { + + const beforeHooks = MethodHooks._beforeHooks[methodName]; + _.each(beforeHooks, (beforeHook, hooksProcessed) => { beforeResult = beforeHook.call(this, { result: undefined, error: undefined, @@ -116,8 +117,8 @@ MethodHooks._initializeHook = function (mapping, methodName, hookFunction) { } // Call after hooks, providing the result and the original arguments - let afterHooks = MethodHooks._afterHooks[methodName]; - _.each(afterHooks, function (afterHook, hooksProcessed) { + const afterHooks = MethodHooks._afterHooks[methodName]; + _.each(afterHooks, (afterHook, hooksProcessed) => { let hookResult = afterHook.call(this, { result: methodResult, error: methodError, diff --git a/server/imports/fixtures/products.js b/server/imports/fixtures/products.js index 538d676da87..622c3bc4f91 100755 --- a/server/imports/fixtures/products.js +++ b/server/imports/fixtures/products.js @@ -98,7 +98,7 @@ export function getProducts(limit = 2) { const products = []; const existingProducts = Products.find({}, {limit: limit}).fetch(); for (let i = 0; i < limit; i = i + 1) { - let product = existingProducts[i] || Factory.create("product"); + const product = existingProducts[i] || Factory.create("product"); products.push(product); } return products; @@ -136,7 +136,7 @@ export default function () { max: 12.99 }; - let product = { + const product = { title: faker.commerce.productName(), pageTitle: faker.lorem.sentence(), description: faker.lorem.paragraph(), diff --git a/server/imports/fixtures/users.js b/server/imports/fixtures/users.js index 35861cb82ae..b4011b17214 100755 --- a/server/imports/fixtures/users.js +++ b/server/imports/fixtures/users.js @@ -12,7 +12,7 @@ export function getUsers(limit = 2) { const users = []; const existingUsers = Meteor.users.find({}, {limit: limit}).fetch(); for (let i = 0; i < limit; i = i + 1) { - let user = existingUsers[i] || Factory.create("user"); + const user = existingUsers[i] || Factory.create("user"); users.push(user); } return users; @@ -33,7 +33,7 @@ const user = { }, emails: function () { - let email = faker.internet.email(); + const email = faker.internet.email(); return [{ address: email, verified: true diff --git a/server/methods/accounts/accounts-validation.app-test.js b/server/methods/accounts/accounts-validation.app-test.js index 7ef1dc12694..b99fa049525 100644 --- a/server/methods/accounts/accounts-validation.app-test.js +++ b/server/methods/accounts/accounts-validation.app-test.js @@ -71,7 +71,7 @@ describe("Account Registration Validation ", function () { const password = "abc12"; Meteor.call("accounts/validation/password", password, undefined, function (error, result) { expect(result).to.be.an("array"); - let errMessage = result[0]; + const errMessage = result[0]; expect(errMessage).to.be.an("object"); expect(errMessage.reason).to.contain("at least 6 characters"); return done(); diff --git a/server/methods/accounts/accounts.app-test.js b/server/methods/accounts/accounts.app-test.js index c0dbc2f132a..8e69f9acc30 100644 --- a/server/methods/accounts/accounts.app-test.js +++ b/server/methods/accounts/accounts.app-test.js @@ -19,7 +19,7 @@ before(function () { describe("Account Meteor method ", function () { const shopId = getShop()._id; const fakeUser = Factory.create("account"); - let originals = {}; + const originals = {}; let sandbox; before(function () { @@ -105,7 +105,7 @@ describe("Account Meteor method ", function () { }); it("should throw error if wrong arguments were passed", function (done) { - let accountSpy = sandbox.spy(Accounts, "update"); + const accountSpy = sandbox.spy(Accounts, "update"); expect(function () { return Meteor.call("accounts/addressBookAdd", 123456); @@ -145,8 +145,8 @@ describe("Account Meteor method ", function () { return fakeUser._id; }); const account2 = Factory.create("account"); - let updateAccountSpy = sandbox.spy(Accounts, "update"); - let upsertAccountSpy = sandbox.spy(Accounts, "upsert"); + const updateAccountSpy = sandbox.spy(Accounts, "update"); + const upsertAccountSpy = sandbox.spy(Accounts, "upsert"); expect(function () { return Meteor.call("accounts/addressBookAdd", getAddress(), account2._id); @@ -160,7 +160,7 @@ describe("Account Meteor method ", function () { it("should disabled isShipping/BillingDefault properties inside sibling" + " address if we enable their while adding", function (done) { - let account = Factory.create("account"); + const account = Factory.create("account"); sandbox.stub(Meteor, "userId", function () { return account.userId; }); @@ -218,7 +218,7 @@ describe("Account Meteor method ", function () { }); it("should allow user to edit addresses", function (done) { - let account = Factory.create("account"); + const account = Factory.create("account"); sandbox.stub(Meteor, "userId", function () { return account.userId; }); @@ -230,7 +230,7 @@ describe("Account Meteor method ", function () { }); spyOnMethod("setShipmentAddress", account.userId); spyOnMethod("setPaymentAddress", account.userId); - let updateAccountSpy = sandbox.spy(Accounts, "update"); + const updateAccountSpy = sandbox.spy(Accounts, "update"); Meteor.call("cart/createCart", account.userId, sessionId); @@ -286,7 +286,7 @@ describe("Account Meteor method ", function () { }); it("should throw error if wrong arguments were passed", function () { - let updateAccountSpy = sandbox.spy(Accounts, "update"); + const updateAccountSpy = sandbox.spy(Accounts, "update"); expect(() => Meteor.call("accounts/addressBookUpdate", 123456)).to.throw; expect(() => Meteor.call("accounts/addressBookUpdate", {})).to.throw; expect(() => Meteor.call("accounts/addressBookUpdate", null)).to.throw; @@ -304,16 +304,16 @@ describe("Account Meteor method ", function () { }); it("should not let non-Admin to edit address of another user", function () { - let account = Factory.create("account"); + const account = Factory.create("account"); const account2 = Factory.create("account"); sandbox.stub(Meteor, "userId", () => account.userId); - let accountUpdateSpy = sandbox.spy(Accounts, "update"); + const accountUpdateSpy = sandbox.spy(Accounts, "update"); expect(() => Meteor.call("accounts/addressBookUpdate", getAddress(), account2._id)).to.throw; expect(accountUpdateSpy).to.not.have.been.called; }); it("enabling isShipping/BillingDefault properties should add this address to cart", function () { - let account = Factory.create("account"); + const account = Factory.create("account"); spyOnMethod("setShipmentAddress", account.userId); spyOnMethod("setPaymentAddress", account.userId); sandbox.stub(Meteor, "userId", function () { @@ -385,7 +385,7 @@ describe("Account Meteor method ", function () { ); it("should update cart default addresses via `type` argument", function () { - let account = Factory.create("account"); + const account = Factory.create("account"); const userId = account.userId; spyOnMethod("setShipmentAddress", account.userId); spyOnMethod("setPaymentAddress", account.userId); @@ -409,7 +409,7 @@ describe("Account Meteor method ", function () { Meteor.call("accounts/addressBookUpdate", address, null, "isBillingDefault"); Meteor.call("accounts/addressBookUpdate", address, null, "isShippingDefault"); - let cart = Cart.findOne({userId: userId}); + const cart = Cart.findOne({userId: userId}); expect(cart.billing[0].address._id).to.equal(address._id); expect(cart.shipping[0].address._id).to.equal(address._id); }); @@ -437,7 +437,7 @@ describe("Account Meteor method ", function () { }); it("should throw error if wrong arguments were passed", function () { - let updateAccountSpy = sandbox.spy(Accounts, "update"); + const updateAccountSpy = sandbox.spy(Accounts, "update"); expect(() => Meteor.call("accounts/addressBookRemove", 123456)).to.throw; expect(() => Meteor.call("accounts/addressBookRemove", {})).to.throw; expect(() => Meteor.call("accounts/addressBookRemove", null)).to.throw; @@ -461,7 +461,7 @@ describe("Account Meteor method ", function () { sandbox.stub(Meteor, "userId", function () { return account.userId; }); - let accountUpdateSpy = sandbox.spy(Accounts, "update"); + const accountUpdateSpy = sandbox.spy(Accounts, "update"); expect(() => Meteor.call("accounts/addressBookRemove", address2._id, account2.userId)).to.throw; expect(accountUpdateSpy).to.not.have.been.called; @@ -471,7 +471,7 @@ describe("Account Meteor method ", function () { const account = Factory.create("account"); const address = account.profile.addressBook[0]; sandbox.stub(Meteor, "userId", () => account.userId); - let cartUnsetSpy = sandbox.spy(Meteor.server.method_handlers, "cart/unsetAddresses"); + const cartUnsetSpy = sandbox.spy(Meteor.server.method_handlers, "cart/unsetAddresses"); Meteor.call("accounts/addressBookRemove", address._id); expect(cartUnsetSpy).to.have.been.called; @@ -489,7 +489,7 @@ describe("Account Meteor method ", function () { describe("accounts/inviteShopMember", function () { it("should not let non-Owners invite a user to the shop", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let createUserSpy = sandbox.spy(MeteorAccount, "createUser"); + const createUserSpy = sandbox.spy(MeteorAccount, "createUser"); // create user expect(() => Meteor.call("accounts/inviteShopMember", shopId, fakeUser.emails[0].address, diff --git a/server/methods/catalog.app-test.js b/server/methods/catalog.app-test.js index 42a6e41a556..3193aba48cf 100644 --- a/server/methods/catalog.app-test.js +++ b/server/methods/catalog.app-test.js @@ -62,7 +62,7 @@ describe("core product methods", function () { describe("products/cloneVariant", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Roles, "userIsInRole", () => false); - let insertProductSpy = sandbox.spy(Products, "insert"); + const insertProductSpy = sandbox.spy(Products, "insert"); expect(() => Meteor.call("products/cloneVariant", "fakeId", "fakeVarId")).to.throw(Meteor.Error, /Access Denied/); expect(insertProductSpy).to.not.have.been.called; @@ -103,7 +103,7 @@ describe("core product methods", function () { describe("products/createVariant", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); + const updateProductSpy = sandbox.spy(Products, "update"); expect(() => Meteor.call("products/createVariant", "fakeId")).to.throw(Meteor.Error, /Access Denied/); expect(updateProductSpy).to.not.have.been.called; }); @@ -161,7 +161,7 @@ describe("core product methods", function () { describe("products/updateVariant", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.stub(Products, "update"); + const updateProductSpy = sandbox.stub(Products, "update"); expect(() => Meteor.call("products/updateVariant", { _id: "fakeId" })).to.throw(Meteor.Error, /Access Denied/); expect(updateProductSpy).to.not.have.been.called; }); @@ -184,7 +184,7 @@ describe("core product methods", function () { sandbox.stub(Reaction, "hasPermission", () => true); let updatedVariant; const product = addProduct(); - let variant = Products.find({ ancestors: [product._id] }).fetch()[0]; + const variant = Products.find({ ancestors: [product._id] }).fetch()[0]; Meteor.call("products/updateVariant", { _id: variant._id, title: "Updated Title", @@ -200,7 +200,7 @@ describe("core product methods", function () { describe("products/deleteVariant", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let removeProductSpy = sandbox.spy(Products, "remove"); + const removeProductSpy = sandbox.spy(Products, "remove"); expect(() => Meteor.call("products/deleteVariant", "fakeId")).to.throw(Meteor.Error, /Access Denied/); expect(removeProductSpy).to.not.have.been.called; }); @@ -219,7 +219,7 @@ describe("core product methods", function () { sandbox.stub(Reaction, "hasPermission", () => true); const product = addProduct(); const variant = Products.find({ ancestors: [product._id] }).fetch()[0]; - let variants = Products.find({ ancestors: { + const variants = Products.find({ ancestors: { $in: [variant._id] }}).fetch(); expect(variants.length).to.equal(2); @@ -240,7 +240,7 @@ describe("core product methods", function () { sandbox.stub(Meteor.server.method_handlers, "inventory/remove", function () { check(arguments, [Match.Any]); }); - let insertProductSpy = sandbox.spy(Products, "insert"); + const insertProductSpy = sandbox.spy(Products, "insert"); expect(() => Meteor.call("products/cloneProduct", {})).to.throw(Meteor.Error, /Access Denied/); expect(insertProductSpy).to.not.have.been.called; }); @@ -276,7 +276,7 @@ describe("core product methods", function () { check(arguments, [Match.Any]); }); const product = addProduct(); - let variants = Products.find({ ancestors: { $in: [product._id] } }).fetch(); + const variants = Products.find({ ancestors: { $in: [product._id] } }).fetch(); expect(variants.length).to.equal(3); Meteor.call("products/cloneProduct", product); const clone = Products.find({ @@ -285,7 +285,7 @@ describe("core product methods", function () { }, type: "simple" }).fetch()[0]; - let cloneVariants = Products.find({ + const cloneVariants = Products.find({ ancestors: { $in: [clone._id] } }).fetch(); expect(cloneVariants.length).to.equal(3); @@ -348,14 +348,14 @@ describe("core product methods", function () { describe("createProduct", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let insertProductSpy = sandbox.spy(Products, "insert"); + const insertProductSpy = sandbox.spy(Products, "insert"); expect(() => Meteor.call("products/createProduct")).to.throw(Meteor.Error, /Access Denied/); expect(insertProductSpy).to.not.have.been.called; }); it("should create new product", function () { sandbox.stub(Reaction, "hasPermission", () => true); - let insertProductSpy = sandbox.stub(Products, "insert", () => 1); + const insertProductSpy = sandbox.stub(Products, "insert", () => 1); expect(Meteor.call("products/createProduct")).to.equal(1); expect(insertProductSpy).to.have.been.called; }); @@ -377,7 +377,7 @@ describe("core product methods", function () { describe("deleteProduct", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let removeProductSpy = sandbox.spy(Products, "remove"); + const removeProductSpy = sandbox.spy(Products, "remove"); expect(() => Meteor.call("products/deleteProduct", "fakeId")).to.throw(Meteor.Error, /Access Denied/); expect(removeProductSpy).to.not.have.been.called; }); @@ -403,7 +403,7 @@ describe("core product methods", function () { describe("updateProductField", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); + const updateProductSpy = sandbox.spy(Products, "update"); expect(() => Meteor.call("products/updateProductField", "fakeId", "title", "Updated Title")).to.throw(Meteor.Error, /Access Denied/); expect(updateProductSpy).to.not.have.been.called; @@ -434,8 +434,8 @@ describe("core product methods", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); - let insertTagsSpy = sandbox.spy(Tags, "insert"); + const updateProductSpy = sandbox.spy(Products, "update"); + const insertTagsSpy = sandbox.spy(Tags, "insert"); expect(() => Meteor.call("products/updateProductTags", "fakeId", "productTag", null)).to.throw(Meteor.Error, /Access Denied/); expect(updateProductSpy).to.not.have.been.called; expect(insertTagsSpy).to.not.have.been.called; @@ -444,7 +444,7 @@ describe("core product methods", function () { it("should add new tag when passed tag name and null ID by admin", function () { sandbox.stub(Reaction, "hasPermission", () => true); let product = addProduct(); - let tagName = "Product Tag"; + const tagName = "Product Tag"; expect(Tags.findOne({ name: tagName})).to.be.undefined; Meteor.call("products/updateProductTags", product._id, tagName, null); const tag = Tags.findOne({ name: tagName }); @@ -456,7 +456,7 @@ describe("core product methods", function () { it("should add existing tag when passed existing tag and tag._id by admin", function () { sandbox.stub(Reaction, "hasPermission", () => true); let product = addProduct(); - let tag = Factory.create("tag"); + const tag = Factory.create("tag"); expect(Tags.find().count()).to.equal(1); expect(product.hashtags).to.not.contain(tag._id); Meteor.call("products/updateProductTags", product._id, tag.name, tag._id); @@ -473,8 +473,8 @@ describe("core product methods", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); - let removeTagsSpy = sandbox.spy(Tags, "remove"); + const updateProductSpy = sandbox.spy(Products, "update"); + const removeTagsSpy = sandbox.spy(Tags, "remove"); expect(() => Meteor.call("products/removeProductTag", "fakeId", "tagId")).to.throw(Meteor.Error, /Access Denied/); expect(updateProductSpy).to.not.have.been.called; @@ -484,7 +484,7 @@ describe("core product methods", function () { it("should remove product tag by admin", function () { sandbox.stub(Reaction, "hasPermission", () => true); let product = addProduct(); - let tag = Factory.create("tag"); + const tag = Factory.create("tag"); Meteor.call("products/updateProductTags", product._id, tag.name, tag._id); product = Products.findOne(product._id); expect(product.hashtags).to.contain(tag._id); @@ -503,7 +503,7 @@ describe("core product methods", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let productUpdateSpy = sandbox.spy(Products, "update"); + const productUpdateSpy = sandbox.spy(Products, "update"); expect(() => Meteor.call("products/setHandle", "fakeId")) .to.throw(Meteor.Error, /Access Denied/); expect(productUpdateSpy).to.not.have.been.called; @@ -545,7 +545,7 @@ describe("core product methods", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); + const updateProductSpy = sandbox.spy(Products, "update"); expect(function () { return Meteor.call("products/setHandleTag", "fakeId", "tagId"); }).to.throw(Meteor.Error, /Access Denied/); @@ -555,7 +555,7 @@ describe("core product methods", function () { it("should set handle tag for product by admin", function () { sandbox.stub(Reaction, "hasPermission", () => true); let product = addProduct(); - let tag = Factory.create("tag"); + const tag = Factory.create("tag"); Meteor.call("products/setHandleTag", product._id, tag._id); product = Products.findOne(product._id); expect(product.handle).to.equal(tag.slug); @@ -569,7 +569,7 @@ describe("core product methods", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); + const updateProductSpy = sandbox.spy(Products, "update"); expect(() => Meteor.call("products/updateProductPosition", "fakeId", {}, "tag")).to.throw(Meteor.Error, /Access Denied/); expect(updateProductSpy).to.not.have.been.called; @@ -577,7 +577,7 @@ describe("core product methods", function () { it("should update product position by admin", function (done) { sandbox.stub(Reaction, "hasPermission", () => true); - let product = addProduct(); + const product = addProduct(); const tag = Factory.create("tag"); const position = { position: 0, @@ -596,7 +596,7 @@ describe("core product methods", function () { describe("updateMetaFields position", () => { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); + const updateProductSpy = sandbox.spy(Products, "update"); expect(() => Meteor.call("products/updateVariantsPosition", ["fakeId"])).to.throw(Meteor.Error, /Access Denied/); expect(updateProductSpy).to.not.have.been.called; }); @@ -627,7 +627,7 @@ describe("core product methods", function () { describe("updateMetaFields", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); + const updateProductSpy = sandbox.spy(Products, "update"); expect(() => Meteor.call("products/updateMetaFields", "fakeId", { key: "Material", value: "Spandex" @@ -653,7 +653,7 @@ describe("core product methods", function () { describe("publishProduct", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Reaction, "hasPermission", () => false); - let updateProductSpy = sandbox.spy(Products, "update"); + const updateProductSpy = sandbox.spy(Products, "update"); expect(() => Meteor.call("products/publishProduct", "fakeId")).to.throw(Meteor.Error, /Access Denied/); expect(updateProductSpy).to.not.have.been.called; }); @@ -661,7 +661,7 @@ describe("core product methods", function () { it("should let admin publish product", function () { sandbox.stub(Reaction, "hasPermission", () => true); let product = addProduct(); - let isVisible = product.isVisible; + const isVisible = product.isVisible; expect(() => Meteor.call("products/publishProduct", product._id)).to.not.throw(Meteor.Error, /Access Denied/); product = Products.findOne(product._id); expect(product.isVisible).to.equal(!isVisible); @@ -670,7 +670,7 @@ describe("core product methods", function () { it("should let admin toggle product visibility", function () { sandbox.stub(Reaction, "hasPermission", () => true); let product = addProduct(); - let isVisible = product.isVisible; + const isVisible = product.isVisible; expect(() => Meteor.call("products/publishProduct", product._id)).to.not.throw(Meteor.Error, /Access Denied/); product = Products.findOne(product._id); expect(product.isVisible).to.equal(!isVisible); @@ -682,7 +682,7 @@ describe("core product methods", function () { it("should not publish product when missing title", function () { sandbox.stub(Reaction, "hasPermission", () => true); let product = addProduct(); - let isVisible = product.isVisible; + const isVisible = product.isVisible; Products.update(product._id, { $set: { title: "" @@ -700,9 +700,9 @@ describe("core product methods", function () { sandbox.stub(Reaction, "hasPermission", () => true); let product = addProduct(); const isVisible = product.isVisible; - let variant = Products.findOne({ancestors: [product._id]}); + const variant = Products.findOne({ancestors: [product._id]}); expect(variant.ancestors[0]).to.equal(product._id); - let options = Products.find({ + const options = Products.find({ ancestors: [product._id, variant._id] }).fetch(); expect(options.length).to.equal(2); @@ -725,7 +725,7 @@ describe("core product methods", function () { it("should not publish product when missing variant", function () { let product = addProduct(); - let isVisible = product.isVisible; + const isVisible = product.isVisible; sandbox.stub(Roles, "userIsInRole", () => true); Products.remove({ancestors: { $in: [product._id] }}); expect(() => Meteor.call("products/publishProduct", product._id)).to.throw(Meteor.Error, /Forbidden/); diff --git a/server/methods/catalog.js b/server/methods/catalog.js index 070ddfa7cd0..152fd13335b 100644 --- a/server/methods/catalog.js +++ b/server/methods/catalog.js @@ -37,7 +37,7 @@ const toDenormalize = [ function createTitle(newTitle, productId) { // exception product._id needed for cases then double triggering happens let title = newTitle || ""; - let titleCount = Products.find({ + const titleCount = Products.find({ title: title, _id: { $nin: [productId] @@ -48,7 +48,7 @@ function createTitle(newTitle, productId) { // product handle prefix let titleString = title; // copySuffix "-copy-number" suffix of product - let copySuffix = titleString.match(/-copy-\d+$/) || titleString.match(/-copy$/); + const copySuffix = titleString.match(/-copy-\d+$/) || titleString.match(/-copy$/); // if product is a duplicate, we should take the copy number, and cut // the handle if (copySuffix) { @@ -92,7 +92,7 @@ function createTitle(newTitle, productId) { function createHandle(productHandle, productId) { let handle = productHandle || ""; // exception product._id needed for cases then double triggering happens - let handleCount = Products.find({ + const handleCount = Products.find({ handle: handle, _id: { $nin: [productId] @@ -103,7 +103,7 @@ function createHandle(productHandle, productId) { // product handle prefix let handleString = handle; // copySuffix "-copy-number" suffix of product - let copySuffix = handleString.match(/-copy-\d+$/) || handleString.match(/-copy$/); + const copySuffix = handleString.match(/-copy-\d+$/) || handleString.match(/-copy$/); // if product is a duplicate, we should take the copy number, and cut // the handle @@ -151,7 +151,7 @@ function copyMedia(newId, variantOldId, variantNewId) { Media.find({ "metadata.variantId": variantOldId }).forEach(function (fileObj) { - let newFile = fileObj.copy(); + const newFile = fileObj.copy(); return newFile.update({ $set: { "metadata.productId": newId, @@ -188,7 +188,7 @@ function denormalize(id, field) { } else if (doc.type === "variant" && doc.ancestors.length === 1) { variants = Catalog.getVariants(id); } - let update = {}; + const update = {}; switch (field) { case "inventoryPolicy": @@ -230,7 +230,7 @@ function denormalize(id, field) { function isSoldOut(variants) { return variants.every(variant => { if (variant.inventoryManagement && variant.inventoryPolicy) { - return Catalog.getVariantQuantity(variant) === 0; + return Catalog.getVariantQuantity(variant) <= 0; } return false; }); @@ -344,7 +344,7 @@ Meteor.methods({ return sortedVariants.map(variant => { const oldId = variant._id; let type = "child"; - let clone = {}; + const clone = {}; if (variantId === variant._id) { type = "parent"; Object.assign(clone, variant, { @@ -467,7 +467,7 @@ Meteor.methods({ throw new Meteor.Error(403, "Access Denied"); } - let currentVariant = Products.findOne(variant._id); + const currentVariant = Products.findOne(variant._id); // update variants if (typeof currentVariant === "object") { const newVariant = Object.assign({}, currentVariant, variant); @@ -575,7 +575,7 @@ Meteor.methods({ function buildAncestors(ancestors) { const newAncestors = []; ancestors.map(oldId => { - let pair = getIds(oldId); + const pair = getIds(oldId); // TODO do we always have newId on this step? newAncestors.push(pair[0].newId); }); @@ -588,15 +588,15 @@ Meteor.methods({ products = productOrArray; } - for (let product of products) { + for (const product of products) { // cloning product - let productNewId = Random.id(); + const productNewId = Random.id(); setId({ oldId: product._id, newId: productNewId }); - let newProduct = Object.assign({}, product, { + const newProduct = Object.assign({}, product, { _id: productNewId // ancestors: product.ancestors.push(product._id) }); @@ -628,14 +628,14 @@ Meteor.methods({ }).fetch(); // why we are using `_.sortBy` described in `products/cloneVariant` const sortedVariants = _.sortBy(variants, doc => doc.ancestors.length); - for (let variant of sortedVariants) { - let variantNewId = Random.id(); + for (const variant of sortedVariants) { + const variantNewId = Random.id(); setId({ oldId: variant._id, newId: variantNewId }); - let ancestors = buildAncestors(variant.ancestors); - let newVariant = Object.assign({}, variant, { + const ancestors = buildAncestors(variant.ancestors); + const newVariant = Object.assign({}, variant, { _id: variantNewId, ancestors: ancestors }); @@ -782,12 +782,12 @@ Meteor.methods({ if (value === "false" || value === "true") { update = EJSON.parse(`{${field}:${value}}`); } else { - let stringValue = EJSON.stringify(value); + const stringValue = EJSON.stringify(value); update = EJSON.parse("{\"" + field + "\":" + stringValue + "}"); } // we need to use sync mode here, to return correct error and result to UI - let result = Products.update(_id, { + const result = Products.update(_id, { $set: update }, { selector: { @@ -821,17 +821,17 @@ Meteor.methods({ } this.unblock(); - let newTag = { + const newTag = { slug: Reaction.getSlug(tagName), name: tagName }; - let existingTag = Tags.findOne({ + const existingTag = Tags.findOne({ slug: Reaction.getSlug(tagName) }); if (existingTag) { - let productCount = Products.find({ + const productCount = Products.find({ _id: productId, hashtags: { $in: [existingTag._id] @@ -897,13 +897,13 @@ Meteor.methods({ } }); - let productCount = Products.find({ + const productCount = Products.find({ hashtags: { $in: [tagId] } }).count(); - let relatedTagsCount = Tags.find({ + const relatedTagsCount = Tags.find({ relatedTagIds: { $in: [tagId] } @@ -927,7 +927,7 @@ Meteor.methods({ throw new Meteor.Error(403, "Access Denied"); } - let product = Products.findOne(productId); + const product = Products.findOne(productId); let handle = Reaction.getSlug(product.title); handle = createHandle(handle, product._id); Products.update(product._id, { @@ -964,8 +964,8 @@ Meteor.methods({ }; } - let product = Products.findOne(productId); - let tag = Tags.findOne(tagId); + const product = Products.findOne(productId); + const tag = Tags.findOne(tagId); // set handle if (product.handle === tag.slug) { let handle = Reaction.getSlug(product.title); @@ -975,13 +975,13 @@ Meteor.methods({ return handle; } // toggle handle - let existingHandles = Products.find({ + const existingHandles = Products.find({ handle: tag.slug }).fetch(); // this is needed to take care about product's handle which(product) was // previously tagged. - for (let currentProduct of existingHandles) { - let currentProductHandle = createHandle( + for (const currentProduct of existingHandles) { + const currentProductHandle = createHandle( Reaction.getSlug(currentProduct.title), currentProduct._id); Products.update(currentProduct._id, diff --git a/server/methods/core/cart-create.app-test.js b/server/methods/core/cart-create.app-test.js index 1ec15c28ef7..69042f21cdc 100644 --- a/server/methods/core/cart-create.app-test.js +++ b/server/methods/core/cart-create.app-test.js @@ -14,9 +14,9 @@ Fixtures(); describe("Add/Create cart methods", function () { - let user = Factory.create("user"); + const user = Factory.create("user"); const shop = getShop(); - let userId = user._id; + const userId = user._id; const sessionId = Reaction.sessionId = Random.id(); let sandbox; let originals; @@ -61,9 +61,9 @@ describe("Add/Create cart methods", function () { it.skip("should create a test cart", function () { // This test needs to be skipped until we can properly stub out the shopIdAutoValue function sandbox.stub(Reaction, "getShopId", () => shop._id); - let cartInsertSpy = sandbox.spy(Cart, "insert"); - let cartId = Meteor.call("cart/createCart", userId, sessionId); - let cart = Cart.findOne({userId: userId}); + const cartInsertSpy = sandbox.spy(Cart, "insert"); + const cartId = Meteor.call("cart/createCart", userId, sessionId); + const cart = Cart.findOne({userId: userId}); expect(cartInsertSpy).to.have.been.called; expect(cartId).to.equal(cart._id); }); @@ -107,7 +107,7 @@ describe("Add/Create cart methods", function () { it("should add item to cart", function (done) { let cart = Factory.create("cart"); - let items = cart.items.length; + const items = cart.items.length; spyOnMethod("addToCart", cart.userId); Meteor.call("cart/addToCart", productId, variantId, quantity); Meteor._sleepForMs(500); @@ -125,7 +125,7 @@ describe("Add/Create cart methods", function () { Meteor.call("cart/addToCart", productId, variantId, quantity); // add a second item of same variant Meteor.call("cart/addToCart", productId, variantId, quantity); - let cart = Cart.findOne(cartId); + const cart = Cart.findOne(cartId); expect(cart.items.length).to.equal(1); expect(cart.items[0].quantity).to.equal(2); }); @@ -190,7 +190,7 @@ describe("Add/Create cart methods", function () { spyOnMethod("copyCartToOrder", cart.userId); // The main moment of test. We are spy on `insert` operation but do not // let it through this call - let insertStub = sandbox.stub(Reaction.Collections.Orders, "insert"); + const insertStub = sandbox.stub(Reaction.Collections.Orders, "insert"); function copyCartFunc() { return Meteor.call("cart/copyCartToOrder", cart._id); } @@ -200,7 +200,7 @@ describe("Add/Create cart methods", function () { }); it("should create an order", function (done) { - let cart = Factory.create("cartToOrder"); + const cart = Factory.create("cartToOrder"); sandbox.stub(Reaction, "getShopId", function () { return cart.shopId; }); @@ -208,7 +208,7 @@ describe("Add/Create cart methods", function () { // let's keep it simple. We don't want to see a long email about // success. But I leave it here in case if anyone want to check whole // method flow. - let insertStub = sandbox.stub(Reaction.Collections.Orders, "insert"); + const insertStub = sandbox.stub(Reaction.Collections.Orders, "insert"); function copyCartFunc() { return Meteor.call("cart/copyCartToOrder", cart._id); } @@ -250,7 +250,7 @@ describe("Add/Create cart methods", function () { }); it("should throw error if wrong arguments were passed", function (done) { - let accountUpdateStub = sandbox.stub(Accounts, "update"); + const accountUpdateStub = sandbox.stub(Accounts, "update"); expect(function () { return Meteor.call("cart/unsetAddresses", 123456); diff --git a/server/methods/core/cart-merge.app-test.js b/server/methods/core/cart-merge.app-test.js index b2dee8c465a..c80b701c929 100644 --- a/server/methods/core/cart-merge.app-test.js +++ b/server/methods/core/cart-merge.app-test.js @@ -73,13 +73,13 @@ describe("Merge Cart function ", function () { let cartCount = Collections.Cart.find().count(); expect(cartCount).to.equal(2); spyOnMethod("mergeCart", cart.userId); - let cartRemoveSpy = sandbox.spy(Collections.Cart, "remove"); + const cartRemoveSpy = sandbox.spy(Collections.Cart, "remove"); Collections.Cart.update({}, { $set: { sessionId: sessionId } }); - let mergeResult = Meteor.call("cart/mergeCart", cart._id, sessionId); + const mergeResult = Meteor.call("cart/mergeCart", cart._id, sessionId); expect(mergeResult).to.be.ok; anonymousCart = Collections.Cart.findOne(anonymousCart._id); cart = Collections.Cart.findOne(cart._id); @@ -113,7 +113,7 @@ describe("Merge Cart function ", function () { }); it("should throw an error if cart user is not current user", function (done) { - let cart = Factory.create("cart"); + const cart = Factory.create("cart"); spyOnMethod("mergeCart", "someIdHere"); function mergeCartFunction() { return Meteor.call("cart/mergeCart", cart._id, "someSessionId"); diff --git a/server/methods/core/cart-remove.app-test.js b/server/methods/core/cart-remove.app-test.js index 75ff12d0b52..14e7c6e7568 100644 --- a/server/methods/core/cart-remove.app-test.js +++ b/server/methods/core/cart-remove.app-test.js @@ -32,7 +32,7 @@ describe("cart methods", function () { }); it("should remove item from cart", function (done) { - let cart = Factory.create("cart"); + const cart = Factory.create("cart"); const cartUserId = cart.userId; sandbox.stub(Reaction, "getShopId", () => shop._id); sandbox.stub(Meteor, "userId", () => cartUserId); @@ -42,14 +42,14 @@ describe("cart methods", function () { sandbox.stub(Meteor.server.method_handlers, "shipping/updateShipmentQuotes", function () { check(arguments, [Match.Any]); }); - let updateSpy = sandbox.spy(Collections.Cart, "update"); - let cartFromCollection = Collections.Cart.findOne(cart._id); + const updateSpy = sandbox.spy(Collections.Cart, "update"); + const cartFromCollection = Collections.Cart.findOne(cart._id); const cartItemId = cartFromCollection.items[0]._id; assert.equal(cartFromCollection.items.length, 2); Meteor.call("cart/removeFromCart", cartItemId); assert.equal(updateSpy.callCount, 1, "update should be called one time"); Meteor._sleepForMs(1000); - let updatedCart = Collections.Cart.findOne(cart._id); + const updatedCart = Collections.Cart.findOne(cart._id); assert.equal(updatedCart.items.length, 1, "there should be one item left in cart"); return done(); }); @@ -61,16 +61,16 @@ describe("cart methods", function () { sandbox.stub(Meteor.server.method_handlers, "shipping/updateShipmentQuotes", function () { check(arguments, [Match.Any]); }); - let cart = Factory.create("cart"); + const cart = Factory.create("cart"); const cartUserId = cart.userId; sandbox.stub(Reaction, "getShopId", () => shop._id); sandbox.stub(Meteor, "userId", () => cartUserId); - let cartFromCollection = Collections.Cart.findOne(cart._id); + const cartFromCollection = Collections.Cart.findOne(cart._id); const cartItemId = cartFromCollection.items[0]._id; const originalQty = cartFromCollection.items[0].quantity; Meteor.call("cart/removeFromCart", cartItemId, 1); Meteor._sleepForMs(500); - let updatedCart = Collections.Cart.findOne(cart._id); + const updatedCart = Collections.Cart.findOne(cart._id); expect(updatedCart.items[0].quantity).to.equal(originalQty - 1); }); @@ -81,16 +81,16 @@ describe("cart methods", function () { sandbox.stub(Meteor.server.method_handlers, "shipping/updateShipmentQuotes", function () { check(arguments, [Match.Any]); }); - let cart = Factory.create("cart"); + const cart = Factory.create("cart"); const cartUserId = cart.userId; sandbox.stub(Reaction, "getShopId", () => shop._id); sandbox.stub(Meteor, "userId", () => cartUserId); - let cartFromCollection = Collections.Cart.findOne(cart._id); + const cartFromCollection = Collections.Cart.findOne(cart._id); const cartItemId = cartFromCollection.items[0]._id; const originalQty = cartFromCollection.items[0].quantity; Meteor.call("cart/removeFromCart", cartItemId, originalQty); Meteor._sleepForMs(500); - let updatedCart = Collections.Cart.findOne(cart._id); + const updatedCart = Collections.Cart.findOne(cart._id); expect(updatedCart.items.length).to.equal(1); }); diff --git a/server/methods/core/cart.js b/server/methods/core/cart.js index 4c7b23a203e..a1e52f67b70 100644 --- a/server/methods/core/cart.js +++ b/server/methods/core/cart.js @@ -515,7 +515,7 @@ Meteor.methods({ // we could throw an error, but it's not pretty clever, so let it go w/o // email if (typeof user === "object" && user.emails) { - for (let email of user.emails) { + for (const email of user.emails) { // alternate order email address if (email.provides === "orders") { order.email = email.address; @@ -551,14 +551,14 @@ Meteor.methods({ order.shipping = []; } - let expandedItems = []; + const expandedItems = []; // init item level workflow _.each(order.items, function (item) { // Split items based on their quantity for (let i = 0; i < item.quantity; i++) { // Clone Item - let itemClone = _.clone(item); + const itemClone = _.clone(item); // Remove the quantity since we'll be expanding each item as // it's own record @@ -890,7 +890,7 @@ Meteor.methods({ const selector = { _id: cart._id }; - let update = { $unset: {}}; + const update = { $unset: {}}; // user could turn off the checkbox in address to not to be default, then we // receive `type` arg if (typeof type === "string") { diff --git a/server/methods/core/hooks/cart.js b/server/methods/core/hooks/cart.js index 028664eff87..5987f6c2f7d 100644 --- a/server/methods/core/hooks/cart.js +++ b/server/methods/core/hooks/cart.js @@ -11,9 +11,9 @@ MethodHooks.after("cart/submitPayment", function (options) { Logger.debug("MethodHooks after cart/submitPayment", options); // Default return value is the return value of previous call in method chain // or an empty object if there's no result yet. - let result = options.result || {}; + const result = options.result || {}; if (typeof options.error === "undefined") { - let cart = Cart.findOne({ + const cart = Cart.findOne({ userId: Meteor.userId() }); diff --git a/server/methods/core/methods.app-test.js b/server/methods/core/methods.app-test.js index 33692b3b1e7..c4084848a4d 100644 --- a/server/methods/core/methods.app-test.js +++ b/server/methods/core/methods.app-test.js @@ -23,8 +23,8 @@ describe("Server/Core", function () { it("should throw 403 error by non admin", function (done) { let currentTag; let tag; - let tagUpdateSpy = sandbox.spy(Tags, "update"); - let tagRemoveSpy = sandbox.spy(Tags, "remove"); + const tagUpdateSpy = sandbox.spy(Tags, "update"); + const tagRemoveSpy = sandbox.spy(Tags, "remove"); tag = Factory.create("tag"); currentTag = Factory.create("tag"); function removeTagFunc() { @@ -98,7 +98,7 @@ describe("Server/Core", function () { return true; }); let tag; - let tagCount = Tags.find().count(); + const tagCount = Tags.find().count(); Factory.create("shop"); // Create shop so that ReactionCore.getShopId() doesn't fail Meteor.call("shop/updateHeaderTags", "new tag"); expect(Tags.find().count()).to.equal(tagCount + 1); @@ -126,14 +126,14 @@ describe("Server/Core", function () { describe("shop/locateAddress", function () { it("should locate an address based on known US coordinates", function (done) { this.timeout(10000); - let address = Meteor.call("shop/locateAddress", 34.043125, -118.267118); + const address = Meteor.call("shop/locateAddress", 34.043125, -118.267118); expect(address.zipcode).to.equal("90015"); return done(); }); it("should locate an address with known international coordinates", function () { this.timeout(10000); - let address = Meteor.call("shop/locateAddress", 53.414619, -2.947065); + const address = Meteor.call("shop/locateAddress", 53.414619, -2.947065); expect(address.formattedAddress).to.not.be.undefined; expect(address.formattedAddress).to.contain("248 Molyneux Rd, Kensington"); expect(address.formattedAddress).to.contain("Liverpool"); @@ -143,8 +143,8 @@ describe("Server/Core", function () { it("should provide default empty address", function (done) { this.timeout(10000); - let address = Meteor.call("shop/locateAddress", 26.352498, -89.25293); - let defaultAddress = { + const address = Meteor.call("shop/locateAddress", 26.352498, -89.25293); + const defaultAddress = { latitude: null, longitude: null, country: "United States", diff --git a/server/methods/core/orders.js b/server/methods/core/orders.js index 2345baf18d7..82ba08ad91b 100644 --- a/server/methods/core/orders.js +++ b/server/methods/core/orders.js @@ -26,7 +26,7 @@ Meteor.methods({ } this.unblock(); - let orderId = order._id; + const orderId = order._id; Meteor.call("orders/addTracking", orderId, tracking); Meteor.call("orders/updateHistory", orderId, "Tracking Added", @@ -141,7 +141,7 @@ Meteor.methods({ } // Server-side check to make sure discount is not greater than orderTotal. - let orderTotal = accounting.toFixed( + const orderTotal = accounting.toFixed( order.billing[0].invoice.subtotal + order.billing[0].invoice.shipping + order.billing[0].invoice.taxes @@ -156,7 +156,7 @@ Meteor.methods({ this.unblock(); - let total = + const total = order.billing[0].invoice.subtotal + order.billing[0].invoice.shipping + order.billing[0].invoice.taxes @@ -399,7 +399,7 @@ Meteor.methods({ } // temp hack until we build out multiple payment handlers - let cart = Cart.findOne(cartId); + const cart = Cart.findOne(cartId); let shippingId = ""; if (cart.shipping) { shippingId = cart.shipping[0]._id; @@ -535,8 +535,8 @@ Meteor.methods({ */ if (!Meteor.userId()) { - throw new Meteor.Error(403, "Access Denied. You are not connected."); - } + throw new Meteor.Error(403, "Access Denied. You are not connected."); + } return Orders.update({cartId: cartId}, { $set: { @@ -641,7 +641,7 @@ Meteor.methods({ throw new Meteor.Error(403, "Access Denied"); } - let order = Orders.findOne(orderId); + const order = Orders.findOne(orderId); const itemIds = order.shipping[0].items.map((item) => { return item._id; }); @@ -717,7 +717,7 @@ Meteor.methods({ this.unblock(); - let future = new Future(); + const future = new Future(); const processor = paymentMethod.processor.toLowerCase(); Meteor.call(`${processor}/refund/list`, paymentMethod, (error, result) => { @@ -750,8 +750,8 @@ Meteor.methods({ throw new Meteor.Error(403, "Access Denied"); } const processor = paymentMethod.processor.toLowerCase(); - let order = Orders.findOne(orderId); - let transactionId = paymentMethod.transactionId; + const order = Orders.findOne(orderId); + const transactionId = paymentMethod.transactionId; const result = Meteor.call(`${processor}/refund/create`, paymentMethod, amount); Orders.update({ diff --git a/server/methods/core/payments.js b/server/methods/core/payments.js index 5d16eb98367..7804df0e287 100644 --- a/server/methods/core/payments.js +++ b/server/methods/core/payments.js @@ -15,7 +15,7 @@ Meteor.methods({ check(paymentMethod, Object); // temp hack until we build out multiple payment handlers - let cart = Cart.findOne(cartId); + const cart = Cart.findOne(cartId); let paymentId = ""; if (cart.billing) { paymentId = cart.billing[0]._id; diff --git a/server/methods/core/shipping.js b/server/methods/core/shipping.js index ab93bdf8be3..d013533c7f4 100644 --- a/server/methods/core/shipping.js +++ b/server/methods/core/shipping.js @@ -21,9 +21,9 @@ Meteor.methods({ } check(cartId, String); this.unblock(); - let cart = Cart.findOne(cartId); + const cart = Cart.findOne(cartId); if (cart) { - let rates = Meteor.call("shipping/getShippingRates", cart); + const rates = Meteor.call("shipping/getShippingRates", cart); // no rates found if (!rates) { return []; @@ -75,9 +75,9 @@ Meteor.methods({ */ "shipping/getShippingRates": function (cart) { check(cart, Object); - let rates = []; - let shops = []; - let products = cart.items; + const rates = []; + const shops = []; + const products = cart.items; // default selector is current shop let selector = { shopId: Reaction.getShopId() @@ -88,7 +88,7 @@ Meteor.methods({ } // create an array of shops, allowing // the cart to have products from multiple shops - for (let product of products) { + for (const product of products) { if (product.shopId) { shops.push(product.shopId); } @@ -102,11 +102,11 @@ Meteor.methods({ }; } - let shippingMethods = Shipping.find(selector); + const shippingMethods = Shipping.find(selector); shippingMethods.forEach(function (shipping) { - let _results = []; - for (let method of shipping.methods) { + const _results = []; + for (const method of shipping.methods) { if (!(method.enabled === true)) { continue; } diff --git a/server/methods/core/shop.js b/server/methods/core/shop.js index 765e49387cc..4252691a9f6 100644 --- a/server/methods/core/shop.js +++ b/server/methods/core/shop.js @@ -38,8 +38,8 @@ Meteor.methods({ } // identify a shop admin - let userId = shopAdminUserId || Meteor.userId(); - let adminRoles = Roles.getRolesForUser(currentUser, Reaction.getShopId()); + const userId = shopAdminUserId || Meteor.userId(); + const adminRoles = Roles.getRolesForUser(currentUser, Reaction.getShopId()); // ensure unique id and shop name shop._id = Random.id(); shop.name = shop.name + count; @@ -65,8 +65,8 @@ Meteor.methods({ "shop/getLocale": function () { this.unblock(); let clientAddress; - let geo = new GeoCoder(); - let result = {}; + const geo = new GeoCoder(); + const result = {}; let defaultCountryCode = "US"; let localeCurrency = "USD"; // if called from server, ip won't be defined. @@ -77,7 +77,7 @@ Meteor.methods({ } // get shop locale/currency related data - let shop = Collections.Shops.findOne(Reaction.getShopId(), { + const shop = Collections.Shops.findOne(Reaction.getShopId(), { fields: { addressBook: 1, locales: 1, @@ -100,10 +100,10 @@ Meteor.methods({ } } // geocode reverse ip lookup - let geoCountryCode = geo.geoip(clientAddress).country_code; + const geoCountryCode = geo.geoip(clientAddress).country_code; // countryCode either from geo or defaults - let countryCode = (geoCountryCode || defaultCountryCode).toUpperCase(); + const countryCode = (geoCountryCode || defaultCountryCode).toUpperCase(); // get currency rates result.currency = {}; @@ -239,11 +239,11 @@ Meteor.methods({ _.each(shopCurrencies, function (currencyConfig, currencyKey) { if (exchangeRates[currencyKey] !== undefined) { - let rateUpdate = { + const rateUpdate = { // this needed for shop/flushCurrencyRates Method "currencies.updatedAt": new Date(rateResults.data.timestamp * 1000) }; - let collectionKey = `currencies.${currencyKey}.rate`; + const collectionKey = `currencies.${currencyKey}.rate`; rateUpdate[collectionKey] = exchangeRates[currencyKey]; Collections.Shops.update(shopId, { $set: rateUpdate @@ -271,7 +271,7 @@ Meteor.methods({ currencies: 1 } }); - let updatedAt = shop.currencies.updatedAt; + const updatedAt = shop.currencies.updatedAt; // if updatedAt is not a Date(), then there is no rates yet if (typeof updatedAt !== "object") { @@ -284,7 +284,7 @@ Meteor.methods({ if (now < updatedAt) { // todo remove this line. its for tests _.each(shop.currencies, function (currencyConfig, currencyKey) { - let rate = `currencies.${currencyKey}.rate`; + const rate = `currencies.${currencyKey}.rate`; if (typeof currencyConfig.rate === "number") { Collections.Shops.update(shopId, { @@ -365,11 +365,11 @@ Meteor.methods({ // begin actual address lookups if (latitude !== null && longitude !== null) { - let geo = new GeoCoder(); + const geo = new GeoCoder(); return geo.reverse(latitude, longitude); } // geocode reverse ip lookup - let geo = new GeoCoder(); + const geo = new GeoCoder(); return geo.geoip(clientAddress); }, @@ -416,19 +416,19 @@ Meteor.methods({ check(tagId, Match.OneOf(String, null, void 0)); check(currentTagId, Match.OneOf(String, null, void 0)); - let newTagId; + let newTagId = {}; // must have 'core' permissions if (!Reaction.hasPermission("core")) { throw new Meteor.Error(403, "Access Denied"); } this.unblock(); - let newTag = { + const newTag = { slug: Reaction.getSlug(tagName), name: tagName }; - let existingTag = Collections.Tags.findOne({ + const existingTag = Collections.Tags.findOne({ slug: Reaction.getSlug(tagName), name: tagName }); @@ -510,13 +510,13 @@ Meteor.methods({ } }); // check to see if tag is in use. - let productCount = Collections.Products.find({ + const productCount = Collections.Products.find({ hashtags: { $in: [tagId] } }).count(); // check to see if in use as a related tag - let relatedTagsCount = Collections.Tags.find({ + const relatedTagsCount = Collections.Tags.find({ relatedTagIds: { $in: [tagId] } @@ -679,7 +679,7 @@ Meteor.methods({ "shop/changeLayouts": function (shopId, newLayout) { check(shopId, String); check(newLayout, String); - let shop = Collections.Shops.findOne(shopId); + const shop = Collections.Shops.findOne(shopId); for (let i = 0; i < shop.layout.length; i++) { shop.layout[i].layout = newLayout; } diff --git a/server/methods/core/shops.app-test.js b/server/methods/core/shops.app-test.js index 6739edbe9a7..f07fdbe4160 100644 --- a/server/methods/core/shops.app-test.js +++ b/server/methods/core/shops.app-test.js @@ -50,7 +50,7 @@ describe("core shop methods", function () { it("should throw 403 error by non admin", function (done) { sandbox.stub(Reaction, "hasPermission", () => false); - let insertShopSpy = sandbox.spy(Shops, "insert"); + const insertShopSpy = sandbox.spy(Shops, "insert"); function createShopFunc() { return Meteor.call("shop/createShop"); } @@ -74,7 +74,7 @@ describe("shop/changeLayouts", function () { const shop = Factory.create("shop"); Meteor.call("shop/changeLayouts", shop._id, "myNewLayout"); const myShop = Shops.findOne(shop._id); - for (let layout of myShop.layout) { + for (const layout of myShop.layout) { expect(layout.layout).to.equal("myNewLayout"); } }); diff --git a/server/methods/core/workflows/orders.js b/server/methods/core/workflows/orders.js index a000f77baea..0be791540a6 100644 --- a/server/methods/core/workflows/orders.js +++ b/server/methods/core/workflows/orders.js @@ -34,7 +34,7 @@ Meteor.methods({ "workflow/coreOrderWorkflow/coreOrderCompleted": function (options) { check(options, Match.OrderHookOptions()); - let order = options.order; + const order = options.order; const result = _.every(order.items, (item) => { return _.includes(item.workflow.workflow, "coreOrderItemWorkflow/completed"); diff --git a/server/methods/translations.app-test.js b/server/methods/translations.app-test.js index dc9ce109c05..16f251038c4 100644 --- a/server/methods/translations.app-test.js +++ b/server/methods/translations.app-test.js @@ -22,8 +22,8 @@ describe("i18n methods", function () { describe("i18n/flushTranslations", function () { it("should throw 403 error by non admin", function () { sandbox.stub(Roles, "userIsInRole", () => false); - let removeTranslationSpy = sandbox.spy(Translations, "remove"); - let importTranslationSpy = sandbox.spy(Reaction.Import, "translation"); + const removeTranslationSpy = sandbox.spy(Translations, "remove"); + const importTranslationSpy = sandbox.spy(Reaction.Import, "translation"); expect(() => Meteor.call("i18n/flushTranslations")).to.throw(Meteor.Error, /Access Denied/); expect(removeTranslationSpy).to.not.have.been.called; expect(importTranslationSpy).to.not.have.been.called; @@ -32,7 +32,7 @@ describe("i18n methods", function () { it("should remove and load translations back by admin", function () { sandbox.stub(Meteor, "userId", () => "0123456789"); sandbox.stub(Roles, "userIsInRole", () => true); - let removeTranslationSpy = sandbox.spy(Translations, "remove"); + const removeTranslationSpy = sandbox.spy(Translations, "remove"); Factory.create("shop"); Meteor.call("i18n/flushTranslations"); expect(removeTranslationSpy).to.have.been.called; diff --git a/server/publications/collections/cart-publications.app-test.js b/server/publications/collections/cart-publications.app-test.js index 4b53c7b489c..21ca5a1a0b4 100644 --- a/server/publications/collections/cart-publications.app-test.js +++ b/server/publications/collections/cart-publications.app-test.js @@ -40,7 +40,7 @@ describe("Cart Publication", function () { }); it("should return a cart cursor", function () { - let account = Factory.create("account"); + const account = Factory.create("account"); sandbox.stub(Meteor, "userId", function () { return account.userId; }); diff --git a/server/publications/collections/media.js b/server/publications/collections/media.js index c76ca178317..f08811700b8 100644 --- a/server/publications/collections/media.js +++ b/server/publications/collections/media.js @@ -8,7 +8,7 @@ import { Reaction } from "/server/api"; Meteor.publish("Media", function (shops) { check(shops, Match.Optional(Array)); let selector; - let shopId = Reaction.getShopId(); + const shopId = Reaction.getShopId(); if (!shopId) { return this.ready(); } diff --git a/server/publications/collections/members.js b/server/publications/collections/members.js index 7b32bc1fcb8..acc4c79e86a 100644 --- a/server/publications/collections/members.js +++ b/server/publications/collections/members.js @@ -18,8 +18,8 @@ Meteor.publish("ShopMembers", function () { if (typeof this.userId !== "string") { return this.ready(); } - let readPermissions = ["reaction-orders", "owner", "admin", "reaction-accounts"]; - let shopId = Reaction.getShopId(); + const readPermissions = ["reaction-orders", "owner", "admin", "reaction-accounts"]; + const shopId = Reaction.getShopId(); if (!shopId) { return this.ready(); } diff --git a/server/publications/collections/product.js b/server/publications/collections/product.js index c3518586274..86ca7c2633c 100644 --- a/server/publications/collections/product.js +++ b/server/publications/collections/product.js @@ -13,7 +13,7 @@ Meteor.publish("Product", function (productId) { return this.ready(); } let _id; - let shop = Reaction.getCurrentShop(); + const shop = Reaction.getCurrentShop(); // verify that shop is ready if (typeof shop !== "object") { return this.ready(); diff --git a/server/publications/collections/products.js b/server/publications/collections/products.js index eab019434ea..404fa23369f 100644 --- a/server/publications/collections/products.js +++ b/server/publications/collections/products.js @@ -79,7 +79,7 @@ Meteor.publish("Products", function (productScrollLimit = 24, productFilters, so } if (shop) { - let selector = { + const selector = { ancestors: { $exists: true, $eq: [] @@ -97,7 +97,7 @@ Meteor.publish("Products", function (productScrollLimit = 24, productFilters, so }); // check if this user is a shopAdmin - for (let thisShopId of productFilters.shops) { + for (const thisShopId of productFilters.shops) { if (Roles.userIsInRole(this.userId, ["admin", "createProduct"], thisShopId)) { shopAdmin = true; } @@ -115,7 +115,7 @@ Meteor.publish("Products", function (productScrollLimit = 24, productFilters, so // filter by query if (productFilters.query) { - let cond = { + const cond = { $regex: productFilters.query, $options: "i" }; diff --git a/server/publications/collections/sessions.js b/server/publications/collections/sessions.js index 604506e4396..4a8a13a34cf 100644 --- a/server/publications/collections/sessions.js +++ b/server/publications/collections/sessions.js @@ -12,7 +12,7 @@ this.ServerSessions = new Mongo.Collection("Sessions"); Meteor.publish("Sessions", function (sessionId) { check(sessionId, Match.OneOf(String, null)); - let created = new Date().getTime(); + const created = new Date().getTime(); let newSessionId; // if we don"t have a sessionId create a new session // REALLY - we should always have a client sessionId @@ -24,7 +24,7 @@ Meteor.publish("Sessions", function (sessionId) { newSessionId = sessionId; } // get the session from existing sessionId - let serverSession = ServerSessions.find(newSessionId); + const serverSession = ServerSessions.find(newSessionId); // if not found, also create a new server session if (serverSession.count() === 0) { diff --git a/server/startup/accounts.js b/server/startup/accounts.js index 7a4c52d0b4b..dddc417606c 100644 --- a/server/startup/accounts.js +++ b/server/startup/accounts.js @@ -24,12 +24,12 @@ export default function () { return attempt.allowed; } - let loginEmail = attempt.methodArguments[0].user.email; - let adminEmail = process.env.REACTION_EMAIL; + const loginEmail = attempt.methodArguments[0].user.email; + const adminEmail = process.env.REACTION_EMAIL; if (loginEmail && loginEmail === adminEmail) { // filter out the matching login email from any existing emails - let userEmail = _.filter(attempt.user.emails, function (email) { + const userEmail = _.filter(attempt.user.emails, function (email) { return email.address === loginEmail; }); @@ -52,8 +52,8 @@ export default function () { return {}; } let loginHandler; - let stampedToken = Accounts._generateStampedLoginToken(); - let userId = Accounts.insertUserDoc({ + const stampedToken = Accounts._generateStampedLoginToken(); + const userId = Accounts.insertUserDoc({ services: { anonymous: true }, @@ -80,8 +80,8 @@ export default function () { const shopId = shop._id; const defaultVisitorRole = ["anonymous", "guest", "product", "tag", "index", "cart/checkout", "cart/completed"]; const defaultRoles = ["guest", "account/profile", "product", "tag", "index", "cart/checkout", "cart/completed"]; - let roles = {}; - let additionals = { + const roles = {}; + const additionals = { profile: {} }; if (!user.emails) user.emails = []; @@ -94,9 +94,9 @@ export default function () { } else { roles[shopId] = shop.defaultRoles || defaultRoles; // also add services with email defined to user.emails[] - for (let service in user.services) { + for (const service in user.services) { if (user.services[service].email) { - let email = { + const email = { provides: "default", address: user.services[service].email, verified: true @@ -120,7 +120,7 @@ export default function () { } } // clone before adding roles - let account = Object.assign({}, user, additionals); + const account = Object.assign({}, user, additionals); account.userId = user._id; Collections.Accounts.insert(account); @@ -157,7 +157,7 @@ export default function () { // all users are guest, but anonymous user don't have profile access // or ability to order history, etc. so ensure its removed upon login. if (options.type !== "anonymous" && options.type !== "resume") { - let update = { + const update = { $pullAll: {} }; diff --git a/server/startup/i18n.js b/server/startup/i18n.js index 09793156bea..762dc029ab2 100644 --- a/server/startup/i18n.js +++ b/server/startup/i18n.js @@ -19,7 +19,7 @@ export function loadCoreTranslations() { if (directoryExists(i18nFolder)) { fs.readdir(i18nFolder, Meteor.bindEnvironment(function (err, files) { if (err) throw new Meteor.Error("No translations found for import.", err); - for (let file of files) { + for (const file of files) { if (~file.indexOf("json")) { Logger.debug(`Importing Translations from ${file}`); const json = fs.readFileSync(i18nFolder + file, "utf8"); diff --git a/server/startup/plugins.js b/server/startup/plugins.js index 0b6bfd22727..af29262b574 100644 --- a/server/startup/plugins.js +++ b/server/startup/plugins.js @@ -87,9 +87,9 @@ function getImportPaths(baseDirPath) { // get all plugin directories at provided base path const pluginDirs = getDirectories(baseDirPath); - let clientImportPaths = []; - let serverImportPaths = []; - let registryImportPaths = []; + const clientImportPaths = []; + const serverImportPaths = []; + const registryImportPaths = []; // read registry.json and require server/index.js if they exist pluginDirs.forEach((plugin) => {