<commit_before>module.exports = function(grunt) {

    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        changelog: {},

        bump: {
            options: {
                files: ['package.json'],
                updateConfigs: [],
                commit: true,
                commitMessage: 'Release v%VERSION%',
                commitFiles: ['package.json'],
                createTag: true,
                tagName: 'v%VERSION%',
                tagMessage: 'Version %VERSION%',
                push: true,
                pushTo: 'origin',
                gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d'
            }
        },

        jshint: {
            options: {
                node: true,
                browser: true,
                esnext: true,
                bitwise: true,
                curly: true,
                eqeqeq: true,
                immed: true,
                indent: 4,
                latedef: true,
                newcap: true,
                noarg: true,
                regexp: true,
                undef: true,
                unused: true,
                trailing: true,
                smarttabs: true,
                globals: {
                    L: false,

                    // Mocha

                    describe: false,
                    it: false,
                    before: false,
                    after: false,
                    beforeEach: false,
                    afterEach: false,
                    chai: false,
                    expect: false,
                    sinon: false
                }
            },
            source: {
                src: [ 'src/*.js', 'Gruntfile.js', 'package.json' ]
            },
            test: {
                src: [ 'test/SpecHelper.js', 'test/src/**' ],
            },
            grunt: {
                src: [ 'Gruntfile.js' ]
            }
        },

        uglify: {
            dist: {
                files: {
                    'dist/Leaflet.Toolbar.min.js': ['dist/Leaflet.Toolbar.js']
                }
            }
        },

        less: {
            source: {
                files: {
                    'dist/Leaflet.Toolbar.css': 'src/Toolbar.less'
                }
            }
        },

        karma: {
            travis: {
                configFile: 'test/karma.conf.js',
                background: false,
                singleRun: true,
                browsers: [ 'PhantomJS' ]
            },
            development: {
                configFile: 'test/karma.conf.js',
                background: true
            },
            unit: {
                configFile: 'test/karma.conf.js',
                background: false,
                singleRun: true
            }
        },

        watch: {
            options : {
                livereload: true
            },
            source: {
                files: [
                    'src/*.js',
                    'test/**',
                    'Gruntfile.js'
                ],
                tasks: [ 'build:js' ]
            },
            css: {
                files: [ 'src/*.less' ],
                tasks: [ 'build:css' ]
            }

        },

        concat: {
            dist: {
                options: {
                    banner: '(function(window, document, undefined) {\n\n"use strict";\n\n',
                    footer: '\n\n})(window, document);'
                },
                src: [
                    'src/Toolbar.js',
                    'src/ToolbarHandler.js',
                    'src/Toolbar.*.js'
                ],
                dest: 'dist/Leaflet.Toolbar.js',
            }
        }
    });

    /* Run tests once. */
    grunt.registerTask('test', [ 'jshint', 'karma:test', 'coverage' ]);

    /* Default (development): Watch files and lint, test, and build on change. */
    grunt.registerTask('default', ['karma:development:start', 'watch']);

    grunt.registerTask('travis', [ 'jshint', 'karma:travis' ]);

    grunt.registerTask('build:js', [
        'jshint',
        'karma:development:run',
        'coverage',
        'concat:dist',
        'uglify:dist'
    ]);

    grunt.registerTask('build:css', [ 'less' ]);

    grunt.registerTask('coverage', 'Custom commmand-line reporter for karma-coverage', function() {
        var coverageReports = grunt.file.expand('coverage/*/coverage.txt'),
            reports = {},
            report, i, len;

        for (i = 0, len = coverageReports.length; i < len; i++) {
            report = grunt.file.read(coverageReports[i]);
            if (!reports[report]) {
                reports[report] = [coverageReports[i]];
            } else {
                reports[report].push(coverageReports[i]);
            }
        }

        for (report in reports) {
            if (reports.hasOwnProperty(report)) {
                for (i = 0, len = reports[report].length; i < len; i++) {
                    grunt.log.writeln(reports[report][i]);
                }
                grunt.log.writeln(report);
            }
        }
    });
};
<commit_msg>Change ToolbarHandler to ToolbarAction in Gruntfile.<commit_after>module.exports = function(grunt) {

    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        changelog: {},

        bump: {
            options: {
                files: ['package.json'],
                updateConfigs: [],
                commit: true,
                commitMessage: 'Release v%VERSION%',
                commitFiles: ['package.json'],
                createTag: true,
                tagName: 'v%VERSION%',
                tagMessage: 'Version %VERSION%',
                push: true,
                pushTo: 'origin',
                gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d'
            }
        },

        jshint: {
            options: {
                node: true,
                browser: true,
                esnext: true,
                bitwise: true,
                curly: true,
                eqeqeq: true,
                immed: true,
                indent: 4,
                latedef: true,
                newcap: true,
                noarg: true,
                regexp: true,
                undef: true,
                unused: true,
                trailing: true,
                smarttabs: true,
                globals: {
                    L: false,

                    // Mocha

                    describe: false,
                    it: false,
                    before: false,
                    after: false,
                    beforeEach: false,
                    afterEach: false,
                    chai: false,
                    expect: false,
                    sinon: false
                }
            },
            source: {
                src: [ 'src/*.js', 'Gruntfile.js', 'package.json' ]
            },
            test: {
                src: [ 'test/SpecHelper.js', 'test/src/**' ],
            },
            grunt: {
                src: [ 'Gruntfile.js' ]
            }
        },

        uglify: {
            dist: {
                files: {
                    'dist/Leaflet.Toolbar.min.js': ['dist/Leaflet.Toolbar.js']
                }
            }
        },

        less: {
            source: {
                files: {
                    'dist/Leaflet.Toolbar.css': 'src/Toolbar.less'
                }
            }
        },

        karma: {
            travis: {
                configFile: 'test/karma.conf.js',
                background: false,
                singleRun: true,
                browsers: [ 'PhantomJS' ]
            },
            development: {
                configFile: 'test/karma.conf.js',
                background: true
            },
            unit: {
                configFile: 'test/karma.conf.js',
                background: false,
                singleRun: true
            }
        },

        watch: {
            options : {
                livereload: true
            },
            source: {
                files: [
                    'src/*.js',
                    'test/**',
                    'Gruntfile.js'
                ],
                tasks: [ 'build:js' ]
            },
            css: {
                files: [ 'src/*.less' ],
                tasks: [ 'build:css' ]
            }

        },

        concat: {
            dist: {
                options: {
                    banner: '(function(window, document, undefined) {\n\n"use strict";\n\n',
                    footer: '\n\n})(window, document);'
                },
                src: [
                    'src/Toolbar.js',
                    'src/ToolbarAction.js',
                    'src/Toolbar.*.js'
                ],
                dest: 'dist/Leaflet.Toolbar.js',
            }
        }
    });

    /* Run tests once. */
    grunt.registerTask('test', [ 'jshint', 'karma:test', 'coverage' ]);

    /* Default (development): Watch files and lint, test, and build on change. */
    grunt.registerTask('default', ['karma:development:start', 'watch']);

    grunt.registerTask('travis', [ 'jshint', 'karma:travis' ]);

    grunt.registerTask('build:js', [
        'jshint',
        'karma:development:run',
        'coverage',
        'concat:dist',
        'uglify:dist'
    ]);

    grunt.registerTask('build:css', [ 'less' ]);

    grunt.registerTask('coverage', 'Custom commmand-line reporter for karma-coverage', function() {
        var coverageReports = grunt.file.expand('coverage/*/coverage.txt'),
            reports = {},
            report, i, len;

        for (i = 0, len = coverageReports.length; i < len; i++) {
            report = grunt.file.read(coverageReports[i]);
            if (!reports[report]) {
                reports[report] = [coverageReports[i]];
            } else {
                reports[report].push(coverageReports[i]);
            }
        }

        for (report in reports) {
            if (reports.hasOwnProperty(report)) {
                for (i = 0, len = reports[report].length; i < len; i++) {
                    grunt.log.writeln(reports[report][i]);
                }
                grunt.log.writeln(report);
            }
        }
    });
};
<|endoftext|>


<commit_before>/* eslint-disable no-template-curly-in-string */
const path = require('path');

const meta = require('user-meta');
const gitUsername = require('git-username');
const { json, install } = require('mrm-core');

const packages = ['schema-utils', 'loader-utils'];

const devPackages = [
  // Utilities
  'del',
  'del-cli',
  'cross-env',
  'memfs',
  'standard-version',
  '@commitlint/cli',
  '@commitlint/config-conventional',
  'commitlint-azure-pipelines-cli',
  'husky',
  'npm-run-all',

  // Jest
  'jest',
  'jest-junit',
  'babel-jest',

  // Babel
  '@babel/cli',
  '@babel/core',
  '@babel/preset-env',

  // ESLint
  'eslint',
  'eslint-plugin-import',
  'eslint-config-prettier',
  'lint-staged',
  'prettier',

  // Webpack
  'webpack',

  // Webpack Contrib
  '@webpack-contrib/defaults',
  '@webpack-contrib/eslint-config-webpack',
];

module.exports = () => {
  const { name } = meta;
  const github = gitUsername();
  const packageName = path.basename(process.cwd());
  const repository = `${github}/${packageName}`;

  const file = json('package.json');
  const existing = file.get();

  json('package.json')
    .set({
      name: existing.name || `${packageName}`,
      version: existing.version || '1.0.0',
      description: existing.description || '',
      license: existing.license || 'MIT',
      repository: `${repository}`,
      author: existing.author || `${name}`,
      homepage: `https://github.com/${repository}`,
      bugs: `https://github.com/${repository}/issues`,
      main: existing.main || 'dist/cjs.js',
      engines: {
        node: `>= 10.13.0`,
      },
      scripts: {
        start: 'npm run build -- -w',
        clean: 'del-cli dist',
        prebuild: 'npm run clean',
        build: 'cross-env NODE_ENV=production babel src -d dist --copy-files',
        commitlint: 'commitlint --from=master',
        security: 'npm audit',
        'lint:prettier':
          'prettier "{**/*,*}.{js,json,md,yml,css,ts}" --list-different',
        'lint:js': 'eslint --cache .',
        lint: 'npm-run-all -l -p "lint:**"',
        'test:only': 'cross-env NODE_ENV=test jest',
        'test:watch': 'cross-env NODE_ENV=test jest --watch',
        'test:coverage':
          'cross-env NODE_ENV=test jest --collectCoverageFrom="src/**/*.js" --coverage',
        pretest: 'npm run lint',
        test: 'cross-env NODE_ENV=test npm run test:coverage',
        prepare: 'npm run build',
        release: 'standard-version',
        defaults: existing.scripts.defaults || 'webpack-defaults',
      },
      files: existing.files || ['dist/', 'lib/', 'index.js'],
      peerDependencies: existing.peerDependencies || {
        webpack: '^4.0.0 || ^5.0.0',
      },
      dependencies: existing.dependencies || {},
      devDependencies: existing.devDependencies || {},
      keywords: existing.keywords || ['webpack'],
    })
    .save();

  install(packages, { dev: false });
  install(devPackages);
};
<commit_msg>refactor: simplify npm scripts<commit_after>/* eslint-disable no-template-curly-in-string */
const path = require('path');

const meta = require('user-meta');
const gitUsername = require('git-username');
const { json, install } = require('mrm-core');

const packages = ['schema-utils', 'loader-utils'];

