<commit_before>/**
 * @author: @AngularClass
 */

const webpack = require('webpack');
const helpers = require('./helpers');
const ngtools = require('@ngtools/webpack');
const branding = require('./branding');
var path = require('path');
var stringify = require('json-stringify');
var fs = require('fs');

/*
 * Webpack Plugins
 */
const autoprefixer = require('autoprefixer');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const IgnorePlugin = require('webpack/lib/IgnorePlugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
// const ngcWebpack = require('ngc-webpack');
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
// const TsConfigPathsPlugin = require('awesome-typescript-loader');

/*
 * Webpack Constants
 */
// const HMR = helpers.hasProcessFlag('hot');
// const AOT = helpers.hasNpmFlag('aot');
const METADATA = {
  baseUrl: '/',
  isDevServer: helpers.isWebpackDevServer(),
  FABRIC8_BRANDING: process.env.FABRIC8_BRANDING || 'fabric8'
};

/*
 * Webpack configuration
 *
 * See: http://webpack.github.io/docs/configuration.html#cli
 */
module.exports = function (options) {
  const isProd = options.env === 'production';
  const aotMode = false;//options && options.aot !== undefined;
  console.log('The options from the webpack config: ' + stringify(options, null, 2));

  // ExtractTextPlugin
  const extractCSS = new ExtractTextPlugin({
    filename: '_assets/stylesheets/[name].[id]' + ( isProd ? '.[contenthash]' : '' ) + '.css'
  });

  // const entryFile = aotMode ? './src/main.browser.aot.ts' : './src/main.browser.ts';
  // const outPath = aotMode ? 'dist' : 'aot';
  // const devtool = aotMode ? 'source-map' : 'eval-source-map';
  // const srcPath = path.join(__dirname, 'demo', 'src');
  var config = {

    /*
     * Cache generated modules and chunks to improve performance for multiple incremental builds.
     * This is enabled by default in watch mode.
     * You can pass false to disable it.
     *
     * See: http://webpack.github.io/docs/configuration.html#cache
     */
    //cache: false,

    /*
     * The entry point for the bundle
     * Our Angular.js app
     *
     * See: https://webpack.js.org/configuration/entry-context/#entry
     */
    entry: {
      'polyfills': './src/polyfills.browser.ts',
      'vendor': './src/vendor.browser.ts',
      // 'main': aotMode ? './src/main.browser.aot.ts' : './src/main.browser.ts'
      'main': './src/main.browser.ts'
    },

    /*
     * Options affecting the resolving of modules.
     *
     * See: https://webpack.js.org/configuration/resolve
     */
    resolve: {

      /**
       * An array that automatically resolve certain extensions.
       * Which is what enables users to leave off the extension when importing.
       *
       * See: https://webpack.js.org/configuration/resolve/#resolve-extensions
       */
      extensions: ['.ts', '.js', '.json']
    },

    /*
     * Options affecting the normal modules.
     *
     * See: http://webpack.github.io/docs/configuration.html#module
     */
    module: {

      rules: [

        /*
         * Typescript loader support for .ts and Angular 2 async routes via .async.ts
         * Replace templateUrl and stylesUrl with require()
         *
         * See: https://github.com/s-panferov/awesome-typescript-loader
         * See: https://github.com/TheLarkInn/angular2-template-loader
         */
        {
          test: /\.ts$/,
          use: aotMode ? [
            '@ngtools/webpack'
          ] : [
              '@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd,
              'awesome-typescript-loader',
              'angular2-template-loader',
              'angular2-router-loader'
            ],
          // loaders: '@ngtools/webpack',
          exclude: [/\.(spec|e2e)\.ts$/]
        },

        /**
         * Static analysis linter for TypeScript advanced options configuration
         * Description: An extensible linter for the TypeScript language.
         *
         * See: https://github.com/wbuchwalter/tslint-loader
         */
        {
          test: /\.ts$/,
          enforce: 'pre',
          loader: 'tslint-loader',
          exclude: [
            /node_modules/,
            /src\/a-runtime-console/,
            // /src\/main.browser.ts/,
            // /src\/polyfills.browser.ts/,
            // /src\/vendor.browser.ts/
          ],
          options: {
          //   configuration: {
          //     rules: {
          //       quotemark: [true, 'double']
          //     }
          //   },
          //
            // can specify a custom config file relative to current directory or with absolute path
            // 'tslint-custom.json'
            configFile: "tslint.json",

            // tslint errors are displayed by default as warnings
            // set emitErrors to true to display them as errors
            emitErrors: true,

            // tslint does not interrupt the compilation by default
            // if you want any file with tslint errors to fail
            // set failOnHint to true
            failOnHint: true,

            // enables type checked rules like 'for-in-array'
            // uses tsconfig.json from current working directory
            typeCheck: false,

            // automatically fix linting errors
            fix: false,

            // can specify a custom tsconfig file relative to current directory or with absolute path
            // to be used with type checked rules
            tsConfigFile: 'tsconfig.json',

            // path to directory containing formatter (optional)
            formattersDirectory: 'node_modules/tslint-loader/formatters/',

            // name of your formatter (optional)
            formatter: 'custom',

            // These options are useful if you want to save output to files
            // for your continuous integration server
            fileOutput: {
              // The directory where each file's report is saved
              dir: './lint/',

              // The extension to use for each report's filename. Defaults to 'txt'
              ext: 'xml',

              // If true, all files are removed from the report directory at the beginning of run
              clean: true,

              // A string to include at the top of every report file.
              // Useful for some report formats.
              header: '<?xml version="1.0" encoding="utf-8"?>\n<checkstyle version="5.7">',

              // A string to include at the bottom of every report file.
              // Useful for some report formats.
              footer: '</checkstyle>'
            }
          }
        },

        /*
         * Json loader support for *.json files.
         *
         * See: https://github.com/webpack/json-loader
         */
        {
          test: /\.json$/,
          use: ['json-loader']
        },

        /* HTML Linter
         * Checks all files against .htmlhintrc
        */
        {
          enforce: 'pre',
          test: /\.html$/,
          loader: 'htmlhint-loader',
          exclude: [/node_modules/,/src\/a-runtime-console/],
          options: {
            configFile: './.htmlhintrc'
          }
        },

        /* Raw loader support for *.html
         * Returns file content as string
         *
         * See: https://github.com/webpack/raw-loader
         */
        {
          test: /\.html$/,
          use: ['html-loader']
        },

        /*
         * to string and css loader support for *.css files
         * Returns file content as string
         *
         */
        {
          test: /^(?!.*component).*\.css$/,
          use: extractCSS.extract({
            fallback: "style-loader",
            use: [
              {
                loader: 'css-loader',
                options: {
                  sourceMap: true,
                  context: '/'
                },
              },
            ]
          })
        },
        {
          test: /\.component\.css$/,
          use: [
            {
              loader: 'to-string-loader'
            }, {
              loader: 'css-loader',
              options: {
                minimize: true,
                sourceMap: true,
                context: '/'
              }
            }
          ],
        },
        {
          test: /^(?!.*component).*\.less$/,
          use: extractCSS.extract({
            fallback: 'style-loader',
            use: [
              {
                loader: 'css-loader',
                options: {
                  minimize: true,
                  sourceMap: true,
                  context: '/'
                }
              }, {
                loader: 'less-loader',
                options: {
                  paths: [
                    path.resolve(__dirname, "../node_modules/patternfly/dist/less"),
                    path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies"),
                    path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies/bootstrap"),
                    path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies/font-awesome"),
                  ],
                  sourceMap: true
                }
              }
            ],
          })
        }, {
          test: /\.component\.less$/,
          use: [
            {
              loader: 'to-string-loader'
            }, {
              loader: 'css-loader',
              options: {
                minimize: true,
                sourceMap: true,
                context: '/'
              }
            }, {
              loader: 'less-loader',
              options: {
                paths: [
                  path.resolve(__dirname, "../node_modules/patternfly/dist/less"),
                  path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies"),
                  path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies/bootstrap"),
                  path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies/font-awesome"),
                ],
                sourceMap: true
              }
            }
          ],
        },

        /**
         * File loader for supporting fonts, for example, in CSS files.
         */
        {
          test: /\.(woff2|woff|ttf|eot|svg)$/,
          use: {
            loader: 'url-loader',
            query: {
              limit: 3000,
              includePaths: [
                path.resolve(__dirname, "../node_modules/patternfly/dist/fonts/")
              ],
              name: '_assets/fonts/[name]' + (isProd ? '.[hash]' : '') + '.[ext]'
            }
          },
          exclude: path.resolve(__dirname, "../src/assets/images/")
        },
        {
          test: /\.(jpg|png|svg|gif|jpeg)$/,
          use: {
            loader: 'url-loader',
            query: {
              limit: 3000,
              includePaths: [
                path.resolve(__dirname, "../src/assets/images/")
              ],
              name: '_assets/images/[name]' + (isProd ? '.[hash]' : '') + '.[ext]'
            }
          },
          exclude: path.resolve(__dirname, "../node_modules/patternfly/dist/fonts/")
        }
      ]
    },

    /*
     * Add additional plugins to the compiler.
     *
     * See: http://webpack.github.io/docs/configuration.html#plugins
     */
    plugins: [
      /*
       * Plugin: ForkCheckerPlugin
       * Description: Do type checking in a separate process, so webpack don't need to wait.
       *
       * See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse
       */
      new CheckerPlugin(),

      /*
       * Plugin: CommonsChunkPlugin
       * Description: Shares common code between the pages.
       * It identifies common modules and put them into a commons chunk.
       *
       * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
       * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
       */
      new CommonsChunkPlugin({
        name: ['polyfills', 'vendor'].reverse()
      }),

      /*
       * Plugin: ContextReplacementPlugin
       * Description: Provides context to Angular's use of System.import
       *
       * See: https://webpack.github.io/docs/list-of-plugins.html#contextreplacementplugin
       * See: https://github.com/angular/angular/issues/11580
       */
      new ContextReplacementPlugin(
        // The (\\|\/) piece accounts for path separators in *nix and Windows
        /(.+)?angular(\\|\/)core(.+)?/,
        path.resolve(__dirname, 'src') // location of your src
      ),

      /*
       * Plugin: CopyWebpackPlugin
       * Description: Copy files and directories in webpack.
       *
       * Copies project static assets.
       *
       * See: https://www.npmjs.com/package/copy-webpack-plugin
       */
       /*
       * this needs to be redirected to reside in the _assets/ directory
       */
      new CopyWebpackPlugin([
        {
          from: 'src/meta'
        }
      ]),

      /*
       * Plugin: HtmlWebpackPlugin
       * Description: Simplifies creation of HTML files to serve your webpack bundles.
       * This is especially useful for webpack bundles that include a hash in the filename
       * which changes every compilation.
       *
       * See: https://github.com/ampedandwired/html-webpack-plugin
       */
      new HtmlWebpackPlugin({
        template: 'src/index.ejs',
        title: branding.assets[METADATA.FABRIC8_BRANDING].title.prefix,
        chunksSortMode: 'dependency',
        metadata: METADATA
      }),

      /*
       * Plugin: ScriptExtHtmlWebpackPlugin
       * Description: Enhances html-webpack-plugin functionality
       * with different deployment options for your scripts including:
       *
       * See: https://github.com/numical/script-ext-html-webpack-plugin
       */
      new ScriptExtHtmlWebpackPlugin({
        defaultAttribute: 'defer'
      }),

      /*
       * Plugin LoaderOptionsPlugin (experimental)
       *
       * See: https://gist.github.com/sokra/27b24881210b56bbaff7
       */
      new LoaderOptionsPlugin({}),

      extractCSS,

      new webpack.IgnorePlugin(/^\.\/locale$/, /[^-]moment$/),

      /*
       * StyleLintPlugin
      */
      new StyleLintPlugin({
        configFile: '.stylelintrc',
        syntax: 'less',
        context: 'src',
        files: '**/*.less',
        lintDirtyModulesOnly: false,
        failOnError: true,
        emitErrors: true,
        quiet: false,
      })
    ],

    /*
     * Include polyfills or mocks for various node stuff
     * Description: Node configuration
     *
     * See: https://webpack.github.io/docs/configuration.html#node
     */
    node: {
      global: true,
      crypto: 'empty',
      process: true,
      module: false,
      clearImmediate: false,
      setImmediate: false
    }
  };

  if (aotMode) {
    config.plugins.push(new ngtools.AotPlugin({
      tsConfigPath: 'tsconfig-aot.json'
      // entryModule: './src/app/app.module#AppModule',
      // genDir: './src/aot'
    }));
  }

  return config;
};
<commit_msg>fix(stylelint): prevent webpack watching from stopping when stylelint errors occur (#3053)<commit_after>/**
 * @author: @AngularClass
 */

const webpack = require('webpack');
const helpers = require('./helpers');
const ngtools = require('@ngtools/webpack');
const branding = require('./branding');
var path = require('path');
var stringify = require('json-stringify');
var fs = require('fs');

/*
 * Webpack Plugins
 */
const autoprefixer = require('autoprefixer');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const IgnorePlugin = require('webpack/lib/IgnorePlugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
// const ngcWebpack = require('ngc-webpack');
const NormalModuleReplacementPlugin = require('webpack/lib/NormalModuleReplacementPlugin');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
// const TsConfigPathsPlugin = require('awesome-typescript-loader');

/*
 * Webpack Constants
 */
// const HMR = helpers.hasProcessFlag('hot');
// const AOT = helpers.hasNpmFlag('aot');
const METADATA = {
  baseUrl: '/',
  isDevServer: helpers.isWebpackDevServer(),
  FABRIC8_BRANDING: process.env.FABRIC8_BRANDING || 'fabric8'
};

/*
 * Webpack configuration
 *
 * See: http://webpack.github.io/docs/configuration.html#cli
 */
module.exports = function (options) {
  const isProd = options.env === 'production';
  const aotMode = false;//options && options.aot !== undefined;
  console.log('The options from the webpack config: ' + stringify(options, null, 2));

  // ExtractTextPlugin
  const extractCSS = new ExtractTextPlugin({
    filename: '_assets/stylesheets/[name].[id]' + ( isProd ? '.[contenthash]' : '' ) + '.css'
  });

  // const entryFile = aotMode ? './src/main.browser.aot.ts' : './src/main.browser.ts';
  // const outPath = aotMode ? 'dist' : 'aot';
  // const devtool = aotMode ? 'source-map' : 'eval-source-map';
  // const srcPath = path.join(__dirname, 'demo', 'src');
  var config = {

    /*
     * Cache generated modules and chunks to improve performance for multiple incremental builds.
     * This is enabled by default in watch mode.
     * You can pass false to disable it.
     *
     * See: http://webpack.github.io/docs/configuration.html#cache
     */
    //cache: false,

    /*
     * The entry point for the bundle
     * Our Angular.js app
     *
     * See: https://webpack.js.org/configuration/entry-context/#entry
     */
    entry: {
      'polyfills': './src/polyfills.browser.ts',
      'vendor': './src/vendor.browser.ts',
      // 'main': aotMode ? './src/main.browser.aot.ts' : './src/main.browser.ts'
      'main': './src/main.browser.ts'
    },

    /*
     * Options affecting the resolving of modules.
     *
     * See: https://webpack.js.org/configuration/resolve
     */
    resolve: {

      /**
       * An array that automatically resolve certain extensions.
       * Which is what enables users to leave off the extension when importing.
       *
       * See: https://webpack.js.org/configuration/resolve/#resolve-extensions
       */
      extensions: ['.ts', '.js', '.json']
    },

    /*
     * Options affecting the normal modules.
     *
     * See: http://webpack.github.io/docs/configuration.html#module
     */
    module: {

      rules: [

        /*
         * Typescript loader support for .ts and Angular 2 async routes via .async.ts
         * Replace templateUrl and stylesUrl with require()
         *
         * See: https://github.com/s-panferov/awesome-typescript-loader
         * See: https://github.com/TheLarkInn/angular2-template-loader
         */
        {
          test: /\.ts$/,
          use: aotMode ? [
            '@ngtools/webpack'
          ] : [
              '@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd,
              'awesome-typescript-loader',
              'angular2-template-loader',
              'angular2-router-loader'
            ],
          // loaders: '@ngtools/webpack',
          exclude: [/\.(spec|e2e)\.ts$/]
        },

        /**
         * Static analysis linter for TypeScript advanced options configuration
         * Description: An extensible linter for the TypeScript language.
         *
         * See: https://github.com/wbuchwalter/tslint-loader
         */
        {
          test: /\.ts$/,
          enforce: 'pre',
          loader: 'tslint-loader',
          exclude: [
            /node_modules/,
            /src\/a-runtime-console/,
            // /src\/main.browser.ts/,
            // /src\/polyfills.browser.ts/,
            // /src\/vendor.browser.ts/
          ],
          options: {
          //   configuration: {
          //     rules: {
          //       quotemark: [true, 'double']
          //     }
          //   },
          //
            // can specify a custom config file relative to current directory or with absolute path
            // 'tslint-custom.json'
            configFile: "tslint.json",

            // tslint errors are displayed by default as warnings
            // set emitErrors to true to display them as errors
            emitErrors: true,

            // tslint does not interrupt the compilation by default
            // if you want any file with tslint errors to fail
            // set failOnHint to true
            failOnHint: true,

            // enables type checked rules like 'for-in-array'
            // uses tsconfig.json from current working directory
            typeCheck: false,

            // automatically fix linting errors
            fix: false,

            // can specify a custom tsconfig file relative to current directory or with absolute path
            // to be used with type checked rules
            tsConfigFile: 'tsconfig.json',

            // path to directory containing formatter (optional)
            formattersDirectory: 'node_modules/tslint-loader/formatters/',

            // name of your formatter (optional)
            formatter: 'custom',

            // These options are useful if you want to save output to files
            // for your continuous integration server
            fileOutput: {
              // The directory where each file's report is saved
              dir: './lint/',

              // The extension to use for each report's filename. Defaults to 'txt'
              ext: 'xml',

              // If true, all files are removed from the report directory at the beginning of run
              clean: true,

              // A string to include at the top of every report file.
              // Useful for some report formats.
              header: '<?xml version="1.0" encoding="utf-8"?>\n<checkstyle version="5.7">',

              // A string to include at the bottom of every report file.
              // Useful for some report formats.
              footer: '</checkstyle>'
            }
          }
        },

        /*
         * Json loader support for *.json files.
         *
         * See: https://github.com/webpack/json-loader
         */
        {
          test: /\.json$/,
          use: ['json-loader']
        },

        /* HTML Linter
         * Checks all files against .htmlhintrc
        */
        {
          enforce: 'pre',
          test: /\.html$/,
          loader: 'htmlhint-loader',
          exclude: [/node_modules/,/src\/a-runtime-console/],
          options: {
            configFile: './.htmlhintrc'
          }
        },

        /* Raw loader support for *.html
         * Returns file content as string
         *
         * See: https://github.com/webpack/raw-loader
         */
        {
          test: /\.html$/,
          use: ['html-loader']
        },

        /*
         * to string and css loader support for *.css files
         * Returns file content as string
         *
         */
        {
          test: /^(?!.*component).*\.css$/,
          use: extractCSS.extract({
            fallback: "style-loader",
            use: [
              {
                loader: 'css-loader',
                options: {
                  sourceMap: true,
                  context: '/'
                },
              },
            ]
          })
        },
        {
          test: /\.component\.css$/,
          use: [
            {
              loader: 'to-string-loader'
            }, {
              loader: 'css-loader',
              options: {
                minimize: true,
                sourceMap: true,
                context: '/'
              }
            }
          ],
        },
        {
          test: /^(?!.*component).*\.less$/,
          use: extractCSS.extract({
            fallback: 'style-loader',
            use: [
              {
                loader: 'css-loader',
                options: {
                  minimize: true,
                  sourceMap: true,
                  context: '/'
                }
              }, {
                loader: 'less-loader',
                options: {
                  paths: [
                    path.resolve(__dirname, "../node_modules/patternfly/dist/less"),
                    path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies"),
                    path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies/bootstrap"),
                    path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies/font-awesome"),
                  ],
                  sourceMap: true
                }
              }
            ],
          })
        }, {
          test: /\.component\.less$/,
          use: [
            {
              loader: 'to-string-loader'
            }, {
              loader: 'css-loader',
              options: {
                minimize: true,
                sourceMap: true,
                context: '/'
              }
            }, {
              loader: 'less-loader',
              options: {
                paths: [
                  path.resolve(__dirname, "../node_modules/patternfly/dist/less"),
                  path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies"),
                  path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies/bootstrap"),
                  path.resolve(__dirname, "../node_modules/patternfly/dist/less/dependencies/font-awesome"),
                ],
                sourceMap: true
              }
            }
          ],
        },

        /**
         * File loader for supporting fonts, for example, in CSS files.
         */
        {
          test: /\.(woff2|woff|ttf|eot|svg)$/,
          use: {
            loader: 'url-loader',
            query: {
              limit: 3000,
              includePaths: [
                path.resolve(__dirname, "../node_modules/patternfly/dist/fonts/")
              ],
              name: '_assets/fonts/[name]' + (isProd ? '.[hash]' : '') + '.[ext]'
            }
          },
          exclude: path.resolve(__dirname, "../src/assets/images/")
        },
        {
          test: /\.(jpg|png|svg|gif|jpeg)$/,
          use: {
            loader: 'url-loader',
            query: {
              limit: 3000,
              includePaths: [
                path.resolve(__dirname, "../src/assets/images/")
              ],
              name: '_assets/images/[name]' + (isProd ? '.[hash]' : '') + '.[ext]'
            }
          },
          exclude: path.resolve(__dirname, "../node_modules/patternfly/dist/fonts/")
        }
      ]
    },

    /*
     * Add additional plugins to the compiler.
     *
     * See: http://webpack.github.io/docs/configuration.html#plugins
     */
    plugins: [
      /*
       * Plugin: ForkCheckerPlugin
       * Description: Do type checking in a separate process, so webpack don't need to wait.
       *
       * See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse
       */
      new CheckerPlugin(),

      /*
       * Plugin: CommonsChunkPlugin
       * Description: Shares common code between the pages.
       * It identifies common modules and put them into a commons chunk.
       *
       * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
       * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
       */
      new CommonsChunkPlugin({
        name: ['polyfills', 'vendor'].reverse()
      }),

      /*
       * Plugin: ContextReplacementPlugin
       * Description: Provides context to Angular's use of System.import
       *
       * See: https://webpack.github.io/docs/list-of-plugins.html#contextreplacementplugin
       * See: https://github.com/angular/angular/issues/11580
       */
      new ContextReplacementPlugin(
        // The (\\|\/) piece accounts for path separators in *nix and Windows
        /(.+)?angular(\\|\/)core(.+)?/,
        path.resolve(__dirname, 'src') // location of your src
      ),

      /*
       * Plugin: CopyWebpackPlugin
       * Description: Copy files and directories in webpack.
       *
       * Copies project static assets.
       *
       * See: https://www.npmjs.com/package/copy-webpack-plugin
       */
       /*
       * this needs to be redirected to reside in the _assets/ directory
       */
      new CopyWebpackPlugin([
        {
          from: 'src/meta'
        }
      ]),

      /*
       * Plugin: HtmlWebpackPlugin
       * Description: Simplifies creation of HTML files to serve your webpack bundles.
       * This is especially useful for webpack bundles that include a hash in the filename
       * which changes every compilation.
       *
       * See: https://github.com/ampedandwired/html-webpack-plugin
       */
      new HtmlWebpackPlugin({
        template: 'src/index.ejs',
        title: branding.assets[METADATA.FABRIC8_BRANDING].title.prefix,
        chunksSortMode: 'dependency',
        metadata: METADATA
      }),

      /*
       * Plugin: ScriptExtHtmlWebpackPlugin
       * Description: Enhances html-webpack-plugin functionality
       * with different deployment options for your scripts including:
       *
       * See: https://github.com/numical/script-ext-html-webpack-plugin
       */
      new ScriptExtHtmlWebpackPlugin({
        defaultAttribute: 'defer'
      }),

      /*
       * Plugin LoaderOptionsPlugin (experimental)
       *
       * See: https://gist.github.com/sokra/27b24881210b56bbaff7
       */
      new LoaderOptionsPlugin({}),

      extractCSS,

      new webpack.IgnorePlugin(/^\.\/locale$/, /[^-]moment$/),

      /*
       * StyleLintPlugin
      */
      new StyleLintPlugin({
        configFile: '.stylelintrc',
        syntax: 'less',
        context: 'src',
        files: '**/*.less',
        lintDirtyModulesOnly: false,
        failOnError: false,
        emitErrors: true,
        quiet: false,
      })
    ],

    /*
     * Include polyfills or mocks for various node stuff
     * Description: Node configuration
     *
     * See: https://webpack.github.io/docs/configuration.html#node
     */
    node: {
      global: true,
      crypto: 'empty',
      process: true,
      module: false,
      clearImmediate: false,
      setImmediate: false
    }
  };

  if (aotMode) {
    config.plugins.push(new ngtools.AotPlugin({
      tsConfigPath: 'tsconfig-aot.json'
      // entryModule: './src/app/app.module#AppModule',
      // genDir: './src/aot'
    }));
  }

  return config;
};
<|endoftext|>


<commit_before>/**
 * @author: @AngularClass
 */

const webpack = require('webpack');
const helpers = require('./helpers');

/*
 * Webpack Plugins
 */
// problem with copy-webpack-plugin
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin;
const HtmlElementsPlugin = require('./html-elements-plugin');
const AssetsPlugin = require('assets-webpack-plugin');

/*
 * Webpack Constants
 */
const HMR = helpers.hasProcessFlag('hot');
const METADATA = {
  title: 'Angular2 Webpack Starter by @gdi2290 from @AngularClass',
  baseUrl: '/',
  isDevServer: helpers.isWebpackDevServer()
};

/*
 * Webpack configuration
 *
 * See: http://webpack.github.io/docs/configuration.html#cli
 */
module.exports = function(options) {
  isProd = options.env === 'production';
  return {

    /*
     * Static metadata for index.html
     *
     * See: (custom attribute)
     */
    metadata: METADATA,

    /*
     * Cache generated modules and chunks to improve performance for multiple incremental builds.
     * This is enabled by default in watch mode.
     * You can pass false to disable it.
     *
     * See: http://webpack.github.io/docs/configuration.html#cache
     */
     //cache: false,

    /*
     * The entry point for the bundle
     * Our Angular.js app
     *
     * See: http://webpack.github.io/docs/configuration.html#entry
     */
    entry: {

      'polyfills': './src/polyfills.browser.ts',
      'vendor':    './src/vendor.browser.ts',
      'main':      './src/main.browser.ts'

    },

    /*
     * Options affecting the resolving of modules.
     *
     * See: http://webpack.github.io/docs/configuration.html#resolve
     */
    resolve: {

      /*
       * An array of extensions that should be used to resolve modules.
       *
       * See: http://webpack.github.io/docs/configuration.html#resolve-extensions
       */
      extensions: ['', '.ts', '.js', '.json'],

      // Make sure root is src
      root: helpers.root('src'),

      // remove other default values
      modulesDirectories: ['node_modules'],

    },

    /*
     * Options affecting the normal modules.
     *
     * See: http://webpack.github.io/docs/configuration.html#module
     */
    module: {

      /*
       * An array of applied pre and post loaders.
       *
       * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders
       */
      preLoaders: [
        {
          test: /\.ts$/,
          loader: 'string-replace-loader',
          query: {
            search: '(System|SystemJS)(.*[\\n\\r]\\s*\\.|\\.)import\\((.+)\\)',
            replace: '$1.import($3).then(mod => (mod.__esModule && mod.default) ? mod.default : mod)',
            flags: 'g'
          },
          include: [helpers.root('src')]
        },

      ],

      /*
       * An array of automatically applied loaders.
       *
       * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to.
       * This means they are not resolved relative to the configuration file.
       *
       * See: http://webpack.github.io/docs/configuration.html#module-loaders
       */
      loaders: [

        /*
         * Typescript loader support for .ts and Angular 2 async routes via .async.ts
         * Replace templateUrl and stylesUrl with require()
         *
         * See: https://github.com/s-panferov/awesome-typescript-loader
         * See: https://github.com/TheLarkInn/angular2-template-loader
         */
        {
          test: /\.ts$/,
          loaders: [
            '@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd,
            'awesome-typescript-loader',
            'angular2-template-loader'
          ],
          exclude: [/\.(spec|e2e)\.ts$/]
        },

        /*
         * Json loader support for *.json files.
         *
         * See: https://github.com/webpack/json-loader
         */
        {
          test: /\.json$/,
          loader: 'json-loader'
        },

        /*
         * to string and css loader support for *.css files
         * Returns file content as string
         *
         */
        {
          test: /\.css$/,
          loaders: ['to-string-loader', 'css-loader']
        },

        /* Raw loader support for *.html
         * Returns file content as string
         *
         * See: https://github.com/webpack/raw-loader
         */
        {
          test: /\.html$/,
          loader: 'raw-loader',
          exclude: [helpers.root('src/index.html')]
        },

        /* File loader for supporting images, for example, in CSS files.
        */
        {
          test: /\.(jpg|png|gif)$/,
          loader: 'file'
        }
      ],

      postLoaders: [
        {
          test: /\.js$/,
          loader: 'string-replace-loader',
          query: {
            search: 'var sourceMappingUrl = extractSourceMappingUrl\\(cssText\\);',
            replace: 'var sourceMappingUrl = "";',
            flags: 'g'
          }
        }
      ]
    },

    /*
     * Add additional plugins to the compiler.
     *
     * See: http://webpack.github.io/docs/configuration.html#plugins
     */
    plugins: [
      new AssetsPlugin({
        path: helpers.root('dist'),
        filename: 'webpack-assets.json',
        prettyPrint: true
      }),

      /*
       * Plugin: ForkCheckerPlugin
       * Description: Do type checking in a separate process, so webpack don't need to wait.
       *
       * See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse
       */
      new ForkCheckerPlugin(),
      /*
       * Plugin: CommonsChunkPlugin
       * Description: Shares common code between the pages.
       * It identifies common modules and put them into a commons chunk.
       *
       * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
       * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
       */
      new webpack.optimize.CommonsChunkPlugin({
        name: ['polyfills', 'vendor'].reverse()
      }),

      /*
       * Plugin: CopyWebpackPlugin
       * Description: Copy files and directories in webpack.
       *
       * Copies project static assets.
       *
       * See: https://www.npmjs.com/package/copy-webpack-plugin
       */
      new CopyWebpackPlugin([{
        from: 'src/assets',
        to: 'assets'
      }]),

      /*
       * Plugin: HtmlWebpackPlugin
       * Description: Simplifies creation of HTML files to serve your webpack bundles.
       * This is especially useful for webpack bundles that include a hash in the filename
       * which changes every compilation.
       *
       * See: https://github.com/ampedandwired/html-webpack-plugin
       */
      new HtmlWebpackPlugin({
        template: 'src/index.html',
        chunksSortMode: 'dependency'
      }),

      /*
       * Plugin: HtmlHeadConfigPlugin
       * Description: Generate html tags based on javascript maps.
       *
       * If a publicPath is set in the webpack output configuration, it will be automatically added to
       * href attributes, you can disable that by adding a "=href": false property.
       * You can also enable it to other attribute by settings "=attName": true.
       *
       * The configuration supplied is map between a location (key) and an element definition object (value)
       * The location (key) is then exported to the template under then htmlElements property in webpack configuration.
       *
       * Example:
       *  Adding this plugin configuration
       *  new HtmlElementsPlugin({
       *    headTags: { ... }
       *  })
       *
       *  Means we can use it in the template like this:
       *  <%= webpackConfig.htmlElements.headTags %>
       *
       * Dependencies: HtmlWebpackPlugin
       */
      new HtmlElementsPlugin({
        headTags: require('./head-config.common')
      }),

    ],

    /*
     * Include polyfills or mocks for various node stuff
     * Description: Node configuration
     *
     * See: https://webpack.github.io/docs/configuration.html#node
     */
    node: {
      global: 'window',
      crypto: 'empty',
      process: true,
      module: false,
      clearImmediate: false,
      setImmediate: false
    }

  };
}
<commit_msg>fix: Angular2 dependency warning (#998)<commit_after>/**
 * @author: @AngularClass
 */

const webpack = require('webpack');
const helpers = require('./helpers');

/*
 * Webpack Plugins
 */
// problem with copy-webpack-plugin
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin;
const HtmlElementsPlugin = require('./html-elements-plugin');
const AssetsPlugin = require('assets-webpack-plugin');
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');

/*
 * Webpack Constants
 */
const HMR = helpers.hasProcessFlag('hot');
const METADATA = {
  title: 'Angular2 Webpack Starter by @gdi2290 from @AngularClass',
  baseUrl: '/',
  isDevServer: helpers.isWebpackDevServer()
};

/*
 * Webpack configuration
 *
 * See: http://webpack.github.io/docs/configuration.html#cli
 */
module.exports = function(options) {
  isProd = options.env === 'production';
  return {

    /*
     * Static metadata for index.html
     *
     * See: (custom attribute)
     */
    metadata: METADATA,

    /*
     * Cache generated modules and chunks to improve performance for multiple incremental builds.
     * This is enabled by default in watch mode.
     * You can pass false to disable it.
     *
     * See: http://webpack.github.io/docs/configuration.html#cache
     */
     //cache: false,

    /*
     * The entry point for the bundle
     * Our Angular.js app
     *
     * See: http://webpack.github.io/docs/configuration.html#entry
     */
    entry: {

      'polyfills': './src/polyfills.browser.ts',
      'vendor':    './src/vendor.browser.ts',
      'main':      './src/main.browser.ts'

    },

    /*
     * Options affecting the resolving of modules.
     *
     * See: http://webpack.github.io/docs/configuration.html#resolve
     */
    resolve: {

      /*
       * An array of extensions that should be used to resolve modules.
       *
       * See: http://webpack.github.io/docs/configuration.html#resolve-extensions
       */
      extensions: ['', '.ts', '.js', '.json'],

      // Make sure root is src
      root: helpers.root('src'),

      // remove other default values
      modulesDirectories: ['node_modules'],

    },

    /*
     * Options affecting the normal modules.
     *
     * See: http://webpack.github.io/docs/configuration.html#module
     */
    module: {

      /*
       * An array of applied pre and post loaders.
       *
       * See: http://webpack.github.io/docs/configuration.html#module-preloaders-module-postloaders
       */
      preLoaders: [
        {
          test: /\.ts$/,
          loader: 'string-replace-loader',
          query: {
            search: '(System|SystemJS)(.*[\\n\\r]\\s*\\.|\\.)import\\((.+)\\)',
            replace: '$1.import($3).then(mod => (mod.__esModule && mod.default) ? mod.default : mod)',
            flags: 'g'
          },
          include: [helpers.root('src')]
        },

      ],

      /*
       * An array of automatically applied loaders.
       *
       * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to.
       * This means they are not resolved relative to the configuration file.
       *
       * See: http://webpack.github.io/docs/configuration.html#module-loaders
       */
      loaders: [

        /*
         * Typescript loader support for .ts and Angular 2 async routes via .async.ts
         * Replace templateUrl and stylesUrl with require()
         *
         * See: https://github.com/s-panferov/awesome-typescript-loader
         * See: https://github.com/TheLarkInn/angular2-template-loader
         */
        {
          test: /\.ts$/,
          loaders: [
            '@angularclass/hmr-loader?pretty=' + !isProd + '&prod=' + isProd,
            'awesome-typescript-loader',
            'angular2-template-loader'
          ],
          exclude: [/\.(spec|e2e)\.ts$/]
        },

        /*
         * Json loader support for *.json files.
         *
         * See: https://github.com/webpack/json-loader
         */
        {
          test: /\.json$/,
          loader: 'json-loader'
        },

        /*
         * to string and css loader support for *.css files
         * Returns file content as string
         *
         */
        {
          test: /\.css$/,
          loaders: ['to-string-loader', 'css-loader']
        },

        /* Raw loader support for *.html
         * Returns file content as string
         *
         * See: https://github.com/webpack/raw-loader
         */
        {
          test: /\.html$/,
          loader: 'raw-loader',
          exclude: [helpers.root('src/index.html')]
        },

        /* File loader for supporting images, for example, in CSS files.
        */
        {
          test: /\.(jpg|png|gif)$/,
          loader: 'file'
        }
      ],

      postLoaders: [
        {
          test: /\.js$/,
          loader: 'string-replace-loader',
          query: {
            search: 'var sourceMappingUrl = extractSourceMappingUrl\\(cssText\\);',
            replace: 'var sourceMappingUrl = "";',
            flags: 'g'
          }
        }
      ]
    },

    /*
     * Add additional plugins to the compiler.
     *
     * See: http://webpack.github.io/docs/configuration.html#plugins
     */
    plugins: [
      new AssetsPlugin({
        path: helpers.root('dist'),
        filename: 'webpack-assets.json',
        prettyPrint: true
      }),

      /*
       * Plugin: ForkCheckerPlugin
       * Description: Do type checking in a separate process, so webpack don't need to wait.
       *
       * See: https://github.com/s-panferov/awesome-typescript-loader#forkchecker-boolean-defaultfalse
       */
      new ForkCheckerPlugin(),
      /*
       * Plugin: CommonsChunkPlugin
       * Description: Shares common code between the pages.
       * It identifies common modules and put them into a commons chunk.
       *
       * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin
       * See: https://github.com/webpack/docs/wiki/optimization#multi-page-app
       */
      new webpack.optimize.CommonsChunkPlugin({
        name: ['polyfills', 'vendor'].reverse()
      }),

      /**
       * Plugin: ContextReplacementPlugin
       * Description: Provides context to Angular's use of System.import
       *
       * See: https://webpack.github.io/docs/list-of-plugins.html#contextreplacementplugin
       * See: https://github.com/angular/angular/issues/11580
       */
      new ContextReplacementPlugin(
        // The (\\|\/) piece accounts for path separators in *nix and Windows
        /angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
        helpers.root('src') // location of your src
      ),

      /*
       * Plugin: CopyWebpackPlugin
       * Description: Copy files and directories in webpack.
       *
       * Copies project static assets.
       *
       * See: https://www.npmjs.com/package/copy-webpack-plugin
       */
      new CopyWebpackPlugin([{
        from: 'src/assets',
        to: 'assets'
      }]),

      /*
       * Plugin: HtmlWebpackPlugin
       * Description: Simplifies creation of HTML files to serve your webpack bundles.
       * This is especially useful for webpack bundles that include a hash in the filename
       * which changes every compilation.
       *
       * See: https://github.com/ampedandwired/html-webpack-plugin
       */
      new HtmlWebpackPlugin({
        template: 'src/index.html',
        chunksSortMode: 'dependency'
      }),

      /*
       * Plugin: HtmlHeadConfigPlugin
       * Description: Generate html tags based on javascript maps.
       *
       * If a publicPath is set in the webpack output configuration, it will be automatically added to
       * href attributes, you can disable that by adding a "=href": false property.
       * You can also enable it to other attribute by settings "=attName": true.
       *
       * The configuration supplied is map between a location (key) and an element definition object (value)
       * The location (key) is then exported to the template under then htmlElements property in webpack configuration.
       *
       * Example:
       *  Adding this plugin configuration
       *  new HtmlElementsPlugin({
       *    headTags: { ... }
       *  })
       *
       *  Means we can use it in the template like this:
       *  <%= webpackConfig.htmlElements.headTags %>
       *
       * Dependencies: HtmlWebpackPlugin
       */
      new HtmlElementsPlugin({
        headTags: require('./head-config.common')
      }),

    ],

    /*
     * Include polyfills or mocks for various node stuff
     * Description: Node configuration
     *
     * See: https://webpack.github.io/docs/configuration.html#node
     */
    node: {
      global: 'window',
      crypto: 'empty',
      process: true,
      module: false,
      clearImmediate: false,
      setImmediate: false
    }

  };
}
<|endoftext|>


<commit_before>// Webpack Configuration
// http://webpack.github.io/docs/configuration.html

module.exports = function (isDebug) {
    return {
        output: {
            publicPatch: './build/',
            path: './build/',
            filename: 'app.js',
            hideModules: true
        },

        cache: isDebug,
        debug: isDebug,
        devtool: false,
        entry: './src/app.jsx',
        qiuet: true,

        stats: {
            colors: true,
            reasons: isDebug
        },

        plugins: isDebug ? [] : [
            new webpack.DefinePlugin({'process.env.NODE_ENV': '"production"'})
            new webpack.optimize.DedupePlugin(),
            new webpack.optimize.UglifyJsPlugin(),
            new webpack.optimize.OccurenceOrderPlugin(),
            new webpack.optimize.AggressiveMergingPlugin()
        ],

        module: {
            preLoaders: [
                {
                    test: '\\.js$',
                    exclude: 'node_modules',
                    loader: 'jshint'
                }
            ],

            loaders: [
                {
                    test: /\.css$/,
                    loader: 'style!css'
                },
                {
                    test: /\.gif/,
                    loader: 'url-loader?limit=10000&minetype=image/gif'
                },
                {
                    test: /\.jpg/,
                    loader: 'url-loader?limit=10000&minetype=image/jpg'
                },
                {
                    test: /\.png/,
                    loader: 'url-loader?limit=10000&minetype=image/png'
                },
                {
                    test: /\.jsx$/,
                    loader: 'jsx-loader'
                }
            ]
        }
    };
};
<commit_msg>Fix webpack.config.js for production build. Closes #2<commit_after>// Webpack Configuration
// http://webpack.github.io/docs/configuration.html

var webpack = require('webpack');

module.exports = function (isDebug) {
    return {
        output: {
            publicPatch: './build/',
            path: './build/',
            filename: 'app.js',
            hideModules: true
        },

        cache: isDebug,
        debug: isDebug,
        devtool: false,
        entry: './src/app.jsx',
        qiuet: true,

        stats: {
            colors: true,
            reasons: isDebug
        },

        plugins: isDebug ? [] : [
            new webpack.DefinePlugin({'process.env.NODE_ENV': '"production"'}),
            new webpack.optimize.DedupePlugin(),
            new webpack.optimize.UglifyJsPlugin(),
            new webpack.optimize.OccurenceOrderPlugin(),
            new webpack.optimize.AggressiveMergingPlugin()
        ],

        module: {
            preLoaders: [
                {
                    test: '\\.js$',
                    exclude: 'node_modules',
                    loader: 'jshint'
                }
            ],

            loaders: [
                {
                    test: /\.css$/,
                    loader: 'style!css'
                },
                {
                    test: /\.gif/,
                    loader: 'url-loader?limit=10000&minetype=image/gif'
                },
                {
                    test: /\.jpg/,
                    loader: 'url-loader?limit=10000&minetype=image/jpg'
                },
                {
                    test: /\.png/,
                    loader: 'url-loader?limit=10000&minetype=image/png'
                },
                {
                    test: /\.jsx$/,
                    loader: 'jsx-loader'
                }
            ]
        }
    };
};
<|endoftext|>


<commit_before>/*global Backbone, DOMPurify */
hqDefine("cloudcare/js/formplayer/utils/util", function () {
    var Util = {};

    /**
     * confirmationModal
     *
     * Takes an options hash that specifies options for a confirmation modal.
     *
     * @param options - Object
     *      {
     *          'title': <title> | 'Confirm?',
     *          'message': <message>,
     *          'confirmText': <confirmText> | 'OK',
     *          'cancelText': <cancelText> | 'Cancel',
     *          'onConfirm': function() {},
     *      }
     */
    Util.confirmationModal = function (options) {
        options = _.defaults(options, {
            title: gettext('Confirm?'),
            message: '',
            confirmText: gettext('OK'),
            cancelText: gettext('Cancel'),
            onConfirm: function () {},
        });
        var $modal = $('#js-confirmation-modal');
        $modal.find('.js-modal-title').text(options.title);
        $modal.find('.js-modal-body').html(DOMPurify.sanitize(options.message));
        $modal.find('#js-confirmation-confirm').text(options.confirmText);
        $modal.find('#js-confirmation-cancel').text(options.cancelText);

        var $confirmationButton = $modal.find('#js-confirmation-confirm');
        $confirmationButton.off('.confirmationModal');
        $confirmationButton.on('click.confirmationModal', function (e) {
            options.onConfirm(e);
        });
        $modal.modal('show');
    };

    Util.encodedUrlToObject = function (encodedUrl) {
        return decodeURIComponent(encodedUrl);
    };

    Util.objectToEncodedUrl = function (object) {
        return encodeURIComponent(object);
    };

    Util.currentUrlToObject = function () {
        var url = Backbone.history.getFragment();
        try {
            return Util.CloudcareUrl.fromJson(Util.encodedUrlToObject(url));
        } catch (e) {
            // This means that we're on the homepage
            return new Util.CloudcareUrl({});
        }
    };

    Util.setUrlToObject = function (urlObject, replace) {
        replace = replace || false;
        var encodedUrl = Util.objectToEncodedUrl(urlObject.toJson());
        hqImport("cloudcare/js/formplayer/app").navigate(encodedUrl, { replace: replace });
    };

    Util.doUrlAction = function (actionCallback) {
        var currentObject = Util.CurrentUrlToObject();
        actionCallback(currentObject);
        Util.setUrlToObject(currentObject);
    };

    Util.setCrossDomainAjaxOptions = function (options) {
        options.type = 'POST';
        options.dataType = "json";
        options.crossDomain = {crossDomain: true};
        options.xhrFields = {withCredentials: true};
        options.contentType = "application/json;charset=UTF-8";
    };

    Util.saveDisplayOptions = function (displayOptions) {
        var displayOptionsKey = Util.getDisplayOptionsKey();
        localStorage.setItem(displayOptionsKey, JSON.stringify(displayOptions));
    };

    Util.getSavedDisplayOptions = function () {
        var displayOptionsKey = Util.getDisplayOptionsKey();
        try {
            return JSON.parse(localStorage.getItem(displayOptionsKey));
        } catch (e) {
            window.console.warn('Unabled to parse saved display options');
            return {};
        }
    };

    Util.getDisplayOptionsKey = function () {
        var user = hqImport("cloudcare/js/formplayer/app").getChannel().request('currentUser');
        return [
            user.environment,
            user.domain,
            user.username,
            'displayOptions',
        ].join(':');
    };

    Util.pagesToShow = function (selectedPage, totalPages, limit) {
        var limitHalf = Math.floor(limit / 2);
        if (totalPages < limit) {
            return {
                start: 0,
                end: totalPages,
            };
        }

        if (selectedPage < limitHalf) {
            return {
                start: 0,
                end: limit,
            };
        }

        if (selectedPage > totalPages - limitHalf) {
            return {
                start: totalPages - limit,
                end: totalPages,
            };
        }

        return {
            start: selectedPage - limitHalf,
            end: selectedPage + limitHalf,
        };
    };

    Util.getStickyQueryInputs = function () {
        if (!hqImport("hqwebapp/js/toggles").toggleEnabled('WEBAPPS_STICKY_SEARCH')) {
            return {};
        }
        if (!this.stickyQueryInputs) {
            return {};
        }
        return this.stickyQueryInputs[sessionStorage.queryKey] || {};
    };

    Util.setStickyQueryInputs = function (inputs) {
        if (!this.stickyQueryInputs) {
            this.stickyQueryInputs = {};
        }
        this.stickyQueryInputs[sessionStorage.queryKey] = inputs;
    };

    Util.CloudcareUrl = function (options) {
        this.appId = options.appId;
        this.copyOf = options.copyOf;
        this.sessionId = options.sessionId;
        this.steps = options.steps;
        this.page = options.page;
        this.search = options.search;
        this.queryData = options.queryData;
        this.singleApp = options.singleApp;
        this.sortIndex = options.sortIndex;
        this.forceManualAction = options.forceManualAction;

        this.setSteps = function (steps) {
            this.steps = steps;
        };

        this.addStep = function (step) {
            if (!this.steps) {
                this.steps = [];
            }

            // Steps only deal with strings, because formplayer will send them back as strings
            this.steps.push(String(step));

            // clear out pagination and search when we take a step
            this.page = null;
            this.search = null;
        };

        this.setPage = function (page) {
            this.page = page;
        };

        this.setSort = function (sortIndex) {
            this.sortIndex = sortIndex;
        };

        this.setSearch = function (search) {
            this.search = search;
            //clear out pagination on search
            this.page = null;
            this.sortIndex = null;
        };

        this.setQueryData = function (queryDict, execute) {
            if (!this.queryData) {
                this.queryData = {};
            }
            var steps = hqImport("cloudcare/js/formplayer/utils/util").currentUrlToObject().steps;
            this.queryData[sessionStorage.queryKey] = {
                inputs: queryDict,
                execute: execute,
                selections: steps,
            };
            this.page = null;
            this.search = null;
        };

        this.setForceManualAction = function (force) {
            this.forceManualAction = force;
        };

        this.clearExceptApp = function () {
            this.sessionId = null;
            this.steps = null;
            this.page = null;
            this.sortIndex = null;
            this.search = null;
            this.forceManualAction = null;
        };

        this.onSubmit = function () {
            this.page = null;
            this.sortIndex = null;
            this.search = null;
            this.forceManualAction = null;
        };

        this.spliceSteps = function (index) {
            // null out the session if we clicked the root (home)
            if (index === 0) {
                this.steps = null;
                this.sessionId = null;
            } else {
                this.steps = this.steps.splice(0, index);
                var stepsKey = this.steps.join(",");
                // Query data is necessary to formplayer navigation, so keep it,
                // but only for the steps that are still relevant to the session.
                this.queryData = _.pick(this.queryData, function (value) {
                    var valueKey = value.selections.join(",");
                    return stepsKey.startsWith(valueKey) && stepsKey !== valueKey;
                });
            }
            this.page = null;
            this.search = null;
            this.sortIndex = null;
            this.forceManualAction = null;
        };
    };

    Util.CloudcareUrl.prototype.toJson = function () {
        var self = this;
        var dict = {
            appId: self.appId,
            copyOf: self.copyOf,
            sessionId: self.sessionId,
            steps: self.steps,
            page: self.page,
            search: self.search,
            queryData: self.queryData || {},    // formplayer can't handle a null
            singleApp: self.singleApp,
            sortIndex: self.sortIndex,
            forceManualAction: self.forceManualAction,
        };
        return JSON.stringify(dict);
    };

    Util.CloudcareUrl.fromJson = function (json) {
        var data = JSON.parse(json);
        var options = {
            'appId': data.appId,
            'copyOf': data.copyOf,
            'sessionId': data.sessionId,
            'steps': data.steps,
            'page': data.page,
            'search': data.search,
            'queryData': data.queryData,
            'singleApp': data.singleApp,
            'sortIndex': data.sortIndex,
            'forceManualAction': data.forceManualAction,
        };
        return new Util.CloudcareUrl(options);
    };

    if (!String.prototype.startsWith) {
        String.prototype.startsWith = function (searchString, position) {
            position = position || 0;
            return this.substr(position, searchString.length) === searchString;
        };
    }

    if (!String.prototype.endsWith) {
        String.prototype.endsWith = function (searchString, position) {
            var subjectString = this.toString();
            if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
                position = subjectString.length;
            }
            position -= searchString.length;
            var lastIndex = subjectString.lastIndexOf(searchString, position);
            return lastIndex !== -1 && lastIndex === position;
        };
    }

    if (!String.prototype.includes) {
        String.prototype.includes = function (search, start) {
            'use strict';
            if (typeof start !== 'number') {
                start = 0;
            }
            if (start + search.length > this.length) {
                return false;
            } else {
                return this.indexOf(search, start) !== -1;
            }
        };
    }

    if (!String.prototype.repeat) {
        String.prototype.repeat = function (count) {
            var result = "",
                string = this.valueOf();
            while (count > 0) {
                result += string;
                count -= 1;
            }
            return result;
        };
    }

    return Util;
});
<commit_msg>Fixed queryData not getting cleared<commit_after>/*global Backbone, DOMPurify */
hqDefine("cloudcare/js/formplayer/utils/util", function () {
    var Util = {};

    /**
     * confirmationModal
     *
     * Takes an options hash that specifies options for a confirmation modal.
     *
     * @param options - Object
     *      {
     *          'title': <title> | 'Confirm?',
     *          'message': <message>,
     *          'confirmText': <confirmText> | 'OK',
     *          'cancelText': <cancelText> | 'Cancel',
     *          'onConfirm': function() {},
     *      }
     */
    Util.confirmationModal = function (options) {
        options = _.defaults(options, {
            title: gettext('Confirm?'),
            message: '',
            confirmText: gettext('OK'),
            cancelText: gettext('Cancel'),
            onConfirm: function () {},
        });
        var $modal = $('#js-confirmation-modal');
        $modal.find('.js-modal-title').text(options.title);
        $modal.find('.js-modal-body').html(DOMPurify.sanitize(options.message));
        $modal.find('#js-confirmation-confirm').text(options.confirmText);
        $modal.find('#js-confirmation-cancel').text(options.cancelText);

        var $confirmationButton = $modal.find('#js-confirmation-confirm');
        $confirmationButton.off('.confirmationModal');
        $confirmationButton.on('click.confirmationModal', function (e) {
            options.onConfirm(e);
        });
        $modal.modal('show');
    };

    Util.encodedUrlToObject = function (encodedUrl) {
        return decodeURIComponent(encodedUrl);
    };

    Util.objectToEncodedUrl = function (object) {
        return encodeURIComponent(object);
    };

    Util.currentUrlToObject = function () {
        var url = Backbone.history.getFragment();
        try {
            return Util.CloudcareUrl.fromJson(Util.encodedUrlToObject(url));
        } catch (e) {
            // This means that we're on the homepage
            return new Util.CloudcareUrl({});
        }
    };

    Util.setUrlToObject = function (urlObject, replace) {
        replace = replace || false;
        var encodedUrl = Util.objectToEncodedUrl(urlObject.toJson());
        hqImport("cloudcare/js/formplayer/app").navigate(encodedUrl, { replace: replace });
    };

    Util.doUrlAction = function (actionCallback) {
        var currentObject = Util.CurrentUrlToObject();
        actionCallback(currentObject);
        Util.setUrlToObject(currentObject);
    };

    Util.setCrossDomainAjaxOptions = function (options) {
        options.type = 'POST';
        options.dataType = "json";
        options.crossDomain = {crossDomain: true};
        options.xhrFields = {withCredentials: true};
        options.contentType = "application/json;charset=UTF-8";
    };

    Util.saveDisplayOptions = function (displayOptions) {
        var displayOptionsKey = Util.getDisplayOptionsKey();
        localStorage.setItem(displayOptionsKey, JSON.stringify(displayOptions));
    };

    Util.getSavedDisplayOptions = function () {
        var displayOptionsKey = Util.getDisplayOptionsKey();
        try {
            return JSON.parse(localStorage.getItem(displayOptionsKey));
        } catch (e) {
            window.console.warn('Unabled to parse saved display options');
            return {};
        }
    };

    Util.getDisplayOptionsKey = function () {
        var user = hqImport("cloudcare/js/formplayer/app").getChannel().request('currentUser');
        return [
            user.environment,
            user.domain,
            user.username,
            'displayOptions',
        ].join(':');
    };

    Util.pagesToShow = function (selectedPage, totalPages, limit) {
        var limitHalf = Math.floor(limit / 2);
        if (totalPages < limit) {
            return {
                start: 0,
                end: totalPages,
            };
        }

        if (selectedPage < limitHalf) {
            return {
                start: 0,
                end: limit,
            };
        }

        if (selectedPage > totalPages - limitHalf) {
            return {
                start: totalPages - limit,
                end: totalPages,
            };
        }

        return {
            start: selectedPage - limitHalf,
            end: selectedPage + limitHalf,
        };
    };

    Util.getStickyQueryInputs = function () {
        if (!hqImport("hqwebapp/js/toggles").toggleEnabled('WEBAPPS_STICKY_SEARCH')) {
            return {};
        }
        if (!this.stickyQueryInputs) {
            return {};
        }
        return this.stickyQueryInputs[sessionStorage.queryKey] || {};
    };

    Util.setStickyQueryInputs = function (inputs) {
        if (!this.stickyQueryInputs) {
            this.stickyQueryInputs = {};
        }
        this.stickyQueryInputs[sessionStorage.queryKey] = inputs;
    };

    Util.CloudcareUrl = function (options) {
        this.appId = options.appId;
        this.copyOf = options.copyOf;
        this.sessionId = options.sessionId;
        this.steps = options.steps;
        this.page = options.page;
        this.search = options.search;
        this.queryData = options.queryData;
        this.singleApp = options.singleApp;
        this.sortIndex = options.sortIndex;
        this.forceManualAction = options.forceManualAction;

        this.setSteps = function (steps) {
            this.steps = steps;
        };

        this.addStep = function (step) {
            if (!this.steps) {
                this.steps = [];
            }

            // Steps only deal with strings, because formplayer will send them back as strings
            this.steps.push(String(step));

            // clear out pagination and search when we take a step
            this.page = null;
            this.search = null;
        };

        this.setPage = function (page) {
            this.page = page;
        };

        this.setSort = function (sortIndex) {
            this.sortIndex = sortIndex;
        };

        this.setSearch = function (search) {
            this.search = search;
            //clear out pagination on search
            this.page = null;
            this.sortIndex = null;
        };

        this.setQueryData = function (queryDict, execute) {
            if (!this.queryData) {
                this.queryData = {};
            }
            var steps = hqImport("cloudcare/js/formplayer/utils/util").currentUrlToObject().steps;
            this.queryData[sessionStorage.queryKey] = {
                inputs: queryDict,
                execute: execute,
                selections: steps,
            };
            this.page = null;
            this.search = null;
        };

        this.setForceManualAction = function (force) {
            this.forceManualAction = force;
        };

        this.clearExceptApp = function () {
            this.sessionId = null;
            this.steps = null;
            this.page = null;
            this.sortIndex = null;
            this.search = null;
            this.queryData = null;
            this.forceManualAction = null;
        };

        this.onSubmit = function () {
            this.page = null;
            this.sortIndex = null;
            this.search = null;
            this.queryData = null;
            this.forceManualAction = null;
        };

        this.spliceSteps = function (index) {
            // null out the session if we clicked the root (home)
            if (index === 0) {
                this.steps = null;
                this.sessionId = null;
            } else {
                this.steps = this.steps.splice(0, index);
                var stepsKey = this.steps.join(",");
                // Query data is necessary to formplayer navigation, so keep it,
                // but only for the steps that are still relevant to the session.
                this.queryData = _.pick(this.queryData, function (value) {
                    var valueKey = value.selections.join(",");
                    return stepsKey.startsWith(valueKey) && stepsKey !== valueKey;
                });
            }
            this.page = null;
            this.search = null;
            this.sortIndex = null;
            this.queryData = null;
            this.forceManualAction = null;
        };
    };

    Util.CloudcareUrl.prototype.toJson = function () {
        var self = this;
        var dict = {
            appId: self.appId,
            copyOf: self.copyOf,
            sessionId: self.sessionId,
            steps: self.steps,
            page: self.page,
            search: self.search,
            queryData: self.queryData || {},    // formplayer can't handle a null
            singleApp: self.singleApp,
            sortIndex: self.sortIndex,
            forceManualAction: self.forceManualAction,
        };
        return JSON.stringify(dict);
    };

    Util.CloudcareUrl.fromJson = function (json) {
        var data = JSON.parse(json);
        var options = {
            'appId': data.appId,
            'copyOf': data.copyOf,
            'sessionId': data.sessionId,
            'steps': data.steps,
            'page': data.page,
            'search': data.search,
            'queryData': data.queryData,
            'singleApp': data.singleApp,
            'sortIndex': data.sortIndex,
            'forceManualAction': data.forceManualAction,
        };
        return new Util.CloudcareUrl(options);
    };

    if (!String.prototype.startsWith) {
        String.prototype.startsWith = function (searchString, position) {
            position = position || 0;
            return this.substr(position, searchString.length) === searchString;
        };
    }

    if (!String.prototype.endsWith) {
        String.prototype.endsWith = function (searchString, position) {
            var subjectString = this.toString();
            if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
                position = subjectString.length;
            }
            position -= searchString.length;
            var lastIndex = subjectString.lastIndexOf(searchString, position);
            return lastIndex !== -1 && lastIndex === position;
        };
    }

    if (!String.prototype.includes) {
        String.prototype.includes = function (search, start) {
            'use strict';
            if (typeof start !== 'number') {
                start = 0;
            }
            if (start + search.length > this.length) {
                return false;
            } else {
                return this.indexOf(search, start) !== -1;
            }
        };
    }

    if (!String.prototype.repeat) {
        String.prototype.repeat = function (count) {
            var result = "",
                string = this.valueOf();
            while (count > 0) {
                result += string;
                count -= 1;
            }
            return result;
        };
    }

    return Util;
});
<|endoftext|>


<commit_before>/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
/*global require, exports, window, Backbone, arangoDocumentModel, _, $*/

window.arangoDocuments = Backbone.Collection.extend({
      currentPage: 1,
      collectionID: 1,
      totalPages: 1,
      documentsPerPage: 10,
      documentsCount: 1,
      offset: 0,

      url: '/_api/documents',
      model: arangoDocumentModel,
      getFirstDocuments: function () {
        if (this.currentPage !== 1) {
          var link = window.location.hash.split("/");
          window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/1";
        }
      },
      getLastDocuments: function () {
        if (this.currentPage !== this.totalPages) {
          var link = window.location.hash.split("/");
          window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + this.totalPages;
        }
      },
      getPrevDocuments: function () {
        if (this.currentPage !== 1) {
          var link = window.location.hash.split("/");
          var page = parseInt(this.currentPage, null) - 1;
          window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + page;
        }
      },
      getNextDocuments: function () {
        if (this.currentPage !== this.totalPages) {
          var link = window.location.hash.split("/");
          var page = parseInt(this.currentPage, null) + 1;
          window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + page;
        }
      },
      getDocuments: function (colid, currpage) {
        var self = this;
        this.collectionID = colid;
        this.currentPage = currpage;

        $.ajax({
          cache: false,
          type: "GET",
          url: "/_api/collection/" + this.collectionID + "/count",
          contentType: "application/json",
          processData: false,
          async: false,
          success: function(data) {
            self.totalPages = Math.ceil(data.count / self.documentsPerPage);
            self.documentsCount = data.count;
          },
          error: function(data) {
          }
        });

        if (isNaN(this.currentPage) || this.currentPage === undefined || this.currentPage < 1) {
          this.currentPage = 1;
        }
        if (this.totalPages === 0) {
          this.totalPages = 1;
        }

        this.offset = (this.currentPage - 1) * this.documentsPerPage;

        var myQueryVal;
        var sortParameter = '_key';
        var sortCount = 10000;

        if (this.documentsCount <= sortCount) {
          //sorted
          myQueryVal = "FOR x in @@collection SORT x._key LIMIT @offset, @count RETURN x";
        }
        else {
          //not sorted
          myQueryVal = "FOR x in @@collection LIMIT @offset, @count RETURN x";
        }

        var myQuery = {
          query: myQueryVal,
          bindVars: {
            "@collection": this.collectionID,
            "offset": this.offset,
            "count": this.documentsPerPage
          }
        };

        $.ajax({
          cache: false,
          type: 'POST',
          async: false,
          url: '/_api/cursor',
          data: JSON.stringify(myQuery),
          contentType: "application/json",
          success: function(data) {
            self.clearDocuments();
            if (self.documentsCount !== 0) {
              $.each(data.result, function(k, v) {
                //ERROR HERE
                window.arangoDocumentsStore.add({
                  "id": v._id,
                  "rev": v._rev,
                  "key": v._key,
                  "content": v
                });
              });
              window.documentsView.drawTable();
              window.documentsView.renderPagination(self.totalPages);
            }
            else {
              window.documentsView.initTable();
              window.documentsView.drawTable();
            }
          },
          error: function(data) {
          }
        });
      },

      getFilteredDocuments: function (colid, currpage, filter, bindValues) {
        var self = this;
        this.collectionID = colid;
        this.currentPage = currpage;
        this.currentFilterPage = currpage;
        var filterString;
        if(filter.length === 0){
           filterString ="";
        } else {
          filterString = ' FILTER' + filter.join(' && ');
        }
        var body = {
          //temp solution, waiting for api with paging possibility
          query: "FOR u IN " + this.collectionID +
                 filterString +
                 " LIMIT 0," + self.documentsPerPage +
                 " RETURN u",
          bindVars: bindValues,
          options: {
            fullCount: true
          }
        };
        $.ajax({
          cache: false,
          type: 'POST',
          async: false,
          url: '/_api/cursor',
          data: JSON.stringify(body),
          contentType: "application/json",
          success: function(data) {
            self.clearDocuments();
            self.documentsCount = data.extra.fullCount;
            self.totalPages = Math.ceil(self.documentsCount / self.documentsPerPage);
            if (isNaN(this.currentPage) || this.currentPage === undefined || this.currentPage < 1) {
              this.currentPage = 1;
            }
            if (this.totalPages === 0) {
              this.totalPages = 1;
            }

            this.offset = (this.currentPage - 1) * this.documentsPerPage;
            if (self.documentsCount !== 0) {
              $.each(data.result, function(k, v) {
                window.arangoDocumentsStore.add({
                  "id": v._id,
                  "rev": v._rev,
                  "key": v._key,
                  "content": v
                });
              });
              window.documentsView.drawTable();
              window.documentsView.renderPagination(self.totalPages, true);
            }
            else {
              window.documentsView.initTable();
              window.documentsView.drawTable();
            }
          },
          error: function(data) {
            "use strict";
          }
        });
      },
      clearDocuments: function () {
        window.arangoDocumentsStore.reset();
      }
});
<commit_msg>optimized sorting for documents - frontend<commit_after>/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
/*global require, exports, window, Backbone, arangoDocumentModel, _, $*/

window.arangoDocuments = Backbone.Collection.extend({
      currentPage: 1,
      collectionID: 1,
      totalPages: 1,
      documentsPerPage: 10,
      documentsCount: 1,
      offset: 0,

      url: '/_api/documents',
      model: arangoDocumentModel,
      getFirstDocuments: function () {
        if (this.currentPage !== 1) {
          var link = window.location.hash.split("/");
          window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/1";
        }
      },
      getLastDocuments: function () {
        if (this.currentPage !== this.totalPages) {
          var link = window.location.hash.split("/");
          window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + this.totalPages;
        }
      },
      getPrevDocuments: function () {
        if (this.currentPage !== 1) {
          var link = window.location.hash.split("/");
          var page = parseInt(this.currentPage, null) - 1;
          window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + page;
        }
      },
      getNextDocuments: function () {
        if (this.currentPage !== this.totalPages) {
          var link = window.location.hash.split("/");
          var page = parseInt(this.currentPage, null) + 1;
          window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + page;
        }
      },
      getDocuments: function (colid, currpage) {
        var self = this;
        this.collectionID = colid;
        this.currentPage = currpage;

        $.ajax({
          cache: false,
          type: "GET",
          url: "/_api/collection/" + this.collectionID + "/count",
          contentType: "application/json",
          processData: false,
          async: false,
          success: function(data) {
            self.totalPages = Math.ceil(data.count / self.documentsPerPage);
            self.documentsCount = data.count;
          },
          error: function(data) {
          }
        });

        if (isNaN(this.currentPage) || this.currentPage === undefined || this.currentPage < 1) {
          this.currentPage = 1;
        }
        if (this.totalPages === 0) {
          this.totalPages = 1;
        }

        this.offset = (this.currentPage - 1) * this.documentsPerPage;

        var myQueryVal;
        var sortParameter = '_key';
        var sortCount = 10000;

        if (this.documentsCount <= sortCount) {
          //sorted
          myQueryVal = "FOR x in @@collection SORT TO_NUMBER(x._key) == 0 ? x._key : TO_NUMBER(x._key) LIMIT @offset, @count RETURN x";
        }
        else {
          //not sorted
          myQueryVal = "FOR x in @@collection LIMIT @offset, @count RETURN x";
        }

        var myQuery = {
          query: myQueryVal,
          bindVars: {
            "@collection": this.collectionID,
            "offset": this.offset,
            "count": this.documentsPerPage
          }
        };

        $.ajax({
          cache: false,
          type: 'POST',
          async: false,
          url: '/_api/cursor',
          data: JSON.stringify(myQuery),
          contentType: "application/json",
          success: function(data) {
            self.clearDocuments();
            if (self.documentsCount !== 0) {
              $.each(data.result, function(k, v) {
                //ERROR HERE
                window.arangoDocumentsStore.add({
                  "id": v._id,
                  "rev": v._rev,
                  "key": v._key,
                  "content": v
                });
              });
              window.documentsView.drawTable();
              window.documentsView.renderPagination(self.totalPages);
            }
            else {
              window.documentsView.initTable();
              window.documentsView.drawTable();
            }
          },
          error: function(data) {
          }
        });
      },

      getFilteredDocuments: function (colid, currpage, filter, bindValues) {
        var self = this;
        this.collectionID = colid;
        this.currentPage = currpage;
        this.currentFilterPage = currpage;
        var filterString;
        if(filter.length === 0){
           filterString ="";
        } else {
          filterString = ' FILTER' + filter.join(' && ');
        }

        var sortCount = 10000;

        var sortString = '';
        if (this.documentsCount <= sortCount) {
          //sorted
          sortString = " SORT TO_NUMBER(u._key) == 0 ? u._key : TO_NUMBER(u._key)";
        }
        var myQueryVal = "FOR u in @@collection" + filterString + sortString +
          " LIMIT 0, @count RETURN u";

        var myQuery = {
          query: myQueryVal,
          bindVars: {
            "@collection": this.collectionID,
            "count": this.documentsPerPage
          },
          options: {
            fullCount: true
          }
        };

        $.each(bindValues, function(k,v) {
          myQuery.bindVars[k] = v;
        });

        $.ajax({
          cache: false,
          type: 'POST',
          async: false,
          url: '/_api/cursor',
          data: JSON.stringify(myQuery),
          contentType: "application/json",
          success: function(data) {
            self.clearDocuments();
            self.documentsCount = data.extra.fullCount;
            self.totalPages = Math.ceil(self.documentsCount / self.documentsPerPage);
            if (isNaN(this.currentPage) || this.currentPage === undefined || this.currentPage < 1) {
              this.currentPage = 1;
            }
            if (this.totalPages === 0) {
              this.totalPages = 1;
            }

            this.offset = (this.currentPage - 1) * this.documentsPerPage;
            if (self.documentsCount !== 0) {
              $.each(data.result, function(k, v) {
                window.arangoDocumentsStore.add({
                  "id": v._id,
                  "rev": v._rev,
                  "key": v._key,
                  "content": v
                });
              });
              window.documentsView.drawTable();
              window.documentsView.renderPagination(self.totalPages, true);
            }
            else {
              window.documentsView.initTable();
              window.documentsView.drawTable();
            }
          },
          error: function(data) {
            "use strict";
          }
        });
      },
      clearDocuments: function () {
        window.arangoDocumentsStore.reset();
      }
});
<|endoftext|>


<commit_before>var cdb = require('cartodb.js');
var moment = require('moment');
var Utils = require('cdb.Utils');
var navigateThroughRouter = require('../../common/view_helpers/navigate_through_router');
var pluralizeString = require('../../common/view_helpers/pluralize_string');
var LikesView = require('../../common/views/likes/view');
var EditableDescription = require('../../dashboard/editable_fields/editable_description');
var EditableTags = require('../../dashboard/editable_fields/editable_tags');
var SyncView = require('../../common/dialogs/sync_dataset/sync_dataset_view');

/**
 * View representing an item in the list under datasets route.
 */
module.exports = cdb.core.View.extend({

  tagName: 'li',
  className: 'DatasetsList-item DatasetsList-item--selectable',

  events: {
    'click .js-tag-link': navigateThroughRouter,
    'click .js-privacy': '_openPrivacyDialog',
    'click .js-sync': '_openSyncDialog',
    'click': '_selectDataset'
  },

  initialize: function() {
    this.user = this.options.user;
    this.router = this.options.router;
    this.template = cdb.templates.getTemplate('dashboard/views/datasets_item');

    this._initBinds();
  },

  render: function() {
    this.clearSubViews();
    var vis = this.model;
    var user = this.user;
    var table = vis.tableMetadata();
    var isOwner = vis.permission.isOwner(user);
    var tags = vis.get('tags') || [];

    var url = vis.viewUrl(this.user);
    url = this.router.model.get('liked') && !vis.permission.getPermission(this.user) ? url.public() : url.edit();

    var d = {
      isRaster:                vis.get('kind') === 'raster',
      geometryType:            table.statsGeomColumnTypes().length > 0 ? table.statsGeomColumnTypes()[0] : '',
      title:                   vis.get('name'),
      datasetUrl:              encodeURI(url),
      isOwner:                 isOwner,
      owner:                   vis.permission.owner.renderData(this.user),
      showPermissionIndicator: !isOwner && vis.permission.getPermission(user) === cdb.admin.Permission.READ_ONLY,
      privacy:                 vis.get('privacy').toLowerCase(),
      likes:                   vis.get('likes') || 0,
      timeDiff:                moment(vis.get('updated_at')).fromNow(),
      tags:                    tags,
      tagsCount:               tags.length,
      router:                  this.router,
      maxTagsToShow:           3,
      rowCount:                undefined,
      datasetSize:             undefined,
      syncStatus:              undefined,
      syncRanAt:               undefined,
      fromExternalSource:      vis.get("synchronization") ? vis.get("synchronization").from_external_source : false
    };

    var rowCount = table.get('row_count');
    if (rowCount >= 0) {
      d.rowCount = ( rowCount < 10000 ? Utils.formatNumber(rowCount) : Utils.readizableNumber(rowCount) );
      d.pluralizedRows = pluralizeString('Row', rowCount);
    }

    var datasetSize = table.get('size');
    if (datasetSize >= 0) {
      d.datasetSize = Utils.readablizeBytes(datasetSize, true);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.syncRanAt = moment(vis.get("synchronization").ran_at || new Date()).fromNow();
      d.syncStatus = vis.get("synchronization").state;
    }

    this.$el.html(this.template(d));

    this._renderDescription();
    this._renderTags();
    this._renderLikesIndicator();
    this._renderTooltips();

    // Item selected?
    this.$el[ vis.get('selected') ? 'addClass' : 'removeClass' ]('is--selected');

    return this;
  },

  _initBinds: function() {
    this.model.on('change', this.render, this);
  },

  _renderDescription: function() {
    var isOwner = this.model.permission.isOwner(this.user);
    var view = new EditableDescription({
      el: this.$('.js-item-description'),
      model: this.model,
      editable: isOwner
    });
    this.addView(view.render());
  },

  _renderTags: function() {
    var isOwner = this.model.permission.isOwner(this.user);
    var view = new EditableTags({
      el: this.$('.js-item-tags'),
      model: this.model,
      router: this.router,
      editable: isOwner
    });
    this.addView(view.render());
  },

  _renderLikesIndicator: function() {
    var view = new LikesView({
      model: this.model.like
    });
    this.$('.js-likes-indicator').replaceWith(view.render().el);
    this.addView(view);
  },

  _renderTooltips: function() {
    // Synchronization
    if (!_.isEmpty(this.model.get("synchronization"))) {
      this.addView(
        new cdb.common.TipsyTooltip({
          el: this.$('.DatasetsList-itemStatus'),
          title: function(e) {
            return $(this).attr('data-title')
          }
        })
      )
    }

    // Owner
    if (!this.model.permission.isOwner(this.user)) {
      this.addView(
        new cdb.common.TipsyTooltip({
          el: this.$('.UserAvatar'),
          title: function(e) {
            return $(this).attr('data-title')
          }
        })
      )
    }
  },

  _openPrivacyDialog: function(ev) {
    this.killEvent(ev);
    cdb.god.trigger('openPrivacyDialog', this.model);
  },

  _openSyncDialog: function(ev) {
    this.killEvent(ev);
    var view = new SyncView({
      clean_on_hide: true,
      enter_to_confirm: true,
      table: this.model.tableMetadata()
    });

    // Force render of this item after changing sync settings
    var self = this;
    var originalOK = view.ok;
    view.ok = function() {
      originalOK.apply(view, arguments);
      self.model.fetch(); // to force a re-render due to possible changed sync settings
    };

    view.appendToBody();
  },

  _selectDataset: function(ev) {
    // Let links use default behaviour
    if (ev.target.tagName !== 'A') {
      this.killEvent(ev);
      this.model.set('selected', !this.model.get('selected'));
    }
  }
});
<commit_msg>Uses same style as in the other view<commit_after>var cdb = require('cartodb.js');
var moment = require('moment');
var Utils = require('cdb.Utils');
var navigateThroughRouter = require('../../common/view_helpers/navigate_through_router');
var pluralizeString = require('../../common/view_helpers/pluralize_string');
var LikesView = require('../../common/views/likes/view');
var EditableDescription = require('../../dashboard/editable_fields/editable_description');
var EditableTags = require('../../dashboard/editable_fields/editable_tags');
var SyncView = require('../../common/dialogs/sync_dataset/sync_dataset_view');

/**
 * View representing an item in the list under datasets route.
 */
module.exports = cdb.core.View.extend({

  tagName: 'li',
  className: 'DatasetsList-item DatasetsList-item--selectable',

  events: {
    'click .js-tag-link': navigateThroughRouter,
    'click .js-privacy': '_openPrivacyDialog',
    'click .js-sync': '_openSyncDialog',
    'click': '_selectDataset'
  },

  initialize: function() {
    this.user = this.options.user;
    this.router = this.options.router;
    this.template = cdb.templates.getTemplate('dashboard/views/datasets_item');

    this._initBinds();
  },

  render: function() {
    this.clearSubViews();
    var vis = this.model;
    var user = this.user;
    var table = vis.tableMetadata();
    var isOwner = vis.permission.isOwner(user);
    var tags = vis.get('tags') || [];

    var url = vis.viewUrl(this.user);
    url = this.router.model.get('liked') && !vis.permission.getPermission(this.user) ? url.public() : url.edit();

    var d = {
      isRaster:                vis.get('kind') === 'raster',
      geometryType:            table.statsGeomColumnTypes().length > 0 ? table.statsGeomColumnTypes()[0] : '',
      title:                   vis.get('name'),
      datasetUrl:              encodeURI(url),
      isOwner:                 isOwner,
      owner:                   vis.permission.owner.renderData(this.user),
      showPermissionIndicator: !isOwner && vis.permission.getPermission(user) === cdb.admin.Permission.READ_ONLY,
      privacy:                 vis.get('privacy').toLowerCase(),
      likes:                   vis.get('likes') || 0,
      timeDiff:                moment(vis.get('updated_at')).fromNow(),
      tags:                    tags,
      tagsCount:               tags.length,
      router:                  this.router,
      maxTagsToShow:           3,
      rowCount:                undefined,
      datasetSize:             undefined,
      syncStatus:              undefined,
      syncRanAt:               undefined,
      fromExternalSource:      ""
    };

    var rowCount = table.get('row_count');
    if (rowCount >= 0) {
      d.rowCount = ( rowCount < 10000 ? Utils.formatNumber(rowCount) : Utils.readizableNumber(rowCount) );
      d.pluralizedRows = pluralizeString('Row', rowCount);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.fromExternalSource = vis.get("synchronization").from_external_source;
    }

    var datasetSize = table.get('size');
    if (datasetSize >= 0) {
      d.datasetSize = Utils.readablizeBytes(datasetSize, true);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.syncRanAt = moment(vis.get("synchronization").ran_at || new Date()).fromNow();
      d.syncStatus = vis.get("synchronization").state;
    }

    this.$el.html(this.template(d));

    this._renderDescription();
    this._renderTags();
    this._renderLikesIndicator();
    this._renderTooltips();

    // Item selected?
    this.$el[ vis.get('selected') ? 'addClass' : 'removeClass' ]('is--selected');

    return this;
  },

  _initBinds: function() {
    this.model.on('change', this.render, this);
  },

  _renderDescription: function() {
    var isOwner = this.model.permission.isOwner(this.user);
    var view = new EditableDescription({
      el: this.$('.js-item-description'),
      model: this.model,
      editable: isOwner
    });
    this.addView(view.render());
  },

  _renderTags: function() {
    var isOwner = this.model.permission.isOwner(this.user);
    var view = new EditableTags({
      el: this.$('.js-item-tags'),
      model: this.model,
      router: this.router,
      editable: isOwner
    });
    this.addView(view.render());
  },

  _renderLikesIndicator: function() {
    var view = new LikesView({
      model: this.model.like
    });
    this.$('.js-likes-indicator').replaceWith(view.render().el);
    this.addView(view);
  },

  _renderTooltips: function() {
    // Synchronization
    if (!_.isEmpty(this.model.get("synchronization"))) {
      this.addView(
        new cdb.common.TipsyTooltip({
          el: this.$('.DatasetsList-itemStatus'),
          title: function(e) {
            return $(this).attr('data-title')
          }
        })
      )
    }

    // Owner
    if (!this.model.permission.isOwner(this.user)) {
      this.addView(
        new cdb.common.TipsyTooltip({
          el: this.$('.UserAvatar'),
          title: function(e) {
            return $(this).attr('data-title')
          }
        })
      )
    }
  },

  _openPrivacyDialog: function(ev) {
    this.killEvent(ev);
    cdb.god.trigger('openPrivacyDialog', this.model);
  },

  _openSyncDialog: function(ev) {
    this.killEvent(ev);
    var view = new SyncView({
      clean_on_hide: true,
      enter_to_confirm: true,
      table: this.model.tableMetadata()
    });

    // Force render of this item after changing sync settings
    var self = this;
    var originalOK = view.ok;
    view.ok = function() {
      originalOK.apply(view, arguments);
      self.model.fetch(); // to force a re-render due to possible changed sync settings
    };

    view.appendToBody();
  },

  _selectDataset: function(ev) {
    // Let links use default behaviour
    if (ev.target.tagName !== 'A') {
      this.killEvent(ev);
      this.model.set('selected', !this.model.get('selected'));
    }
  }
});
<|endoftext|>