const devPackages = [
  // Utilities
  'del',
  'del-cli',
  'cross-env',
  'memfs',
  'standard-version',
  '@commitlint/cli',
  '@commitlint/config-conventional',
  'commitlint-azure-pipelines-cli',
  'husky',
  'npm-run-all',

  // Jest
  'jest',
  'jest-junit',
  'babel-jest',

  // Babel
  '@babel/cli',
  '@babel/core',
  '@babel/preset-env',

  // ESLint
  'eslint',
  'eslint-plugin-import',
  'eslint-config-prettier',
  'lint-staged',
  'prettier',

  // Webpack
  'webpack',

  // Webpack Contrib
  '@webpack-contrib/defaults',
  '@webpack-contrib/eslint-config-webpack',
];

module.exports = () => {
  const { name } = meta;
  const github = gitUsername();
  const packageName = path.basename(process.cwd());
  const repository = `${github}/${packageName}`;

  const file = json('package.json');
  const existing = file.get();

  json('package.json')
    .set({
      name: existing.name || `${packageName}`,
      version: existing.version || '1.0.0',
      description: existing.description || '',
      license: existing.license || 'MIT',
      repository: `${repository}`,
      author: existing.author || `${name}`,
      homepage: `https://github.com/${repository}`,
      bugs: `https://github.com/${repository}/issues`,
      main: existing.main || 'dist/cjs.js',
      engines: {
        node: `>= 10.13.0`,
      },
      scripts: {
        start: 'npm run build -- -w',
        clean: 'del-cli dist',
        prebuild: 'npm run clean',
        build: 'cross-env NODE_ENV=production babel src -d dist --copy-files',
        commitlint: 'commitlint --from=master',
        security: 'npm audit',
        'lint:prettier':
          'prettier "{**/*,*}.{js,json,md,yml,css,ts}" --list-different',
        'lint:js': 'eslint --cache .',
        lint: 'npm-run-all -l -p "lint:**"',
        'test:only': 'cross-env NODE_ENV=test jest',
        'test:watch': 'npm run test:only -- --watch',
        'test:coverage':
          'npm run test:only -- --collectCoverageFrom="src/**/*.js" --coverage',
        pretest: 'npm run lint',
        test: 'npm run test:coverage',
        prepare: 'npm run build',
        release: 'standard-version',
        defaults: existing.scripts.defaults || 'webpack-defaults',
      },
      files: existing.files || ['dist/', 'lib/', 'index.js'],
      peerDependencies: existing.peerDependencies || {
        webpack: '^4.0.0 || ^5.0.0',
      },
      dependencies: existing.dependencies || {},
      devDependencies: existing.devDependencies || {},
      keywords: existing.keywords || ['webpack'],
    })
    .save();

  install(packages, { dev: false });
  install(devPackages);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    revision: {
      options: {
        property: 'meta.revision',
        ref: 'HEAD',
        short: true
      }
    },
    meta: {
      banner: '/**\n' +
        ' * @name <%= pkg.name %>\n' +
        ' * @version <%= pkg.version %>\n' +
        ' * @description\n' +
        ' * <%= pkg.description %>\n' +
        ' * Created at <%= grunt.template.today("yyyy-mm-dd") %>\n' +
        ' * Revision <%= meta.revision %>\n' +
        ' */\n'
    },
    uglify: {
      options: {
        banner: '<%= meta.banner %>',
        mangle: true
      },
      build: {
        files: {
          'build/<%= pkg.name %>.ugly.js': ['build/<%= pkg.name %>.ngmin.js', 'build/templates.js']
        }
      }
    },
    jshint: {
      files: [ 'Gruntfile.js', 'src/modules/**/*.js' ],
      options: {
        globals: {
          jQuery: true,
          console: true,
          module: true
        }
      }
    },
    ngmin: {
      dist: {
        src: [
          'src/anol/anol.js',
          'src/anol/layer.js',
          'src/anol/layer/staticgeojson.js',
          'src/anol/**/*.js',
          'src/modules/module.js',
          'src/modules/**/module.js',
          'src/modules/**/*.js'
        ],
        dest: 'build/<%= pkg.name %>.ngmin.js'
      }
    },
    concat: {
      options: {
        separator: ';\n'
      },
      dev: {
        src: [
          'src/anol/anol.js',
          'src/anol/layer.js',
          'src/anol/layer/staticgeojson.js',
          'src/anol/**/*.js',
          'src/modules/module.js',
          'src/modules/**/module.js',
          'src/modules/**/*.js'
        ],
        dest: 'build/<%= pkg.name %>.js'
      },
      dist: {
        src: [
          'node_modules/jquery/dist/jquery.min.js',
          'node_modules/angular/angular.min.js',
          'node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.min.js',
          'node_modules/angular-translate/dist/angular-translate.min.js',
          'node_modules/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js',
          'node_modules/openlayers/build/ol-custom.js',
          'build/<%= pkg.name %>.ugly.js'
        ],
        dest: 'build/<%= pkg.name %>.min.js'
      }
    },
    clean: {
      prebuild: {
        src: [ 'build' ]
      },
      postbuild: {
        src: [
          'build/<%= pkg.name %>.ngmin.js',
          'build/<%= pkg.name %>.ugly.js',
          'build/templates.js',
        ]
      },
      docs: {
        src: [ 'docs' ]
      },
      'openlayers-build-config': {
        src: [
          'build/openlayers.build.debug.json',
          'build/openlayers.build.json'
        ]
      }
    },
    copy: {
      debug: {
        files: [
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/jquery/dist/jquery.js',
              'node_modules/angular/angular.js',
              'node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.js',
              'node_modules/angular-translate/dist/angular-translate.js',
              'node_modules/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
              'node_modules/openlayers/build/ol-custom.debug.js',
            ],
            dest: 'build'
          },
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/bootstrap/dist/css/bootstrap.css',
              'node_modules/openlayers/dist/ol.css'
            ],
            dest: 'build/css/'
          },
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/bootstrap/dist/fonts/*'
            ],
            dest: 'build/fonts'
          },
          {
            flatten: true,
            expand: true,
            src: 'static/img/*',
            dest: 'build/img'
          }
        ]
      },
      full: {
        files: [
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/bootstrap/dist/css/bootstrap.css',
              'node_modules/openlayers/dist/ol.css'
            ],
            dest: 'build/css/'
          },
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/bootstrap/dist/fonts/*'
            ],
            dest: 'build/fonts'
          },
          {
            flatten: true,
            expand: true,
            src: 'static/img/*',
            dest: 'build/img'
          }
        ]
      }
    },
    'merge-json': {
        'openlayers-build-debug': {
            src: ['config/openlayers.exports.json'],
            dest: 'build/openlayers.build.debug.json'
        },
        'openlayers-build': {
            src: ['config/openlayers.exports.json', 'config/openlayers.compile.json'],
            dest: 'build/openlayers.build.json'
        }
    },
    shell: {
      'build-ol3': {
        command: [
          'cd node_modules/openlayers',
          'make build',
          'node tasks/build.js ../../build/openlayers.build.json build/ol-custom.min.js',
          'cd -'
        ].join('&&')
      },
      'build-ol3-debug' :{
        command: [
          'cd node_modules/openlayers',
          'make build',
          'node tasks/build.js ../../build/openlayers.build.debug.json build/ol-custom.debug.js',
          'cd -'
        ].join('&&')
      }
    },
    connect: {
      server: {
        options: {
          hostname: '*',
          port: 7000
        }
      }
    },
    watch: {
      scripts: {
        files: ['src/anol/**/*.js', 'src/modules/**/*.js', 'src/modules/**/*.html'],
        tasks: ['ngtemplates', 'concat:dev'],
        options: {
          spawn: false,
        },
      },
      sass: {
        files: ['static/css/*.sass'],
        tasks: ['sass', 'copy:resources'],
        options: {
          spawn: false,
        },
      },

    },
    karma: {
        unit: {
          configFile: 'config/karma.conf.js',
        }
    },
    ngdocs: {
      options: {
        dest: 'docs',
        html5Mode: false,
        startPage: '/api',
        title: 'AnOl Documentation',
        editLink: false,
        editExample: false,
        demoExample: false,
        scripts: [
          '../node_modules/openlayers/dist/ol-debug.js',
          '../node_modules/jquery/dist/jquery.min.js',
          '../node_modules/angular/angular.min.js',
          '../node_modules/angular-animate/angular-animate.min.js',
          '../build/anol.js',
          '../build/templates.js'
        ]
      },
      api: {
        title: 'AnOl API',
        src: ['src/modules/**/*.js'],
      },
      wrappers: {
        title: 'Ol3 Wrappers',
        src: ['src/anol/**/*.js']
      }
    },
    ngtemplates:  {
      main: {
        options: {
          module: '<%= pkg.name %>'
        },
        src: ['src/**/templates/*.html'],
        dest: 'build/templates.js'
      }
    },
    sass: {
        options: {
            sourceMap: true
        },
        dist: {
            files: {
                'build/css/anol.css': 'static/css/*.sass'
            }
        }
    },
    concurrent: {
      options: {
        logConcurrentOutput: true
      },
      dev: {
        tasks: ['watch:scripts', 'watch:sass']
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-git-revision');
  grunt.loadNpmTasks('grunt-angular-templates');
  grunt.loadNpmTasks('grunt-ngmin');
  grunt.loadNpmTasks('grunt-ngdocs');
  grunt.loadNpmTasks('grunt-concurrent');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-merge-json');

  grunt.loadNpmTasks('grunt-karma');

  grunt.registerTask('build-ol3', [
    'merge-json:openlayers-build',
    'shell:build-ol3',
    'clean:openlayers-build-config'
  ]);
  grunt.registerTask('build-ol3-debug', [
    'merge-json:openlayers-build-debug',
    'shell:build-ol3-debug',
    'clean:openlayers-build-config'
  ]);

  grunt.registerTask('test', ['karma:unit']);
  grunt.registerTask('dev', [
    'clean:prebuild',
    'sass:dist',
    'ngtemplates',
    'concat:dev',
    'build-ol3-debug',
    'copy:debug',
    'connect:server',
    'concurrent:dev'
  ]);

  grunt.registerTask('build-debug', [
    'clean:prebuild',
    'jshint',
    'sass',
    'ngtemplates',
    'concat:dev',
    'build-ol3-debug',
    'copy:debug'
  ]);
  grunt.registerTask('build-full', [
    'clean:prebuild',
    'jshint',
    'sass',
    'ngtemplates',
    'ngmin:dist',
    'uglify',
    'build-ol3',
    'concat:dist',
    'clean:postbuild',
    'copy:full'
  ]);
  grunt.registerTask('build-doc', ['clean:docs', 'ngdocs']);
};
<commit_msg>Fixed grunt task<commit_after>module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    revision: {
      options: {
        property: 'meta.revision',
        ref: 'HEAD',
        short: true
      }
    },
    meta: {
      banner: '/**\n' +
        ' * @name <%= pkg.name %>\n' +
        ' * @version <%= pkg.version %>\n' +
        ' * @description\n' +
        ' * <%= pkg.description %>\n' +
        ' * Created at <%= grunt.template.today("yyyy-mm-dd") %>\n' +
        ' * Revision <%= meta.revision %>\n' +
        ' */\n'
    },
    uglify: {
      options: {
        banner: '<%= meta.banner %>',
        mangle: true
      },
      build: {
        files: {
          'build/<%= pkg.name %>.ugly.js': ['build/<%= pkg.name %>.ngmin.js', 'build/templates.js']
        }
      }
    },
    jshint: {
      files: [ 'Gruntfile.js', 'src/modules/**/*.js' ],
      options: {
        globals: {
          jQuery: true,
          console: true,
          module: true
        }
      }
    },
    ngmin: {
      dist: {
        src: [
          'src/anol/anol.js',
          'src/anol/layer.js',
          'src/anol/layer/staticgeojson.js',
          'src/anol/**/*.js',
          'src/modules/module.js',
          'src/modules/**/module.js',
          'src/modules/**/*.js'
        ],
        dest: 'build/<%= pkg.name %>.ngmin.js'
      }
    },
    concat: {
      options: {
        separator: ';\n'
      },
      dev: {
        src: [
          'src/anol/anol.js',
          'src/anol/layer.js',
          'src/anol/layer/staticgeojson.js',
          'src/anol/**/*.js',
          'src/modules/module.js',
          'src/modules/**/module.js',
          'src/modules/**/*.js'
        ],
        dest: 'build/<%= pkg.name %>.js'
      },
      dist: {
        src: [
          'node_modules/jquery/dist/jquery.min.js',
          'node_modules/angular/angular.min.js',
          'node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.min.js',
          'node_modules/angular-translate/dist/angular-translate.min.js',
          'node_modules/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js',
          'node_modules/openlayers/build/ol-custom.js',
          'build/<%= pkg.name %>.ugly.js'
        ],
        dest: 'build/<%= pkg.name %>.min.js'
      }
    },
    clean: {
      prebuild: {
        src: [ 'build' ]
      },
      postbuild: {
        src: [
          'build/<%= pkg.name %>.ngmin.js',
          'build/<%= pkg.name %>.ugly.js',
          'build/templates.js',
        ]
      },
      docs: {
        src: [ 'docs' ]
      },
      'openlayers-build-config': {
        src: [
          'build/openlayers.build.debug.json',
          'build/openlayers.build.json'
        ]
      }
    },
    copy: {
      debug: {
        files: [
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/jquery/dist/jquery.js',
              'node_modules/angular/angular.js',
              'node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.js',
              'node_modules/angular-translate/dist/angular-translate.js',
              'node_modules/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
              'node_modules/openlayers/build/ol-custom.debug.js',
            ],
            dest: 'build'
          },
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/bootstrap/dist/css/bootstrap.css',
              'node_modules/openlayers/dist/ol.css'
            ],
            dest: 'build/css/'
          },
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/bootstrap/dist/fonts/*'
            ],
            dest: 'build/fonts'
          },
          {
            flatten: true,
            expand: true,
            src: 'static/img/*',
            dest: 'build/img'
          }
        ]
      },
      full: {
        files: [
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/bootstrap/dist/css/bootstrap.css',
              'node_modules/openlayers/dist/ol.css'
            ],
            dest: 'build/css/'
          },
          {
            flatten: true,
            expand: true,
            src: [
              'node_modules/bootstrap/dist/fonts/*'
            ],
            dest: 'build/fonts'
          },
          {
            flatten: true,
            expand: true,
            src: 'static/img/*',
            dest: 'build/img'
          }
        ]
      }
    },
    'merge-json': {
        'openlayers-build-debug': {
            src: ['config/openlayers.exports.json'],
            dest: 'build/openlayers.build.debug.json'
        },
        'openlayers-build': {
            src: ['config/openlayers.exports.json', 'config/openlayers.compile.json'],
            dest: 'build/openlayers.build.json'
        }
    },
    shell: {
      'build-ol3': {
        command: [
          'cd node_modules/openlayers',
          'make build',
          'node tasks/build.js ../../build/openlayers.build.json build/ol-custom.min.js',
          'cd -'
        ].join('&&')
      },
      'build-ol3-debug' :{
        command: [
          'cd node_modules/openlayers',
          'make build',
          'node tasks/build.js ../../build/openlayers.build.debug.json build/ol-custom.debug.js',
          'cd -'
        ].join('&&')
      }
    },
    connect: {
      server: {
        options: {
          hostname: '*',
          port: 7000
        }
      }
    },
    watch: {
      scripts: {
        files: ['src/anol/**/*.js', 'src/modules/**/*.js', 'src/modules/**/*.html'],
        tasks: ['ngtemplates', 'concat:dev'],
        options: {
          spawn: false,
        },
      },
      sass: {
        files: ['static/css/*.sass'],
        tasks: ['sass', 'copy:debug'],
        options: {
          spawn: false,
        },
      },

    },
    karma: {
        unit: {
          configFile: 'config/karma.conf.js',
        }
    },
    ngdocs: {
      options: {
        dest: 'docs',
        html5Mode: false,
        startPage: '/api',
        title: 'AnOl Documentation',
        editLink: false,
        editExample: false,
        demoExample: false,
        scripts: [
          '../node_modules/openlayers/dist/ol-debug.js',
          '../node_modules/jquery/dist/jquery.min.js',
          '../node_modules/angular/angular.min.js',
          '../node_modules/angular-animate/angular-animate.min.js',
          '../build/anol.js',
          '../build/templates.js'
        ]
      },
      api: {
        title: 'AnOl API',
        src: ['src/modules/**/*.js'],
      },
      wrappers: {
        title: 'Ol3 Wrappers',
        src: ['src/anol/**/*.js']
      }
    },
    ngtemplates:  {
      main: {
        options: {
          module: '<%= pkg.name %>'
        },
        src: ['src/**/templates/*.html'],
        dest: 'build/templates.js'
      }
    },
    sass: {
        options: {
            sourceMap: true
        },
        dist: {
            files: {
                'build/css/anol.css': 'static/css/*.sass'
            }
        }
    },
    concurrent: {
      options: {
        logConcurrentOutput: true
      },
      dev: {
        tasks: ['watch:scripts', 'watch:sass']
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-git-revision');
  grunt.loadNpmTasks('grunt-angular-templates');
  grunt.loadNpmTasks('grunt-ngmin');
  grunt.loadNpmTasks('grunt-ngdocs');
  grunt.loadNpmTasks('grunt-concurrent');
  grunt.loadNpmTasks('grunt-shell');
  grunt.loadNpmTasks('grunt-merge-json');

  grunt.loadNpmTasks('grunt-karma');

  grunt.registerTask('build-ol3', [
    'merge-json:openlayers-build',
    'shell:build-ol3',
    'clean:openlayers-build-config'
  ]);
  grunt.registerTask('build-ol3-debug', [
    'merge-json:openlayers-build-debug',
    'shell:build-ol3-debug',
    'clean:openlayers-build-config'
  ]);

  grunt.registerTask('test', ['karma:unit']);
  grunt.registerTask('dev', [
    'clean:prebuild',
    'sass:dist',
    'ngtemplates',
    'concat:dev',
    'build-ol3-debug',
    'copy:debug',
    'connect:server',
    'concurrent:dev'
  ]);

  grunt.registerTask('build-debug', [
    'clean:prebuild',
    'jshint',
    'sass',
    'ngtemplates',
    'concat:dev',
    'build-ol3-debug',
    'copy:debug'
  ]);
  grunt.registerTask('build-full', [
    'clean:prebuild',
    'jshint',
    'sass',
    'ngtemplates',
    'ngmin:dist',
    'uglify',
    'build-ol3',
    'concat:dist',
    'clean:postbuild',
    'copy:full'
  ]);
  grunt.registerTask('build-doc', ['clean:docs', 'ngdocs']);
};
<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');

const nitro = require('./nitroSdk');
const api = require('./nitroApi/api.js');

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

//_____________________________________________________________________________
let config, apiKey, host;
try {
	config = require('./config.json');
	apiKey = config.nitro.api_key;
	host = config.nitro.host;
}
catch (e) {
	console.log('Please rename config.json.example to config.json and edit for your setup');
	process.exit(2);
}
let query = nitro.newQuery();

nitro.make_request(host,'/nitro/api',apiKey,query,{headers:{Accept: 'application/json'}},function(obj){
	console.log('Nitro JSON API');
	fs.writeFileSync('./nitroApi/api.json',JSON.stringify(obj,null,2));
	return false;
});
nitro.make_request(host,'/nitro/api',apiKey,query,{headers:{Accept: 'text/xml'}},function(obj){
	console.log('Nitro XML API');
	fs.writeFileSync('./nitroApi/api.xml',obj);
	return false;
});
nitro.make_request(host,'/nitro/api/schema',apiKey,query,{headers:{Accept: 'text/xml'}},function(obj){
	console.log('Nitro XML Schema');
	fs.writeFileSync('./nitroApi/nitro-schema.xsd',obj);
	return false;
});
nitro.make_request('ibl.api.bbci.co.uk','/ibl/v1/schema/ibl.json','',query,{headers:{Accept:'application/json'}},function(obj){
	console.log('iBL JSON Schema');
	fs.writeFileSync('./iblApi/ibl.json',JSON.stringify(obj,null,2));
	return false;
});
let iblKey = 'dummy';
nitro.make_request('ibl.api.bbci.co.uk','/ibl/v1/status',iblKey,query,{},function(obj){
	console.log('iBL status '+obj.status.service+' v'+obj.version+' r'+obj.status.release);
	fs.writeFileSync('./iblApi/ibl_status.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('rms.api.bbc.co.uk','/docs/swagger.json','',query,{proto:'https'},function(obj){
	console.log('RMS (BLUR/PULP) openapi.json');
	fs.writeFileSync('./rmsApi/openapi.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('galileo.int.api.bbc.com','/v2/api-docs','',query,{proto:'https'},function(obj){
	console.log('Galileo swagger.json');
	fs.writeFileSync('./galileoApi/swagger.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('raw.githubusercontent.com','/bbc/simorgh/latest/data/schema.yaml','',query,{proto:'https',headers:{Accept:'text/x-yaml'}},function(obj){
	console.log('Simorgh schema.yaml');
	fs.writeFileSync('./simorghApi/openapi.yaml',obj);
	return false;
});

nitro.make_request('access.api.bbc.com','/api-docs','',query,{proto:'https',headers:{Accept:'application/json'}},function(obj){
	console.log('Access API');
	fs.writeFileSync('./accessApi/swagger.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('locator-service.test.api.bbci.co.uk','/v2/api-docs','',query,{proto:'https',headers:{Accept:'application/json'}},function(obj){
	console.log('Locator API');
	fs.writeFileSync('./locatorApi/swagger.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('isl.britbox.co.uk','/api/spec','',query,{proto:'https',headers:{Accept:'application/json'}},function(obj){
	console.log('BritBox API');
	fs.writeFileSync('./britboxApi/swagger.json',JSON.stringify(obj,null,2));
	return false;
});

query.add(api.fProgrammesPartnerPid,'s0000024',true);
query.add(api.fProgrammesPageSize,1);
nitro.make_request(host,api.nitroProgrammes,apiKey,query,{headers:{Accept: 'application/json'}},function(obj){
	let total = (typeof obj.nitro.results.total !== 'undefined') ? obj.nitro.results.total : obj.nitro.results.more_than+1;
	if (total>0) {
	  console.log('Internal programmes present');
	}
	return false;
});
query.add(api.fProgrammesEntityTypeClip);
nitro.make_request(host,api.nitroProgrammes,apiKey,query,{headers:{Accept: 'application/json'}},function(obj){
	let total = (typeof obj.nitro.results.total !== 'undefined') ? obj.nitro.results.total : obj.nitro.results.more_than+1;
	if (total>0) {
	  console.log('Internal clips present');
	}
	return false;
});
<commit_msg>fix: galileo API url changed<commit_after>'use strict';

const fs = require('fs');

const nitro = require('./nitroSdk');
const api = require('./nitroApi/api.js');

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

//_____________________________________________________________________________
let config, apiKey, host;
try {
	config = require('./config.json');
	apiKey = config.nitro.api_key;
	host = config.nitro.host;
}
catch (e) {
	console.log('Please rename config.json.example to config.json and edit for your setup');
	process.exit(2);
}
let query = nitro.newQuery();

nitro.make_request(host,'/nitro/api',apiKey,query,{headers:{Accept: 'application/json'}},function(obj){
	console.log('Nitro JSON API');
	fs.writeFileSync('./nitroApi/api.json',JSON.stringify(obj,null,2));
	return false;
});
nitro.make_request(host,'/nitro/api',apiKey,query,{headers:{Accept: 'text/xml'}},function(obj){
	console.log('Nitro XML API');
	fs.writeFileSync('./nitroApi/api.xml',obj);
	return false;
});
nitro.make_request(host,'/nitro/api/schema',apiKey,query,{headers:{Accept: 'text/xml'}},function(obj){
	console.log('Nitro XML Schema');
	fs.writeFileSync('./nitroApi/nitro-schema.xsd',obj);
	return false;
});
nitro.make_request('ibl.api.bbci.co.uk','/ibl/v1/schema/ibl.json','',query,{headers:{Accept:'application/json'}},function(obj){
	console.log('iBL JSON Schema');
	fs.writeFileSync('./iblApi/ibl.json',JSON.stringify(obj,null,2));
	return false;
});
let iblKey = 'dummy';
nitro.make_request('ibl.api.bbci.co.uk','/ibl/v1/status',iblKey,query,{},function(obj){
	console.log('iBL status '+obj.status.service+' v'+obj.version+' r'+obj.status.release);
	fs.writeFileSync('./iblApi/ibl_status.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('rms.api.bbc.co.uk','/docs/swagger.json','',query,{proto:'https'},function(obj){
	console.log('RMS (BLUR/PULP) openapi.json');
	fs.writeFileSync('./rmsApi/openapi.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('galileo.api.bbc.com','/v2/api-docs','',query,{proto:'https'},function(obj){
	console.log('Galileo swagger.json');
	fs.writeFileSync('./galileoApi/swagger.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('raw.githubusercontent.com','/bbc/simorgh/latest/data/schema.yaml','',query,{proto:'https',headers:{Accept:'text/x-yaml'}},function(obj){
	console.log('Simorgh schema.yaml');
	fs.writeFileSync('./simorghApi/openapi.yaml',obj);
	return false;
});

nitro.make_request('access.api.bbc.com','/api-docs','',query,{proto:'https',headers:{Accept:'application/json'}},function(obj){
	console.log('Access API');
	fs.writeFileSync('./accessApi/swagger.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('locator-service.test.api.bbci.co.uk','/v2/api-docs','',query,{proto:'https',headers:{Accept:'application/json'}},function(obj){
	console.log('Locator API');
	fs.writeFileSync('./locatorApi/swagger.json',JSON.stringify(obj,null,2));
	return false;
});

nitro.make_request('isl.britbox.co.uk','/api/spec','',query,{proto:'https',headers:{Accept:'application/json'}},function(obj){
	console.log('BritBox API');
	fs.writeFileSync('./britboxApi/swagger.json',JSON.stringify(obj,null,2));
	return false;
});

query.add(api.fProgrammesPartnerPid,'s0000024',true);
query.add(api.fProgrammesPageSize,1);
nitro.make_request(host,api.nitroProgrammes,apiKey,query,{headers:{Accept: 'application/json'}},function(obj){
	let total = (typeof obj.nitro.results.total !== 'undefined') ? obj.nitro.results.total : obj.nitro.results.more_than+1;
	if (total>0) {
	  console.log('Internal programmes present');
	}
	return false;
});

query.add(api.fProgrammesEntityTypeClip);
nitro.make_request(host,api.nitroProgrammes,apiKey,query,{headers:{Accept: 'application/json'}},function(obj){
	let total = (typeof obj.nitro.results.total !== 'undefined') ? obj.nitro.results.total : obj.nitro.results.more_than+1;
	if (total>0) {
	  console.log('Internal clips present');
	}
	return false;
});
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: {
      build: { files: [{ expand: true, src: ['src/**'], dest: 'tmp/' }] }
    },
    browserify: {
      dist: {
        src: ['tmp/src/util/**/*.js'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
      },
      dist: {
        files: {
          'dist/<%= pkg.name %>.min.js': ['<%= browserify.dist.dest %>']
        }
      }
    },
    jshint: {
      files: ['gruntfile.js', 'src/client.js', 'src/notifier.js', 'src/stacktrace.js', 'src/util/**/*.js', 'src/processors/**/*.js', 'src/formatters/**/*.js', 'src/reporters/**/*.js', 'test/**/*.js'],
      options: {
        // options here to override JSHint defaults
        globals: {
          jQuery: true,
          console: true,
          module: true,
          document: true
        }
      }
    },
    watch: {
      files: ['<%= jshint.files %>', 'test/**/*.coffee'],
      tasks: ['test']
    },
    connect: {
      server: {
        options: {
          hostname: '*',
          port: 9001,
          base: '.',
          keepalive: true
        }
      }
    },
    mochacli: {
      all: ['test/**/*.coffee'],
      options: {
        // require: ['should'],
        compilers: [ 'coffee:coffee-script' ],
        files: 'test/**/*.coffee',
        bail: true,
        reporter: 'spec'
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-browserify');

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-mocha-cli');

  grunt.registerTask('test', ['build', 'mochacli', 'jshint']);

  grunt.registerTask('build', ['copy', 'browserify']);
  grunt.registerTask('serve', ['connect']);
  grunt.registerTask('default', ['build']);

};
<commit_msg>Copy bower modules to build<commit_after>module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: {
      build: { files: [{ expand: true, src: ['src/**'], dest: 'tmp/' }] }
    },
    bower: {
      dist: {
        dest: 'tmp/bower'
      }
    },
    browserify: {
      dist: {
        src: ['tmp/src/util/**/*.js'],
        dest: 'dist/<%= pkg.name %>.js'
      }
    },
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
      },
      dist: {
        files: {
          'dist/<%= pkg.name %>.min.js': ['<%= browserify.dist.dest %>']
        }
      }
    },
    jshint: {
      files: ['gruntfile.js', 'src/client.js', 'src/notifier.js', 'src/stacktrace.js', 'src/util/**/*.js', 'src/processors/**/*.js', 'src/formatters/**/*.js', 'src/reporters/**/*.js', 'test/**/*.js'],
      options: {
        // options here to override JSHint defaults
        globals: {
          jQuery: true,
          console: true,
          module: true,
          document: true
        }
      }
    },
    watch: {
      files: ['<%= jshint.files %>', 'test/**/*.coffee'],
      tasks: ['test']
    },
    connect: {
      server: {
        options: {
          hostname: '*',
          port: 9001,
          base: '.',
          keepalive: true
        }
      }
    },
    mochacli: {
      all: ['test/**/*.coffee'],
      options: {
        // require: ['should'],
        compilers: [ 'coffee:coffee-script' ],
        files: 'test/**/*.coffee',
        bail: true,
        reporter: 'spec'
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-bower');
  grunt.loadNpmTasks('grunt-browserify');

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-mocha-cli');

  grunt.registerTask('test', ['build', 'mochacli', 'jshint']);

  grunt.registerTask('build', ['copy', 'bower', 'browserify']);
  grunt.registerTask('serve', ['connect']);
  grunt.registerTask('default', ['build']);

};
<|endoftext|>


<commit_before>import types from '../constants'
import { routeActions } from 'react-router-redux'

const { FORM_SUBMIT_REQUEST, FORM_SUBMIT_SUCCESS, FORM_SUBMIT_FAILURE } = types

const submitRequest = () => {
    return {
        type: FORM_SUBMIT_REQUEST,
        submitted: false
    }
}

const submitSuccess = data => {
    return {
        type: FORM_SUBMIT_SUCCESS,
        submitted: true,
        data
    }
}

const submitFailure = error => {
    return {
        type: FORM_SUBMIT_FAILURE,
        submitted: false,
        error
    }
}

// const submitOrder = (data) => {
//     return dispatch => {
//         dispatch(submitRequest())
//         dispatch(routeActions.push('/order/form/submitting'))
//         setTimeout(() => {
//             simpleStorage.set('formdata', data)
//             dispatch(submitSuccess(data))
//             dispatch(routeActions.push('/home'))
//         }, 2000)
//     }
// }

let server = SERVER
if (process.env.SERVER) {
    server = process.env.SERVER
}

const submitOrder = (data) => {
    return dispatch => {
        let config = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                content: data
            })
        }
        dispatch(submitRequest())
        dispatch(routeActions.push('/order/form/submitting'))
        fetch(`${server}/orders`, config)
        .then(response => {
            if (response.status >= 200 && response.status < 300) {
                dispatch(submitSuccess())
                dispatch(routeActions.push('/home'))
                return Promise.resolve(response)
            }
            return Promise.reject(new Error(response.statusText))
        }).catch(error => {
            dispatch(submitFailure(error))
            dispatch(routeActions.push('/error'))
        })
    }
}

export const submitForm = (data, dispatch) => {
    dispatch(submitOrder(data))
}
<commit_msg>updated the action<commit_after>import types from '../constants'
import { routeActions } from 'react-router-redux'

const { FORM_SUBMIT_REQUEST, FORM_SUBMIT_SUCCESS, FORM_SUBMIT_FAILURE } = types

const submitRequest = () => {
    return {
        type: FORM_SUBMIT_REQUEST,
        submitted: false
    }
}

const submitSuccess = data => {
    return {
        type: FORM_SUBMIT_SUCCESS,
        submitted: true,
        data
    }
}

const submitFailure = error => {
    return {
        type: FORM_SUBMIT_FAILURE,
        submitted: false,
        error: error
    }
}

// const submitOrder = (data) => {
//     return dispatch => {
//         dispatch(submitRequest())
//         dispatch(routeActions.push('/order/form/submitting'))
//         setTimeout(() => {
//             simpleStorage.set('formdata', data)
//             dispatch(submitSuccess(data))
//             dispatch(routeActions.push('/home'))
//         }, 2000)
//     }
// }

let server = SERVER
if (process.env.SERVER) {
    server = process.env.SERVER
}

const submitOrder = (data) => {
    return dispatch => {
        let config = {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                content: data
            })
        }
        dispatch(submitRequest())
        dispatch(routeActions.push('/order/form/submitting'))
        fetch(`${server}/orders`, config)
        .then(response => {
            if (!(response.status >= 200 && response.status < 300)) {
                dispatch(submitFailure(response))
                return
            }
            dispatch(submitSuccess(response))
            dispatch(routeActions.push('/home'))
        })
        .catch(err => {
            dispatch(submitFailure(err))
        })
    }
}

export const submitForm = (data, dispatch) => {
    dispatch(submitOrder(data))
}
<|endoftext|>


<commit_before>var request = require('request');

var safari_browsers = [
	{
		browserName: 'safari',
		platform: 'OS X 10.10',
		version: '8.0'
	},
	{
		browserName: 'safari',
		platform: 'OS X 10.9',
		version: '7.0'
	}
];

var chrome_browsers = [
	{
		browserName: 'chrome',
		platform: 'OS X 10.10',
		version: '44.0'
	},
	{
		browserName: 'chrome',
		platform: 'Windows 10',
		version: '43.0'
	},
	{
		browserName: 'chrome',
		platform: 'Linux',
		version: '42.0'
	}
];

var firefox_browsers = [
	{
		browserName: 'firefox',
		platform: 'Windows 10',
		version: '40.0'
	},
	{
		browserName: 'firefox',
		platform: 'OS X 10.10',
		version: '39.0'
	},
	{
		browserName: 'firefox',
		platform: 'Linux',
		version: '38.0'
	}
];

var ios_browsers = [
	{
		browserName: 'iphone',
		deviceName: 'iPhone Simulator',
		deviceOrientation: 'portrait',
		platform: 'OS X 10.10',
		version: '8.4'
	}
];

var android_browsers = [
	{
		browserName: 'android',
		deviceName: 'Android Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '5.1'
	},
	{
		browserName: 'android',
		deviceName: 'Google Nexus 7 HD Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.4'
	},
	{
		browserName: 'android',
		deviceName: 'Google Nexus 7C Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.3'
	},
	{
		browserName: 'android',
		deviceName: 'LG Nexus 4 Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.2'
	},
	{
		browserName: 'android',
		deviceName: 'HTC One X Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.1'
	},
	{
		browserName: 'android',
		deviceName: 'HTC Evo 3D Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.0'
	}
];

var ie_browsers = [
	{
		browserName: 'internet explorer',
		platform: 'Windows 10',
		version: '11.0'
	},
	{
		browserName: 'internet explorer',
		platform: 'Windows 8.1',
		version: '11.0'
	},
	{
		browserName: 'internet explorer',
		platform: 'Windows 7',
		version: '10.0'
	}
];

var test_urls = [
	'http://0.0.0.0:9999/test/test.html',
	'http://0.0.0.0:9999/test/integration-test.html'
];

module.exports = function(grunt) {
	grunt.initConfig({
		'saucelabs-mocha': {
			all: {
				options: {
					username: 'branchmetrics',
					urls: test_urls,
					maxRetries: 3,
					testname: 'Web SDK Tests',
					browsers: [].concat(
						safari_browsers,
						chrome_browsers,
						firefox_browsers,
						android_browsers,
						ios_browsers,
						ie_browsers)
				}
			},
			options: {
				force: true
			}
		},
		connect: {
			server: {
				options: {
					port: 9999,
					base: ''
				}
			}
		}
	});

	// Loading dependencies
	for (var key in grunt.file.readJSON("package.json").devDependencies) {
		if (key !== "grunt" && key.indexOf("grunt") === 0) {
			grunt.loadNpmTasks(key);
		}
	}

	grunt.loadNpmTasks('grunt-saucelabs');
	grunt.loadNpmTasks('grunt-contrib-connect');

	grunt.registerTask('test', ['connect', 'saucelabs-mocha']);
};
<commit_msg>disable integration tests (temporarily)<commit_after>var request = require('request');

var safari_browsers = [
	{
		browserName: 'safari',
		platform: 'OS X 10.10',
		version: '8.0'
	},
	{
		browserName: 'safari',
		platform: 'OS X 10.9',
		version: '7.0'
	}
];

var chrome_browsers = [
	{
		browserName: 'chrome',
		platform: 'OS X 10.10',
		version: '44.0'
	},
	{
		browserName: 'chrome',
		platform: 'Windows 10',
		version: '43.0'
	},
	{
		browserName: 'chrome',
		platform: 'Linux',
		version: '42.0'
	}
];

var firefox_browsers = [
	{
		browserName: 'firefox',
		platform: 'Windows 10',
		version: '40.0'
	},
	{
		browserName: 'firefox',
		platform: 'OS X 10.10',
		version: '39.0'
	},
	{
		browserName: 'firefox',
		platform: 'Linux',
		version: '38.0'
	}
];

var ios_browsers = [
	{
		browserName: 'iphone',
		deviceName: 'iPhone Simulator',
		deviceOrientation: 'portrait',
		platform: 'OS X 10.10',
		version: '8.4'
	}
];

var android_browsers = [
	{
		browserName: 'android',
		deviceName: 'Android Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '5.1'
	},
	{
		browserName: 'android',
		deviceName: 'Google Nexus 7 HD Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.4'
	},
	{
		browserName: 'android',
		deviceName: 'Google Nexus 7C Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.3'
	},
	{
		browserName: 'android',
		deviceName: 'LG Nexus 4 Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.2'
	},
	{
		browserName: 'android',
		deviceName: 'HTC One X Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.1'
	},
	{
		browserName: 'android',
		deviceName: 'HTC Evo 3D Emulator',
		deviceOrientation: 'portrait',
		platform: 'Linux',
		version: '4.0'
	}
];

var ie_browsers = [
	{
		browserName: 'internet explorer',
		platform: 'Windows 10',
		version: '11.0'
	},
	{
		browserName: 'internet explorer',
		platform: 'Windows 8.1',
		version: '11.0'
	},
	{
		browserName: 'internet explorer',
		platform: 'Windows 7',
		version: '10.0'
	}
];

var test_urls = [
	'http://0.0.0.0:9999/test/test.html'
	// 'http://0.0.0.0:9999/test/test.html',
	// 'http://0.0.0.0:9999/test/integration-test.html'
];

module.exports = function(grunt) {
	grunt.initConfig({
		'saucelabs-mocha': {
			all: {
				options: {
					username: 'branchmetrics',
					urls: test_urls,
					maxRetries: 3,
					testname: 'Web SDK Tests',
					browsers: [].concat(
						safari_browsers,
						chrome_browsers,
						firefox_browsers,
						android_browsers,
						ios_browsers,
						ie_browsers)
				}
			},
			options: {
				force: true
			}
		},
		connect: {
			server: {
				options: {
					port: 9999,
					base: ''
				}
			}
		}
	});

	// Loading dependencies
	for (var key in grunt.file.readJSON("package.json").devDependencies) {
		if (key !== "grunt" && key.indexOf("grunt") === 0) {
			grunt.loadNpmTasks(key);
		}
	}

	grunt.loadNpmTasks('grunt-saucelabs');
	grunt.loadNpmTasks('grunt-contrib-connect');

	grunt.registerTask('test', ['connect', 'saucelabs-mocha']);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
  "use strict";

  var qStr = "";
  var scrub = "";
  if (grunt.option('scrub')){
    scrub = 'scrub=' + grunt.option('scrub');
  }
  var local = "";
  if (grunt.option('local')){
    local= 'local=true';
  }

  if (scrub !== "" || local !== ""){
    qStr += "?" + scrub + "&" + local;
  }

  var expressArgs = [];
  if (grunt.option('rec')){
    expressArgs.push('rec');
  }

  require('load-grunt-tasks')(grunt);
  // Project configuration.
  grunt.initConfig({
    // This line makes your node configurations available for use
    pkg: grunt.file.readJSON('package.json'),

    jshint: {
      myFiles: ['Gruntfile.js',
                'www/js/app.js',
                'www/js/**/*.js',],
      test: [
        'tests/**/*.js',
        '!tests/coverage/**/*.*'
        ]
    },

    compress: {
      options :{
        archive: '<%= pkg.name %>-<%= pkg.version %>.zip'
      },
      dev: {
        src: ['www/**',
              // don't include  files that are needed only for local dev/test
              '!www/index.html',
              '!www/index.tpl.html',
              '!www/js/services/**',
              '!www/js/controllers/**',
              '!www/**/*.log'],
        expand: true
      },
      prod: {
        files :[
          {
            src: [
              'www/**',
              'www/lib/js/ng-cordova.min.js',
              // don't include js that we have minified
              '!www/js/*',
              // add any libs that you do want included here.
              '!www/index.html',
              '!www/index.tpl.html',
              '!www/js/services/**',
              '!www/js/controllers/**',
              '!www/**/*.log'],
            expand: true
          },
          {
            flatten:true,
            expand: true,
            src: ['dest/js/*'],
            dest : 'www/js'
          }
        ]
      }
    },

    uglify : {
      prod: {
        options: {
          mangle: false,
          drop_console: true,
          banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
            '<%= grunt.template.today("yyyy-mm-dd HH:MM:ss") %>*/\n' +
            '/* Copyright <%= grunt.template.today("yyyy") %> MobileCaddy Ltd */\n',
        },
        files: [{
          flatten: true,
          expand: true,
          src:    [
            'www/js/*.js',
            // don't include lib files that are needed only for local dev/test
            '!www/lib/js/**.js'
            ],
          dest:   'dest/js'
        }]
      }
    },

    connect: {
      server: {
        options: {
          port: 3030,
          livereload: true,
          open: "http://localhost:3030/www" + qStr
        }
      }
    },

    express: {
      options: {
        // Override defaults here
      },
      dev: {
        options: {
          args: expressArgs,
          script: 'node_modules/mobilecaddy-codeflow/js/cors-server.js'
        }
      }
    },

    sass: {
      dist: {
        options: {
          style: 'compact',
          sourcemap: 'none'
        },
        files: {
          'www/css/app.css': 'scss/app.scss'
        }
      }
    },

    watch: {
      set1: {
        files: ['app.js',
                'www/js/**/*.js',
                '!www/js/services.js',
                '!www/js/controllers.js',
                'package.json'],
        tasks: ['dev']
      },
      set2: {
        files: [ 'www/templates/*.html'],
        tasks: ['compress:dev']
      },
      set3: {
        files: [ 'scss/*.scss'],
        tasks: ['sass']
      },
      set4: {
        files: [ 'www/css/*.css'],
        tasks: ['compress:dev'],
        options: {
          livereload: true,
        }
      },
      set5: {
        files: [ 'tests/**/*.js'],
        tasks: ['jshint:test']
      },
      express: {
        files: ['cors/cors-server.js'],
        tasks:  [ 'express:dev' ]
      }
    },

    concat: {
        options: {
          separator: '\n',
        },
        services: {
          src:  ['www/js/services/service.module.js', 'www/js/services/*.js'],
          dest: 'www/js/services.js',
        },
        controllers: {
          src:  ['www/js/controllers/controllers.module.js', 'www/js/controllers/*.js'],
          dest: 'www/js/controllers.js',
        },
    },

    copy: {
      devsetup: (function(){
        // node_modules structure is flat from v5.0.0 onwards
        var forceJSPath = (process.version < "v5.0.0") ?
          'node_modules/mobilecaddy-codeflow/node_modules/forcejs/oauthcallback.html' :
          'node_modules/forcejs/oauthcallback.html';
        return {
          files: [
            {
              expand: true,
              flatten: true,
              src: ['node_modules/ionic-sdk/release/js/ionic.bundle.min.js',
                    'node_modules/ng-cordova/dist/ng-cordova.min.js'],
              dest: 'www/lib/js',
              filter: 'isFile'
            },
            // Ionic scss
            {
              expand: true,
              cwd: 'node_modules/ionic-sdk/scss/',
              src: ['**'],
              dest: 'scss/ionic'
            },
            // Ionic fonts
            {
              expand: true,
              cwd: 'node_modules/ionic-sdk/release/fonts/',
              src: ['**'],
              dest: 'www/fonts'
            },
            {
              src: [forceJSPath],
              dest: 'oauthcallback.html'
            },
            {
              expand: true,
              cwd: 'node_modules/mobilecaddy-codeflow/codeflow-app/',
              src: ['**'],
              dest: 'codeflow'
            }
          ]
        };
      }())
    },

    replace: {
      ioniconsVsnRm: {
        src: ['scss/ionic/ionicons/_ionicons-font.scss'],
        dest: 'scss/ionic/ionicons/_ionicons-font.scss',
        replacements: [{
          from: '?v=#{$ionicons-version}',
          to: ''
        },{
          from: '.svg',
          to: '.SVG'
        },{
          from: '.ttf',
          to: '.TTF'
        },{
          from: '.woff',
          to: '.WOFF'
        },{
          from: '.eot',
          to: '.EOT'
        }]
      },
      ngCordovaMocks: {
        src: ['node_modules/ng-cordova/dist/ng-cordova-mocks.js'],
        dest: 'tmp/ng-cordova-mocks.js',
        replacements: [{
          from: 'ngCordovaMocks',
          to: 'ngCordova'
        }]
      },
      node5: (function(){
        // node_modules structure is flat from v5.0.0 onwards
        if (process.version < "v5.0.0") {
          return {};
        } else {
          return {
            src: ['www/index.html', 'www/index.tpl.html', 'codeflow/index.html', 'tests/my.conf.js'],
            overwrite: true,
            replacements: [{
              from: /node_modules\/.*\/node_modules\//g,
              to: function (matchedWord, index, fullText, regexMatches) {
                return 'node_modules/';
              }
            }]
          };
        }
      }())
    },

    rename: {
      ioniconeot: {
        src: 'www/fonts/ionicons.eot',
        dest: 'www/fonts/ionicons.EOT'
      },
      ioniconsvg: {
        src: 'www/fonts/ionicons.svg',
        dest: 'www/fonts/ionicons.SVG'
      },
      ioniconttf: {
        src: 'www/fonts/ionicons.ttf',
        dest: 'www/fonts/ionicons.TTF'
      },
      ioniconwoff: {
        src: 'www/fonts/ionicons.woff',
        dest: 'www/fonts/ionicons.WOFF'
        }
    },

    includeSource: {
      options: {
        basePath: 'www',
        templates: {
          html: {
            js: '<script src="{filePath}"></script>',
          }
        },
      },
      myTarget: {
        files: {
          'www/index.html': 'www/index.tpl.html'
        }
      }
    },

    karma: {
      unit: {
        configFile: 'tests/my.conf.js'
      }
    }

  });
  // Each plugin must be loaded following this pattern
  grunt.registerTask('devsetup', ['copy:devsetup', 'sass', 'includeSource', 'rename', 'replace']);
  grunt.registerTask('serve', ['connect', 'express:dev', 'watch']);
  grunt.registerTask('dev', ['jshint:myFiles', 'includeSource', 'concat', 'compress:dev']);
  grunt.registerTask('unit-test', ['karma']);
  grunt.registerTask('prod', ['jshint:myFiles', 'uglify', 'compress:prod']);
};
<commit_msg>Moving sass task to last in queue for _grunt devsetup_<commit_after>module.exports = function(grunt) {
  "use strict";

  var qStr = "";
  var scrub = "";
  if (grunt.option('scrub')){
    scrub = 'scrub=' + grunt.option('scrub');
  }
  var local = "";
  if (grunt.option('local')){
    local= 'local=true';
  }

  if (scrub !== "" || local !== ""){
    qStr += "?" + scrub + "&" + local;
  }

  var expressArgs = [];
  if (grunt.option('rec')){
    expressArgs.push('rec');
  }

  require('load-grunt-tasks')(grunt);
  // Project configuration.
  grunt.initConfig({
    // This line makes your node configurations available for use
    pkg: grunt.file.readJSON('package.json'),

    jshint: {
      myFiles: ['Gruntfile.js',
                'www/js/app.js',
                'www/js/**/*.js',],
      test: [
        'tests/**/*.js',
        '!tests/coverage/**/*.*'
        ]
    },

    compress: {
      options :{
        archive: '<%= pkg.name %>-<%= pkg.version %>.zip'
      },
      dev: {
        src: ['www/**',
              // don't include  files that are needed only for local dev/test
              '!www/index.html',
              '!www/index.tpl.html',
              '!www/js/services/**',
              '!www/js/controllers/**',
              '!www/**/*.log'],
        expand: true
      },
      prod: {
        files :[
          {
            src: [
              'www/**',
              'www/lib/js/ng-cordova.min.js',
              // don't include js that we have minified
              '!www/js/*',
              // add any libs that you do want included here.
              '!www/index.html',
              '!www/index.tpl.html',
              '!www/js/services/**',
              '!www/js/controllers/**',
              '!www/**/*.log'],
            expand: true
          },
          {
            flatten:true,
            expand: true,
            src: ['dest/js/*'],
            dest : 'www/js'
          }
        ]
      }
    },

    uglify : {
      prod: {
        options: {
          mangle: false,
          drop_console: true,
          banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
            '<%= grunt.template.today("yyyy-mm-dd HH:MM:ss") %>*/\n' +
            '/* Copyright <%= grunt.template.today("yyyy") %> MobileCaddy Ltd */\n',
        },
        files: [{
          flatten: true,
          expand: true,
          src:    [
            'www/js/*.js',
            // don't include lib files that are needed only for local dev/test
            '!www/lib/js/**.js'
            ],
          dest:   'dest/js'
        }]
      }
    },

    connect: {
      server: {
        options: {
          port: 3030,
          livereload: true,
          open: "http://localhost:3030/www" + qStr
        }
      }
    },

    express: {
      options: {
        // Override defaults here
      },
      dev: {
        options: {
          args: expressArgs,
          script: 'node_modules/mobilecaddy-codeflow/js/cors-server.js'
        }
      }
    },

    sass: {
      dist: {
        options: {
          style: 'compact',
          sourcemap: 'none'
        },
        files: {
          'www/css/app.css': 'scss/app.scss'
        }
      }
    },

    watch: {
      set1: {
        files: ['app.js',
                'www/js/**/*.js',
                '!www/js/services.js',
                '!www/js/controllers.js',
                'package.json'],
        tasks: ['dev']
      },
      set2: {
        files: [ 'www/templates/*.html'],
        tasks: ['compress:dev']
      },
      set3: {
        files: [ 'scss/*.scss'],
        tasks: ['sass']
      },
      set4: {
        files: [ 'www/css/*.css'],
        tasks: ['compress:dev'],
        options: {
          livereload: true,
        }
      },
      set5: {
        files: [ 'tests/**/*.js'],
        tasks: ['jshint:test']
      },
      express: {
        files: ['cors/cors-server.js'],
        tasks:  [ 'express:dev' ]
      }
    },

    concat: {
        options: {
          separator: '\n',
        },
        services: {
          src:  ['www/js/services/service.module.js', 'www/js/services/*.js'],
          dest: 'www/js/services.js',
        },
        controllers: {
          src:  ['www/js/controllers/controllers.module.js', 'www/js/controllers/*.js'],
          dest: 'www/js/controllers.js',
        },
    },

    copy: {
      devsetup: (function(){
        // node_modules structure is flat from v5.0.0 onwards
        var forceJSPath = (process.version < "v5.0.0") ?
          'node_modules/mobilecaddy-codeflow/node_modules/forcejs/oauthcallback.html' :
          'node_modules/forcejs/oauthcallback.html';
        return {
          files: [
            {
              expand: true,
              flatten: true,
              src: ['node_modules/ionic-sdk/release/js/ionic.bundle.min.js',
                    'node_modules/ng-cordova/dist/ng-cordova.min.js'],
              dest: 'www/lib/js',
              filter: 'isFile'
            },
            // Ionic scss
            {
              expand: true,
              cwd: 'node_modules/ionic-sdk/scss/',
              src: ['**'],
              dest: 'scss/ionic'
            },
            // Ionic fonts
            {
              expand: true,
              cwd: 'node_modules/ionic-sdk/release/fonts/',
              src: ['**'],
              dest: 'www/fonts'
            },
            {
              src: [forceJSPath],
              dest: 'oauthcallback.html'
            },
            {
              expand: true,
              cwd: 'node_modules/mobilecaddy-codeflow/codeflow-app/',
              src: ['**'],
              dest: 'codeflow'
            }
          ]
        };
      }())
    },

    replace: {
      ioniconsVsnRm: {
        src: ['scss/ionic/ionicons/_ionicons-font.scss'],
        dest: 'scss/ionic/ionicons/_ionicons-font.scss',
        replacements: [{
          from: '?v=#{$ionicons-version}',
          to: ''
        },{
          from: '.svg',
          to: '.SVG'
        },{
          from: '.ttf',
          to: '.TTF'
        },{
          from: '.woff',
          to: '.WOFF'
        },{
          from: '.eot',
          to: '.EOT'
        }]
      },
      ngCordovaMocks: {
        src: ['node_modules/ng-cordova/dist/ng-cordova-mocks.js'],
        dest: 'tmp/ng-cordova-mocks.js',
        replacements: [{
          from: 'ngCordovaMocks',
          to: 'ngCordova'
        }]
      },
      node5: (function(){
        // node_modules structure is flat from v5.0.0 onwards
        if (process.version < "v5.0.0") {
          return {};
        } else {
          return {
            src: ['www/index.html', 'www/index.tpl.html', 'codeflow/index.html', 'tests/my.conf.js'],
            overwrite: true,
            replacements: [{
              from: /node_modules\/.*\/node_modules\//g,
              to: function (matchedWord, index, fullText, regexMatches) {
                return 'node_modules/';
              }
            }]
          };
        }
      }())
    },

    rename: {
      ioniconeot: {
        src: 'www/fonts/ionicons.eot',
        dest: 'www/fonts/ionicons.EOT'
      },
      ioniconsvg: {
        src: 'www/fonts/ionicons.svg',
        dest: 'www/fonts/ionicons.SVG'
      },
      ioniconttf: {
        src: 'www/fonts/ionicons.ttf',
        dest: 'www/fonts/ionicons.TTF'
      },
      ioniconwoff: {
        src: 'www/fonts/ionicons.woff',
        dest: 'www/fonts/ionicons.WOFF'
        }
    },

    includeSource: {
      options: {
        basePath: 'www',
        templates: {
          html: {
            js: '<script src="{filePath}"></script>',
          }
        },
      },
      myTarget: {
        files: {
          'www/index.html': 'www/index.tpl.html'
        }
      }
    },

    karma: {
      unit: {
        configFile: 'tests/my.conf.js'
      }
    }

  });
  // Each plugin must be loaded following this pattern
  grunt.registerTask('devsetup', ['copy:devsetup', 'includeSource', 'rename', 'replace', 'sass']);
  grunt.registerTask('serve', ['connect', 'express:dev', 'watch']);
  grunt.registerTask('dev', ['jshint:myFiles', 'includeSource', 'concat', 'compress:dev']);
  grunt.registerTask('unit-test', ['karma']);
  grunt.registerTask('prod', ['jshint:myFiles', 'uglify', 'compress:prod']);
};
<|endoftext|>


<commit_before>'use strict'
module.exports = update

const Bluebird = require('bluebird')
const qw = require('qw')
const syncTOML = require('@iarna/toml')

const fetch = use('fetch')
const Fic = use('fic')
const ficInflate = use('fic-inflate')
const filenameize = use('filenameize')
const fs = use('fs-promises')
const progress = use('progress')
const promisify = use('promisify')
const TOML = use('toml')
const moment = require('moment')
const uniq = require('lodash.uniq')

function update (args) {
  const fetchOpts = {
    cacheBreak: !args.cache,
    noNetwork: !args.network,
    maxConcurrency: args.concurrency,
    requestsPerSecond: args['requests-per-second'],
    timeout: 10000
  }
  const fetchAndSpin = fetch.withOpts(fetchOpts).wrapWith(progress.spinWhileAnd)
  if (args.xf_user) fetchAndSpin.setGlobalCookie(`xf_user=${args.xf_user}`)

  return Bluebird.map(args.fic, updateFic(fetchAndSpin, args), {concurrency: 10})
    .reduce((exit, result) => result != null ? result : exit)
    .then(exit => exit > 0 ? 0 : 1) // error if nothing updated
}

function readFic (fic) {
  return fs.readFile(fic).then(toml => Fic.fromJSON(syncTOML.parse(toml)))
}

function updateFic (fetch, args) {
  const addNone = args['add-none']
  const addAll = args['add-all']
  const add = addNone ? 'none' : addAll ? 'all' : 'new'
  let fromThreadmarks = !args.scrape || args['and-fetch']
  let fromScrape = args.scrape || args['and-scrape']
  const refresh = args['refresh']
  let fast = args.fast

  return ficFile => {
    return Bluebird.try(() => {
      const existingFic = readFic(ficFile)
      let newFic = fetchLatestVersionWithoutInflate(fetch, existingFic, fromThreadmarks, fromScrape)
      if (fast) {
        return Bluebird.join(existingFic, newFic, (existingFic, newFic) => {
          const lastExisting = existingFic.chapters.slice(-1)[0] || existingFic
          const lastNew = newFic.chapters.slice(-1)[0] || newFic
          if (lastExisting === lastNew || (lastExisting && lastNew && createdDate(lastExisting).isAfter(createdDate(lastNew)))) return
          newFic = ficInflate(newFic, fetch.withOpts({cacheBreak: false}))
          return doMerge()
        })
      } else {
        return doMerge()
      }
      function doMerge () {
        return mergeFic(existingFic, newFic, add).then(changes => {
          const inflatedFic = ficInflate(existingFic, fetch.withOpts({cacheBreak: false}))
          return writeUpdatedFic(ficFile, inflatedFic, refreshMetadata(inflatedFic, changes), refresh)
        })
      }
    }).catch(ex => {
      process.emit('warn', `Skipping ${ficFile}:`, ex)
    })
  }
}

function writeUpdatedFic (ficFile, existingFic, changes, forceSave) {
  return Bluebird.resolve(changes).then(changes => {
    if (!changes.length && !forceSave) return null
    return fs.writeFile(ficFile, TOML.stringify(existingFic)).then(() => {
      progress.output(`${ficFile}\n`)
      if (changes.length) progress.output(`    ${changes.join('\n    ')} \n`)
      return changes.refresh ? 1 : null
    })
  })
}

var fetchLatestVersion = promisify.args((fetch, existingFic, fromThreadmarks, fromScrape) => {
  const newFic = fetchLatestVersionWithoutInflate(fetch, existingFic, fromThreadmarks, fromScrape)

  return ficInflate(newFic, fetch.withOpts({cacheBreak: false}))
})

var fetchLatestVersionWithoutInflate = promisify.args((fetch, existingFic, fromThreadmarks, fromScrape) => {
  const updateFrom = existingFic.updateWith()
  let thisFromThreadmarks = (!existingFic.scrapeMeta && fromThreadmarks) || existingFic.fetchMeta
  let thisFromScrape = fromScrape || existingFic.scrapeMeta

  function getFic (fetch) {
    if (thisFromThreadmarks && thisFromScrape) {
      return Fic.fromUrlAndScrape(fetch, updateFrom)
    } else if (thisFromThreadmarks) {
      return Fic.fromOnlyUrl(fetch, updateFrom)
    } else {
      return Fic.scrapeFromUrl(fetch, updateFrom)
    }
  }

  // Fetch the fic from cache first, which ensures we get any cookies
  // associated with it, THEN fetch it w/o the cache to get updates.
  return getFic(fetch.withOpts({cacheBreak: false})).then(()=> getFic(fetch))
})

function createdDate (chapOrFic) {
  return moment(chapOrFic.created || chapOrFic.modified)
}

var mergeFic = promisify.args(function mergeFic (existingFic, newFic, add) {
  const changes = []
  const toAdd = []

  if (add !== 'none') {
    const types = uniq(newFic.chapters.map(ch => ch.type))
    types.forEach(type => {
      const latestExisting = existingFic.chapters.filter(ch => ch.type === type).concat(existingFic.fics).map(createdDate).reduce((aa, bb) => {
        return aa > bb ? aa : bb
      }, new Date(0))
      const chapters = newFic.chapters.filter(ch => ch.type === type)
      const newestIndex = chapters.length - 1
      if (chapters[newestIndex].created || chapters[newestIndex].modified) {
        for (let newChapter of chapters) {
          if (existingFic.chapterExists(newChapter.link) || existingFic.chapterExists(newChapter.fetchFrom)) {
            continue
          }
          const created = newChapter.created || newChapter.modified
          if (add === 'all' || createdDate(newChapter).isAfter(latestExisting)) {
            toAdd.push(newChapter)
          }
        }
      } else {
        for (let ii = newestIndex; ii >= 0; --ii) {
          const newChapter = chapters[ii]
          if (existingFic.chapterExists(newChapter.link) || existingFic.chapterExists(newChapter.fetchFrom)) {
            if (add === 'all') { continue } else { break }
          }
          toAdd.unshift(newChapter)
        }
      }
    })
  }

  if (existingFic.description == null && newFic.description != null) {
    existingFic.description = newFic.description
    changes.push(`${existingFic.title}: Set fic description to ${newFic.description}`)
  }
  if (existingFic.tags == null && newFic.tags != null && newFic.tags.length) {
    existingFic.tags = newFic.tags
    changes.push(`${existingFic.title}: Set fic tags to ${newFic.tags.join(', ')}`)
  }
  for (let prop of qw`publisher author authorUrl updateFrom link title`) {
    if (existingFic[prop] == null && newFic[prop] != null && (!existingFic.parent || existingFic.parent[prop] !== newFic[prop])) {
      existingFic[prop] = newFic[prop]
      changes.push(`${existingFic.title}: Set fic ${prop} to ${existingFic[prop]}`)
    }
  }

  existingFic.chapters.push.apply(existingFic.chapters, toAdd)
  existingFic.chapters.sort()

  if (toAdd.length) {
    changes.push(`${existingFic.title}: Added ${toAdd.length} new chapters`)
    changes.refresh = true
  }

  const fics = [existingFic].concat(existingFic.fics)
  for (let fic of fics) {
    // Find any chapters with created dates and update them if need be.
    for (let chapter of fic.chapters) {
      const match = newFic.chapters.filter(andChapterEquals(chapter))
      for (let newChapter of match) {
        if (chapter.type === 'chapter' && newChapter.type !== chapter.type) {
          changes.push(`${fic.title}: Updated type for chapter "${newChapter.name}" from ${chapter.type} to ${newChapter.type}`)
          chapter.type = newChapter.type
        }
        if (isDate(newChapter.created) && !dateEqual(newChapter.created, chapter.created)) {
          changes.push(`${fic.title}: Updated creation date for chapter "${newChapter.name}" from ${chapter.created} to ${newChapter.created}`)
          chapter.created = newChapter.created
        }
        if (isDate(newChapter.modified) && !dateEqual(newChapter.modified, chapter.modified)) {
          changes.push(`${fic.title}: Updated modification date for chapter "${newChapter.name}" from ${chapter.modified} to ${newChapter.modified}`)
          chapter.modified = newChapter.modified
        }
        for (let prop of qw`name link fetchFrom author authorUrl tags words`) {
          if (chapter[prop] == null && newChapter[prop] != null) {
            if (newChapter[prop] != fic[prop]) {
              chapter[prop] = newChapter[prop]
              changes.push(`${fic.title}: Set ${prop} for chapter "${newChapter.name}" to ${chapter[prop]}`)
            }
          }
        }
      }
    }
  }
  return changes
})

var refreshMetadata = promisify.args(function mergeFic (existingFic, changes) {
  const fics = [existingFic].concat(existingFic.fics)

  for (let fic of fics) {
    let now = moment()
    let then = moment(0)
    let created = fic.chapters.filter(c => c.type === 'chapter' && (c.created || c.modified)).reduce((ficCreated, chapter) => {
      return ficCreated < moment(chapter.created || chapter.modified) ? ficCreated : moment(chapter.created || chapter.modified)
    }, now)
    if (isDate(created) && (created !== now && (!isDate(fic.created) || !dateEqual(created, fic.created)))) {
      changes.push(`${fic.title}: Updated fic publish time from ${fic.created} to ${created} (from earliest chapter)`)
      fic.created = created
    }

    let modified = fic.chapters.filter(c => c.type === 'chapter' && (c.modified || c.created)).reduce((ficModified, chapter) => ficModified > moment(chapter.modified||chapter.created) ? ficModified : moment(chapter.modified||chapter.created), then)
    if (isDate(modified) && (modified !== then && (!isDate(fic.modified) || !dateEqual(modified, fic.modified)))) {
      changes.push(`${fic.title}: Updated fic last update time from ${fic.modified} to ${modified} (from latest chapter)`)
      fic.modified = modified
    }
  }
  if (existingFic.chapters.length === 0) {
    let created = existingFic.fics.filter(f => f.created).reduce((ficCreated, subfic) => ficCreated < moment(subfic.created) ? ficCreated : moment(subfic.created), moment(existingFic.created))
    if (isDate(created) && (!dateEqual(existingFic.created, created))) {
      changes.push(`${existingFic.title}: Updated fic publish time from ${existingFic.created} to ${created} (from earliest subfic)`)
      existingFic.created = created
    }
    let modified = existingFic.fics.filter(f => f.modified || f.created).reduce((ficModified, subfic) => ficModified > moment(subfic.modified||subfic.created) ? ficModified : moment(subfic.modified||subfic.created), moment(existingFic.modified))
    if (isDate(modified) && (!dateEqual(existingFic.modified, modified))) {
      changes.push(`${existingFic.title}: Updated fic last update time from ${existingFic.modified} to ${modified} (from latest subfic)`)
      existingFic.modified = modified
    }
  }
  return changes
})

function andChapterEquals (chapterA) {
  return chapterB => chapterEqual(chapterA, chapterB)
}

function chapterEqual (chapterA, chapterB) {
  return (chapterA.link && chapterB.link && chapterA.link === chapterB.link) ||
         (chapterA.fetchFrom && chapterB.fetchFrom && chapterA.fetchFrom === chapterB.fetchFrom)
}

function dateEqual (dateA, dateB) {
  return moment(dateA).isSame(dateB)
}

function isDate (date) {
  if (date == null) return false
  if (isNaN(date)) return false
  return date instanceof Date || date instanceof moment
}
<commit_msg>ff-update: handle fics with missing chapter upate dates<commit_after>'use strict'
module.exports = update

const Bluebird = require('bluebird')
const qw = require('qw')
const syncTOML = require('@iarna/toml')

const fetch = use('fetch')
const Fic = use('fic')
const ficInflate = use('fic-inflate')
const filenameize = use('filenameize')
const fs = use('fs-promises')
const progress = use('progress')
const promisify = use('promisify')
const TOML = use('toml')
const moment = require('moment')
const uniq = require('lodash.uniq')

function update (args) {
  const fetchOpts = {
    cacheBreak: !args.cache,
    noNetwork: !args.network,
    maxConcurrency: args.concurrency,
    requestsPerSecond: args['requests-per-second'],
    timeout: 10000
  }
  const fetchAndSpin = fetch.withOpts(fetchOpts).wrapWith(progress.spinWhileAnd)
  if (args.xf_user) fetchAndSpin.setGlobalCookie(`xf_user=${args.xf_user}`)

  return Bluebird.map(args.fic, updateFic(fetchAndSpin, args), {concurrency: 10})
    .reduce((exit, result) => result != null ? result : exit)
    .then(exit => exit > 0 ? 0 : 1) // error if nothing updated
}

function readFic (fic) {
  return fs.readFile(fic).then(toml => Fic.fromJSON(syncTOML.parse(toml)))
}

function updateFic (fetch, args) {
  const addNone = args['add-none']
  const addAll = args['add-all']
  const add = addNone ? 'none' : addAll ? 'all' : 'new'
  let fromThreadmarks = !args.scrape || args['and-fetch']
  let fromScrape = args.scrape || args['and-scrape']
  const refresh = args['refresh']
  let fast = args.fast

  return ficFile => {
    return Bluebird.try(() => {
      const existingFic = readFic(ficFile)
      let newFic = fetchLatestVersionWithoutInflate(fetch, existingFic, fromThreadmarks, fromScrape)
      if (fast) {
        return Bluebird.join(existingFic, newFic, (existingFic, newFic) => {
          const lastExisting = existingFic.chapters.slice(-1)[0] || existingFic
          const lastNew = newFic.chapters.slice(-1)[0] || newFic
          if (lastExisting === lastNew || (lastExisting && lastNew && createdDate(lastExisting).isAfter(createdDate(lastNew)))) return
          newFic = ficInflate(newFic, fetch.withOpts({cacheBreak: false}))
          return doMerge()
        })
      } else {
        return doMerge()
      }
      function doMerge () {
        return mergeFic(existingFic, newFic, add).then(changes => {
          const inflatedFic = ficInflate(existingFic, fetch.withOpts({cacheBreak: false}))
          return writeUpdatedFic(ficFile, inflatedFic, refreshMetadata(inflatedFic, changes), refresh)
        })
      }
    }).catch(ex => {
      process.emit('warn', `Skipping ${ficFile}:`, ex)
    })
  }
}

function writeUpdatedFic (ficFile, existingFic, changes, forceSave) {
  return Bluebird.resolve(changes).then(changes => {
    if (!changes.length && !forceSave) return null
    return fs.writeFile(ficFile, TOML.stringify(existingFic)).then(() => {
      progress.output(`${ficFile}\n`)
      if (changes.length) progress.output(`    ${changes.join('\n    ')} \n`)
      return changes.refresh ? 1 : null
    })
  })
}

var fetchLatestVersion = promisify.args((fetch, existingFic, fromThreadmarks, fromScrape) => {
  const newFic = fetchLatestVersionWithoutInflate(fetch, existingFic, fromThreadmarks, fromScrape)

  return ficInflate(newFic, fetch.withOpts({cacheBreak: false}))
})

var fetchLatestVersionWithoutInflate = promisify.args((fetch, existingFic, fromThreadmarks, fromScrape) => {
  const updateFrom = existingFic.updateWith()
  let thisFromThreadmarks = (!existingFic.scrapeMeta && fromThreadmarks) || existingFic.fetchMeta
  let thisFromScrape = fromScrape || existingFic.scrapeMeta

  function getFic (fetch) {
    if (thisFromThreadmarks && thisFromScrape) {
      return Fic.fromUrlAndScrape(fetch, updateFrom)
    } else if (thisFromThreadmarks) {
      return Fic.fromOnlyUrl(fetch, updateFrom)
    } else {
      return Fic.scrapeFromUrl(fetch, updateFrom)
    }
  }

  // Fetch the fic from cache first, which ensures we get any cookies
  // associated with it, THEN fetch it w/o the cache to get updates.
  return getFic(fetch.withOpts({cacheBreak: false})).then(()=> getFic(fetch))
})

function createdDate (chapOrFic) {
  return moment(chapOrFic.created || chapOrFic.modified)
}

var mergeFic = promisify.args(function mergeFic (existingFic, newFic, add) {
  const changes = []
  const toAdd = []

  if (add !== 'none') {
    const types = uniq(newFic.chapters.map(ch => ch.type))
    types.forEach(type => {
      const latestExisting = existingFic
        .chapters
        .filter(ch => ch.type === type)
        .concat(existingFic.fics)
        .filter(c => c.created || c.modified)
        .map(createdDate)
        .reduce((aa, bb) => aa > bb ? aa : bb, new Date(0))
      const chapters = newFic.chapters.filter(ch => ch.type === type)
      const newestIndex = chapters.length - 1
      if (chapters[newestIndex].created || chapters[newestIndex].modified) {
        for (let newChapter of chapters) {
          if (existingFic.chapterExists(newChapter.link) || existingFic.chapterExists(newChapter.fetchFrom)) {
            continue
          }
          const created = newChapter.created || newChapter.modified
          if (add === 'all' || createdDate(newChapter).isAfter(latestExisting)) {
            toAdd.push(newChapter)
          }
        }
      } else {
        for (let ii = newestIndex; ii >= 0; --ii) {
          const newChapter = chapters[ii]
          if (existingFic.chapterExists(newChapter.link) || existingFic.chapterExists(newChapter.fetchFrom)) {
            if (add === 'all') { continue } else { break }
          }
          toAdd.unshift(newChapter)
        }
      }
    })
  }

  if (existingFic.description == null && newFic.description != null) {
    existingFic.description = newFic.description
    changes.push(`${existingFic.title}: Set fic description to ${newFic.description}`)
  }
  if (existingFic.tags == null && newFic.tags != null && newFic.tags.length) {
    existingFic.tags = newFic.tags
    changes.push(`${existingFic.title}: Set fic tags to ${newFic.tags.join(', ')}`)
  }
  for (let prop of qw`publisher author authorUrl updateFrom link title`) {
    if (existingFic[prop] == null && newFic[prop] != null && (!existingFic.parent || existingFic.parent[prop] !== newFic[prop])) {
      existingFic[prop] = newFic[prop]
      changes.push(`${existingFic.title}: Set fic ${prop} to ${existingFic[prop]}`)
    }
  }

  existingFic.chapters.push.apply(existingFic.chapters, toAdd)
  existingFic.chapters.sort()

  if (toAdd.length) {
    changes.push(`${existingFic.title}: Added ${toAdd.length} new chapters`)
    changes.refresh = true
  }

  const fics = [existingFic].concat(existingFic.fics)
  for (let fic of fics) {
    // Find any chapters with created dates and update them if need be.
    for (let chapter of fic.chapters) {
      const match = newFic.chapters.filter(andChapterEquals(chapter))
      for (let newChapter of match) {
        if (chapter.type === 'chapter' && newChapter.type !== chapter.type) {
          changes.push(`${fic.title}: Updated type for chapter "${newChapter.name}" from ${chapter.type} to ${newChapter.type}`)
          chapter.type = newChapter.type
        }
        if (isDate(newChapter.created) && !dateEqual(newChapter.created, chapter.created)) {
          changes.push(`${fic.title}: Updated creation date for chapter "${newChapter.name}" from ${chapter.created} to ${newChapter.created}`)
          chapter.created = newChapter.created
        }
        if (isDate(newChapter.modified) && !dateEqual(newChapter.modified, chapter.modified)) {
          changes.push(`${fic.title}: Updated modification date for chapter "${newChapter.name}" from ${chapter.modified} to ${newChapter.modified}`)
          chapter.modified = newChapter.modified
        }
        for (let prop of qw`name link fetchFrom author authorUrl tags words`) {
          if (chapter[prop] == null && newChapter[prop] != null) {
            if (newChapter[prop] != fic[prop]) {
              chapter[prop] = newChapter[prop]
              changes.push(`${fic.title}: Set ${prop} for chapter "${newChapter.name}" to ${chapter[prop]}`)
            }
          }
        }
      }
    }
  }
  return changes
})

var refreshMetadata = promisify.args(function mergeFic (existingFic, changes) {
  const fics = [existingFic].concat(existingFic.fics)

  for (let fic of fics) {
    let now = moment()
    let then = moment(0)
    let created = fic.chapters.filter(c => c.type === 'chapter' && (c.created || c.modified)).reduce((ficCreated, chapter) => {
      return ficCreated < moment(chapter.created || chapter.modified) ? ficCreated : moment(chapter.created || chapter.modified)
    }, now)
    if (isDate(created) && (created !== now && (!isDate(fic.created) || !dateEqual(created, fic.created)))) {
      changes.push(`${fic.title}: Updated fic publish time from ${fic.created} to ${created} (from earliest chapter)`)
      fic.created = created
    }

    let modified = fic.chapters.filter(c => c.type === 'chapter' && (c.modified || c.created)).reduce((ficModified, chapter) => ficModified > moment(chapter.modified||chapter.created) ? ficModified : moment(chapter.modified||chapter.created), then)
    if (isDate(modified) && (modified !== then && (!isDate(fic.modified) || !dateEqual(modified, fic.modified)))) {
      changes.push(`${fic.title}: Updated fic last update time from ${fic.modified} to ${modified} (from latest chapter)`)
      fic.modified = modified
    }
  }
  if (existingFic.chapters.length === 0) {
    let created = existingFic.fics.filter(f => f.created).reduce((ficCreated, subfic) => ficCreated < moment(subfic.created) ? ficCreated : moment(subfic.created), moment(existingFic.created))
    if (isDate(created) && (!dateEqual(existingFic.created, created))) {
      changes.push(`${existingFic.title}: Updated fic publish time from ${existingFic.created} to ${created} (from earliest subfic)`)
      existingFic.created = created
    }
    let modified = existingFic.fics.filter(f => f.modified || f.created).reduce((ficModified, subfic) => ficModified > moment(subfic.modified||subfic.created) ? ficModified : moment(subfic.modified||subfic.created), moment(existingFic.modified))
    if (isDate(modified) && (!dateEqual(existingFic.modified, modified))) {
      changes.push(`${existingFic.title}: Updated fic last update time from ${existingFic.modified} to ${modified} (from latest subfic)`)
      existingFic.modified = modified
    }
  }
  return changes
})

function andChapterEquals (chapterA) {
  return chapterB => chapterEqual(chapterA, chapterB)
}

function chapterEqual (chapterA, chapterB) {
  return (chapterA.link && chapterB.link && chapterA.link === chapterB.link) ||
         (chapterA.fetchFrom && chapterB.fetchFrom && chapterA.fetchFrom === chapterB.fetchFrom)
}

function dateEqual (dateA, dateB) {
  return moment(dateA).isSame(dateB)
}

function isDate (date) {
  if (date == null) return false
  if (isNaN(date)) return false
  return date instanceof Date || date instanceof moment
}
<|endoftext|>