<commit_before>/**
 * TreeFramework Gruntfile
 * @author Ilia Kolev
 */

'use strict';

/**
 * Grunt module
 */
module.exports = function (grunt) {

    /**
     * Displays the elapsed execution time of grunt tasks
     */
    require('time-grunt')(grunt);

    /**
     * JIT plugin loader for Grunt
     * https://github.com/shootaroo/jit-grunt
     */
    require('jit-grunt')(grunt, {
        scsslint: 'grunt-scss-lint'
    });

    /**
     * Project configuration
     */
    grunt.initConfig({

        /**
         * Store your Package file so you can reference its specific data whenever necessary
         */
        pkg: grunt.file.readJSON('package.json'),

        /**
         * Set project info
         */
        project: {
            www: 'www',
            js: [
                '<%= project.www %>/assets/js/vendor/*.js',
                '<%= project.www %>/assets/js/src/*.js'
            ],
            css: '<%= project.www %>/assets/css/'
        },

        /**
         * Bowercopy
         * https://npmjs.org/package/grunt-bowercopy
         * Scrupulously manage file locations for bower dependencies.
         */
        bowercopy: {
            options: {
                srcPrefix: 'bower_components',
                clean: true
            },
            jquery: {
                options: {
                    destPrefix: 'www/assets/js/vendor'
                },
                files: {
                    'jquery.min.js': 'jquery/dist/jquery.min.js'
                }
            },
            treeDefaults: {
                options: {
                    destPrefix: 'www/assets/sass/settings'
                },
                files: {
                    '_defaults.scss': 'tree-defaults/_defaults.scss'
                }
            },
            treeFunctions: {
                options: {
                    destPrefix: 'www/assets/sass/tools'
                },
                files: {
                    '_functions.scss': 'tree-functions/_functions.scss'
                }
            },
            treeMixins: {
                options: {
                    destPrefix: 'www/assets/sass/tools'
                },
                files: {
                    '_mixins.scss': 'tree-mixins/_mixins.scss'
                }
            },
            treeNormalizer: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_normalize.scss': 'tree-normalize/_normalize.scss'
                }
            },
            treeReset: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_reset.scss': 'tree-reset/_reset.scss'
                }
            },
            treeBoxSizing: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_box-sizing.scss': 'tree-box-sizing/_box-sizing.scss'
                }
            },
            treeShared: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_shared.scss': 'tree-shared/_shared.scss'
                }
            },
            treeClearfix: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_clearfix.scss': 'tree-clearfix/_clearfix.scss'
                }
            },
            treePage: {
                options: {
                    destPrefix: 'www/assets/sass/base'
                },
                files: {
                    '_page.scss': 'tree-page/_page.scss'
                }
            },
            treeHeadings: {
                options: {
                    destPrefix: 'www/assets/sass/base'
                },
                files: {
                    '_headings.scss': 'treeframework-headings/_headings.scss'
                }
            },
            treeLists: {
                options: {
                    destPrefix: 'www/assets/sass/base'
                },
                files: {
                    '_lists.scss': 'tree-lists/_lists.scss'
                }
            },
            treeImages: {
                options: {
                    destPrefix: 'www/assets/sass/base'
                },
                files: {
                    '_images.scss': 'tree-images/_images.scss'
                }
            },
            treeLayout: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_layout.scss': 'tree-layout/_layout.scss'
                }
            },
            treeBareList: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_bare-list.scss': 'tree-bare-list/_bare-list.scss'
                }
            },
            treeBlockList: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_block-list.scss': 'tree-block-list/_block-list.scss'
                }
            },
            treeTables: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_tables.scss': 'tree-tables/_tables.scss'
                }
            },
            treeMedia: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_media.scss': 'tree-media/_media.scss'
                }
            },
            treeWidths: {
                options: {
                    destPrefix: 'www/assets/sass/trumps'
                },
                files: {
                    '_widths.scss': 'tree-widths/_widths.scss'
                }
            }
        },

        /**
         * JSHint
         * https://github.com/gruntjs/grunt-contrib-jshint
         * Manage the options inside .jshintrc file
         */
        jshint: {
            files: [
                'www/assets/js/src/*.js',
                'Gruntfile.js'
            ],
            options: {
                jshintrc: '.jshintrc',
                ignores: [
                    'www/assets/js/scripts.js',
                    'www/assets/js/scripts.min.js',
                    'www/assets/js/vendor/*.js'
                ]
            }
        },

        /**
         * Concatenate JavaScript files
         * https://github.com/gruntjs/grunt-contrib-concat
         * Imports all .js files
         */
        concat: {
            dist: {
                src: '<%= project.js %>',
                dest:'www/assets/js/scripts.js'
            }
        },

        /**
         * Uglify (minify) JavaScript files
         * https://github.com/gruntjs/grunt-contrib-uglify
         * Compresses and minifies all JavaScript files into one
         */
        uglify: {
            dist: {
                files: {
                    'www/assets/js/scripts.min.js': 'www/assets/js/scripts.js'
                }
            }
        },

        /**
         * A Grunt task to lint your SCSS
         * https://github.com/ahmednuaman/grunt-scss-lint
         */
        scsslint: {
            files: [
                '<%= project.www %>/assets/sass/{,*/}*.scss'
            ],
            options: {
                config: '.scss-lint.yml',
                reporterOutput: null
            }
        },

        /**
         * Compile Sass to CSS using Compass
         * https://github.com/gruntjs/grunt-contrib-compass
         */
        compass: {
            dist: {
                options: {
                    config: 'config.rb'
                }
            }
        },

        /**
         * Autoprefixer
         * Adds vendor prefixes automatically
         * https://github.com/nDmitry/grunt-autoprefixer
         */
        autoprefixer: {
            dist: {
                options: {
                    browsers: [
                        'last 2 version',
                        'safari 6',
                        'ie 9',
                        'opera 12.1',
                        'ios 6',
                        'android 4'
                    ]
                },
                src: '<%= project.css %>screen.css'
            }
        },

        /**
         * CSSO
         * Minify CSS files
         * https://github.com/t32k/grunt-csso
         */
        csso: {
            options: {
                report: 'min'
            },
            dist: {
                files: {
                    '<%= project.css %>screen.min.css': ['<%= project.css %>screen.css']
                }
            }
        },

        /**
         * Browser sync
         * Keep multiple browsers & devices in sync
         * https://github.com/shakyShane/grunt-browser-sync
         */
        browserSync: {
            dev: {
                files: {
                    src : [
                        '<%= project.css %>screen.min.css',
                        '<%= project.www %>/{,*/}*.{html,php}'
                    ]
                },
                options: {
                    watchTask: true,
                    debugInfo: true,
                    server: {
                        baseDir: 'www'
                    }
                }
            }
        },

        /**
         * Runs tasks against changed watched files
         * https://github.com/gruntjs/grunt-contrib-watch
         */
        watch: {
            options: {
                livereload: true
            },
            js: {
                files: '<%= project.js %>',
                tasks: ['concat', 'jshint', 'uglify'],
                options: {
                    spawn: false
                }
            },
            sass: {
                files: 'www/assets/sass/{,*/}*.{scss,sass}',
                tasks: ['compass', 'autoprefixer', 'csso'],
                options: {
                    spawn: false
                }
            },
            pages: {
                files: '<%= project.www %>/{,*/}*.{html,php}'
            },
            images: {
                files: '<%= project.www %>/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
            }
        }
    });

    /**
     * Default task
     * Run 'grunt' on the command line
     */
    grunt.registerTask('default', [
        'compass',
        'autoprefixer',
        'csso',
        'scsslint',
        'jshint',
        'watch'
    ]);

    /**
     * Build task
     * Run 'grunt build' on the command line
     * Then compress all JS/CSS files
     */
    grunt.registerTask('build', [
        'compass',
        'autoprefixer',
        'csso',
        'scsslint',
        'jshint',
        'uglify'
    ]);

    /**
     * Sync task
     * Run 'grunt sync' on the command line
     * Alias sync to browserSync + watch
     */
    grunt.registerTask('sync', [
        'browserSync',
        'watch'
    ]);

    /**
     * Bower task
     * Alias bower to bowercopy
     * Run 'grunt bower' on the command line
     *
     * When updating a bower dependency, update the version in bower.json, run
     * 'grunt bower', and then commit the result. When adding a dependency,
     * update the bowercopy task accordingly.
     */
    grunt.registerTask('bower', 'bowercopy');
};
<commit_msg>Update Gruntfile.js<commit_after>/**
 * TreeFramework Gruntfile
 * @author Ilia Kolev
 */

'use strict';

/**
 * Grunt module
 */
module.exports = function (grunt) {

    /**
     * Displays the elapsed execution time of grunt tasks
     */
    require('time-grunt')(grunt);

    /**
     * JIT plugin loader for Grunt
     * https://github.com/shootaroo/jit-grunt
     */
    require('jit-grunt')(grunt, {
        scsslint: 'grunt-scss-lint'
    });

    /**
     * Project configuration
     */
    grunt.initConfig({

        /**
         * Store your Package file so you can reference its specific data whenever necessary
         */
        pkg: grunt.file.readJSON('package.json'),

        /**
         * Set project info
         */
        project: {
            www: 'www',
            js: [
                '<%= project.www %>/assets/js/vendor/*.js',
                '<%= project.www %>/assets/js/src/*.js'
            ],
            css: '<%= project.www %>/assets/css/'
        },

        /**
         * Bowercopy
         * https://npmjs.org/package/grunt-bowercopy
         * Scrupulously manage file locations for bower dependencies.
         */
        bowercopy: {
            options: {
                srcPrefix: 'bower_components',
                clean: true
            },
            jquery: {
                options: {
                    destPrefix: 'www/assets/js/vendor'
                },
                files: {
                    'jquery.min.js': 'jquery/dist/jquery.min.js'
                }
            },
            treeDefaults: {
                options: {
                    destPrefix: 'www/assets/sass/settings'
                },
                files: {
                    '_defaults.scss': 'tree-defaults/_defaults.scss'
                }
            },
            treeFunctions: {
                options: {
                    destPrefix: 'www/assets/sass/tools'
                },
                files: {
                    '_functions.scss': 'tree-functions/_functions.scss'
                }
            },
            treeMixins: {
                options: {
                    destPrefix: 'www/assets/sass/tools'
                },
                files: {
                    '_mixins.scss': 'tree-mixins/_mixins.scss'
                }
            },
            treeNormalizer: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_normalize.scss': 'tree-normalize/_normalize.scss'
                }
            },
            treeReset: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_reset.scss': 'tree-reset/_reset.scss'
                }
            },
            treeBoxSizing: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_box-sizing.scss': 'tree-box-sizing/_box-sizing.scss'
                }
            },
            treeShared: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_shared.scss': 'tree-shared/_shared.scss'
                }
            },
            treeClearfix: {
                options: {
                    destPrefix: 'www/assets/sass/generic'
                },
                files: {
                    '_clearfix.scss': 'tree-clearfix/_clearfix.scss'
                }
            },
            treePage: {
                options: {
                    destPrefix: 'www/assets/sass/base'
                },
                files: {
                    '_page.scss': 'tree-page/_page.scss'
                }
            },
            treeHeadings: {
                options: {
                    destPrefix: 'www/assets/sass/base'
                },
                files: {
                    '_headings.scss': 'treeframework-headings/_headings.scss'
                }
            },
            treeLists: {
                options: {
                    destPrefix: 'www/assets/sass/base'
                },
                files: {
                    '_lists.scss': 'tree-lists/_lists.scss'
                }
            },
            treeImages: {
                options: {
                    destPrefix: 'www/assets/sass/base'
                },
                files: {
                    '_images.scss': 'tree-images/_images.scss'
                }
            },
            treeLayout: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_layout.scss': 'tree-layout/_layout.scss'
                }
            },
            treeBareList: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_bare-list.scss': 'tree-bare-list/_bare-list.scss'
                }
            },
            treeBlockList: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_block-list.scss': 'tree-block-list/_block-list.scss'
                }
            },
            treeTables: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_tables.scss': 'tree-tables/_tables.scss'
                }
            },
            treeMedia: {
                options: {
                    destPrefix: 'www/assets/sass/objects'
                },
                files: {
                    '_media.scss': 'tree-media/_media.scss'
                }
            },
            treeWidths: {
                options: {
                    destPrefix: 'www/assets/sass/trumps'
                },
                files: {
                    '_widths.scss': 'tree-widths/_widths.scss'
                }
            }
        },

        /**
         * JSHint
         * https://github.com/gruntjs/grunt-contrib-jshint
         * Manage the options inside .jshintrc file
         */
        jshint: {
            files: [
                'www/assets/js/src/*.js',
                'Gruntfile.js'
            ],
            options: {
                jshintrc: '.jshintrc',
                ignores: [
                    'www/assets/js/scripts.js',
                    'www/assets/js/scripts.min.js',
                    'www/assets/js/vendor/*.js'
                ]
            }
        },

        /**
         * Concatenate JavaScript files
         * https://github.com/gruntjs/grunt-contrib-concat
         * Imports all .js files
         */
        concat: {
            dist: {
                src: '<%= project.js %>',
                dest:'www/assets/js/scripts.js'
            }
        },

        /**
         * Uglify (minify) JavaScript files
         * https://github.com/gruntjs/grunt-contrib-uglify
         * Compresses and minifies all JavaScript files into one
         */
        uglify: {
            dist: {
                files: {
                    'www/assets/js/scripts.min.js': 'www/assets/js/scripts.js'
                }
            }
        },

        /**
         * A Grunt task to lint your SCSS
         * https://github.com/ahmednuaman/grunt-scss-lint
         */
        scsslint: {
            files: [
                '<%= project.www %>/assets/sass/{,*/}*.scss'
            ],
            options: {
                config: '.scss-lint.yml',
                reporterOutput: null
            }
        },

        /**
         * Compile Sass to CSS using Compass
         * https://github.com/gruntjs/grunt-contrib-compass
         */
        compass: {
            dist: {
                options: {
                    config: 'config.rb'
                }
            }
        },

        /**
         * Autoprefixer
         * Adds vendor prefixes automatically
         * https://github.com/nDmitry/grunt-autoprefixer
         */
        autoprefixer: {
            dist: {
                options: {
                    browsers: [
                        'last 3 version',
                        'ie 8',
                        'ie 9'
                    ]
                },
                src: '<%= project.css %>screen.css'
            }
        },

        /**
         * CSSO
         * Minify CSS files
         * https://github.com/t32k/grunt-csso
         */
        csso: {
            options: {
                report: 'min'
            },
            dist: {
                files: {
                    '<%= project.css %>screen.min.css': ['<%= project.css %>screen.css']
                }
            }
        },

        /**
         * Browser sync
         * Keep multiple browsers & devices in sync
         * https://github.com/shakyShane/grunt-browser-sync
         */
        browserSync: {
            dev: {
                files: {
                    src : [
                        '<%= project.css %>screen.min.css',
                        '<%= project.www %>/{,*/}*.{html,php}'
                    ]
                },
                options: {
                    watchTask: true,
                    debugInfo: true,
                    server: {
                        baseDir: 'www'
                    }
                }
            }
        },

        /**
         * Runs tasks against changed watched files
         * https://github.com/gruntjs/grunt-contrib-watch
         */
        watch: {
            options: {
                livereload: true
            },
            js: {
                files: '<%= project.js %>',
                tasks: ['concat', 'jshint', 'uglify'],
                options: {
                    spawn: false
                }
            },
            sass: {
                files: 'www/assets/sass/{,*/}*.{scss,sass}',
                tasks: ['compass', 'autoprefixer', 'csso'],
                options: {
                    spawn: false
                }
            },
            pages: {
                files: '<%= project.www %>/{,*/}*.{html,php}'
            },
            images: {
                files: '<%= project.www %>/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
            }
        }
    });

    /**
     * Default task
     * Run 'grunt' on the command line
     */
    grunt.registerTask('default', [
        'compass',
        'autoprefixer',
        'csso',
        'scsslint',
        'jshint',
        'watch'
    ]);

    /**
     * Build task
     * Run 'grunt build' on the command line
     * Then compress all JS/CSS files
     */
    grunt.registerTask('build', [
        'compass',
        'autoprefixer',
        'csso',
        'scsslint',
        'jshint',
        'uglify'
    ]);

    /**
     * Sync task
     * Run 'grunt sync' on the command line
     * Alias sync to browserSync + watch
     */
    grunt.registerTask('sync', [
        'browserSync',
        'watch'
    ]);

    /**
     * Bower task
     * Alias bower to bowercopy
     * Run 'grunt bower' on the command line
     *
     * When updating a bower dependency, update the version in bower.json, run
     * 'grunt bower', and then commit the result. When adding a dependency,
     * update the bowercopy task accordingly.
     */
    grunt.registerTask('bower', 'bowercopy');
};
<|endoftext|>


<commit_before>(function () {
   'use strict';
   var gulp = require('gulp'),

      fs = require('fs'),

      rename = require('gulp-rename'),

      concat = require('gulp-concat'),

      uglify = require('gulp-uglify'),

      jshint = require('gulp-jshint'),

      stripDebug = require('gulp-strip-debug'),

      sourcemaps = require('gulp-sourcemaps'),

      sass = require('gulp-ruby-sass'),

      cssnano = require('gulp-cssnano'),

      htmlReplace = require('gulp-html-replace'),

      del = require('del'),

      path = require('path'),

      gulpFile = require('gulp-file'),

      foreach = require('gulp-foreach'),

      json_merger = require('json_merger'),

      jsonminify = require('gulp-jsonminify'),

      babel = require('gulp-babel'),

      jscs = require('gulp-jscs'),

      vinylfs = require('vinyl-fs');

   var projectRoot = __dirname + '/../../';

   var transpileDir = projectRoot + '/src/transpiled/';

   var buildDir = projectRoot + '/dist/';

   // All file paths used in the gulp file are inside this object
   var paths = {
      js: {
         source: projectRoot + '/src/js/',
         transpiled: transpileDir + '/js/',
         build: buildDir + '/js/',
         sourceRoot: '/js/',
         coreLibrary: projectRoot + '/node_modules/widget-core-library/src/transpiled/js/'
      },
      css: {
         source: projectRoot + '/src/scss/',
         transpiled: transpileDir + '/css/',
         build: buildDir + '/css/',
         sourceRoot: '../../scss/'
      },
      i18n: {
         source: projectRoot + '/src/i18n/',
         coreLibrarySource: projectRoot + '/node_modules/widget-core-library/src/i18n/',
         transpiled: transpileDir + '/i18n/',
         build: buildDir + '/i18n/',
      },
      fonts: {
         source: projectRoot + '/node_modules/widget-core-library/src/fonts/**/*',
         transpiled: transpileDir + '/fonts/',
         build: buildDir + '/fonts/',
      },
      configFiles: [
         projectRoot + '/node_modules/widget-build-tools/widget_config/gitignore',
         projectRoot + '/node_modules/widget-build-tools/widget_config/.editorconfig',
         projectRoot + '/node_modules/widget-build-tools/widget_config/.jshintrc',
         projectRoot + '/node_modules/widget-build-tools/widget_config/.jscsrc',
         projectRoot + '/node_modules/widget-build-tools/widget_config/config.rb',
         projectRoot + '/node_modules/widget-build-tools/widget_config/LICENSE',
         projectRoot + '/node_modules/widget-build-tools/widget_config/.scss-lint.yml'
      ],
      staticFiles: [
         './src/**/*',
         '!./src/js/**',
         '!./src/js/',
         '!./src/scss/**',
         '!./src/scss/',
         '!./src/i18n/**',
         '!./src/i18n/',
         '!./src/transpiled/**',
         '!./src/transpiled/'
      ]
   };

   var buildParameters;
   try {
      buildParameters = JSON.parse(fs.readFileSync('./buildparameters.json'));
   } catch (e) {
      buildParameters = {};
   }

   /**
    * Copies project configuration files from the build tools into the project
    */
   gulp.task('copy-config-files', function () {
      return gulp.src(paths.configFiles)
         .pipe(rename(function ( path ) {
            // .gitignore has special handling because npm strips .gitignore files
            // when downloading dependencies
            if ( path.basename === 'gitignore' ) {
               path.basename = '.gitignore';
            }
         }))
         .pipe(vinylfs.dest(projectRoot, { overwrite: true })); // same as gulp.dest, but accepts an overwrite flag
   });

   gulp.task('clean-temp', function () {
      return del.sync(transpileDir);
   });

   /**
    * Cleans the project (deletes transpileDir and buildDir folders)
    */
   gulp.task('clean', ['clean-temp'], function () {
      return del.sync(buildDir);
   });

   /**
    * Cleans then builds
    */
   gulp.task('default', ['clean'], function () {
      return gulp.start('build');
   });

   /**
    * Tasks used by 'build' to run everything in the right order
    */
   gulp.task('build2', ['copy-config-files'], function () {
      return gulp.start('build3');
   });
   gulp.task('build3', ['compile'], function () {
      return gulp.start('build4');
   });
   gulp.task('build4', ['bundle-static', 'bundle-css', 'bundle-js', 'bundle-fonts'], function () {
      return gulp.start('build5');
   });
   gulp.task('build5', ['html-replace']);

   /**
    * Full build cycle with compilling and minifying
    */
   gulp.task('build', ['build2']);

   /**
    * Replaces references inside index.html to reference the minified and concatanated
    * js and css files
    */
   gulp.task('html-replace', function () {
      var resourcePaths;
      try {
         resourcePaths = JSON.parse(fs.readFileSync('./resourcepaths.json'));
      } catch (e) {
         throw new Error('could not read resourcepaths.json');
      }
      if (resourcePaths.htmlReplace == null) {
         resourcePaths.htmlReplace = {};
      }

      var coreLibConfig = JSON.parse(fs.readFileSync('./node_modules/widget-core-library/package.json'));

      var kambiAPIVersion = coreLibConfig['kambi-widget-api-version'] != null ? coreLibConfig['kambi-widget-api-version'] : '1.0.0.10';

      var kambiWidgetAPIUrl = 'https://c3-static.kambi.com/sb-mobileclient/widget-api/{{API_VERSION}}/kambi-widget-api.js'
         .replace('{{API_VERSION}}', kambiAPIVersion);

      var references = extendObj(
         {
            js: 'js/app.min.js',
            css: 'css/app.min.css',
            'kambi-widget-api': kambiWidgetAPIUrl,
            'third-party-libs': resourcePaths.thirdPartyLibs
         },
         resourcePaths.htmlReplace
      );
      return gulp.src('./src/index.html')
         .pipe(htmlReplace(references))
         .pipe(gulp.dest('./dist'));
   });

   /**
    * Compiles all scss files and places them in {transpileDir}/css/ folder
    */
   gulp.task('compile-scss', [], function () {
      return sass(paths.css.source + 'app.scss', {
            compass: true,
            style: 'expanded',
            lineComments: false,
            sourcemap: true
         })
         .pipe(sourcemaps.write('.', {
            includeContent: false,
            sourceRoot: paths.css.sourceRoot
         }))
         .pipe(gulp.dest(paths.css.transpiled));
   });

   /**
    * Compiles all js files using Babel and places them in {transpileDir} folder
    */
   gulp.task('compile-babel', [], function () {
      var sourceRootMap = function (file) {
         return '../' + path.relative(file.history[0], paths.js.source) + paths.js.sourceRoot;
      }
      return gulp.src(paths.js.source + '/**/*.js')
         .pipe(jshint('.jshintrc'))
         .pipe(jshint.reporter('default'))
         .pipe(jscs())
         .pipe(jscs.reporter())
         .pipe(sourcemaps.init())
         .pipe(babel({
            presets: ['es2015']
         }))
         .pipe(sourcemaps.write('.', {
            includeContent: false,
            sourceRoot: sourceRootMap
         }))
         .pipe(gulp.dest(paths.js.transpiled));
   });

   /**
    * Copies all static files (.html, .json, images) to transpileDir folder, i18n files are handled
    * by the compile-translations task
    */
   gulp.task('compile-static', [], function () {
      return gulp.src(paths.staticFiles)
         .pipe(gulp.dest(transpileDir))
   });

   /**
    * Copies all fonts from widget-core-library to transpileDir
    */
   gulp.task('compile-fonts', [], function () {
      return gulp.src(paths.fonts.source)
         .pipe(gulp.dest(paths.fonts.transpiled));
   });

   /**
    * Compiles all js, scss and i18n files and place them (alongside static files) in the dist
    * folder
    */
   gulp.task('compile', [
      'compile-babel',
      'compile-scss',
      'compile-translations',
      'compile-static',
      'compile-fonts'
   ]);

   /**
    * Watches for any change in the files inside /src/ folder and recompiles them
    */
   gulp.task('watch', [], function () {
      gulp.watch(paths.js.source + '/**/*.js', ['compile-babel']);
      gulp.watch(paths.css.source + '/**/*.scss', ['compile-scss']);
      gulp.watch(paths.i18n.source + '/**/*.json', ['compile-translations']);
      gulp.watch(paths.staticFiles, ['compile-static']);
      gulp.watch(paths.fonts.source, ['compile-fonts']);
   });

   /**
    * Minifies and concatenates all css files from {transpileDir} into {buildDir}
    */
   gulp.task('bundle-css', function () {
      return gulp.src(paths.css.transpiled + '/**/*.css')
         .pipe(concat('app.css'))
         .pipe(gulp.dest(paths.css.build))
         .pipe(cssnano())
         .pipe(rename('app.min.css'))
         .pipe(gulp.dest(paths.css.build));
   });

   /**
    * Minifies and concatenates all js files from {transpileDir} into {buildDir}
    */
   gulp.task('bundle-js', function () {
      return gulp.src([
            paths.js.coreLibrary + '**/*.js',
            paths.js.transpiled + '**/*.js'
         ])
         .pipe(concat('app.js'))
         .pipe(stripDebug())
         .pipe(gulp.dest(paths.js.build))
         .pipe(uglify())
         .pipe(rename('app.min.js'))
         .pipe(gulp.dest(paths.js.build));
   });

   /**
    * Copies all static files (.html, .json, images) to buildDir folder, i18n files are handled
    * by the compile-translations task
    */
   gulp.task('bundle-static', [], function () {
      return gulp.src(paths.staticFiles)
         .pipe(gulp.dest(buildDir));
   });

   /**
    * Copies all font files from widget-core-library to buildDir folder
    */
   gulp.task('bundle-fonts', [], function () {
      return gulp.src(paths.fonts.source)
         .pipe(gulp.dest(paths.fonts.build));
   });

   /**
    * Merges widget i18n files with cherry-picked strings from the widget-core-library
    */
   gulp.task('compile-translations', function () {
      return gulp.src(paths.i18n.source + '/**/*.json')
         .pipe(foreach(function ( stream, file ) {
            var name = path.basename(file.path);
            var filePath = paths.i18n.coreLibrarySource + name;
            var srcJson = JSON.parse(file.contents.toString());
            var selectedFromKambi = {};

            try {
               fs.statSync(filePath); // throws error if file does not exist
               var coreLibraryJson = json_merger.fromFile(filePath);

               // buildParameters.localeStrings should be an object in the following format:
               // { "keyInI18nJSON": "pathToValueInKambiI18nJSON" }
               if (buildParameters.localeStrings != null) {
                  Object.keys(buildParameters.localeStrings).forEach(function ( key ) {
                     // creates a new function that retrieves the string specified by the path in localeStrings from the localeJson
                     /* jslint evil: true */
                     selectedFromKambi[key] = new Function('json', 'return json.' + buildParameters.localeStrings[key])(coreLibraryJson);
                  });
               }

               var result = extendObj(srcJson, selectedFromKambi);
               // TODO find a way to make this synchronous:
               gulpFile(name, JSON.stringify(result, null, 3), { src: true })
                  .pipe(gulp.dest(paths.i18n.transpiled))
                  .pipe(jsonminify())
                  .pipe(gulp.dest(paths.i18n.build));
            } catch (e) {
               console.warn('Warning: could not merge i18n file named: ' + name + ' with core file');
               console.warn(e);
               // TODO find a way to make this synchronous:
               // copying without merging
               gulp.src(paths.i18n.source + name)
                  .pipe(gulp.dest('./' + transpileDir + '/i18n/'))
                  .pipe(jsonminify())
                  .pipe(gulp.dest(paths.i18n.source.build));
            }

            return stream;
         }));
   });

   function extendObj ( obj, src ) {
      Object.keys(src).forEach(function ( key ) {
         obj[key] = src[key];
      });
      return obj;
   }

}).call(this);
<commit_msg>Now gets the core-library Javascript from the /dist/ folder<commit_after>(function () {
   'use strict';
   var gulp = require('gulp'),

      fs = require('fs'),

      rename = require('gulp-rename'),

      concat = require('gulp-concat'),

      uglify = require('gulp-uglify'),

      jshint = require('gulp-jshint'),

      stripDebug = require('gulp-strip-debug'),

      sourcemaps = require('gulp-sourcemaps'),

      sass = require('gulp-ruby-sass'),

      cssnano = require('gulp-cssnano'),

      htmlReplace = require('gulp-html-replace'),

      del = require('del'),

      path = require('path'),

      gulpFile = require('gulp-file'),

      foreach = require('gulp-foreach'),

      json_merger = require('json_merger'),

      jsonminify = require('gulp-jsonminify'),

      babel = require('gulp-babel'),

      jscs = require('gulp-jscs'),

      vinylfs = require('vinyl-fs');

   var projectRoot = __dirname + '/../../';

   var transpileDir = projectRoot + '/src/transpiled/';

   var buildDir = projectRoot + '/dist/';

   // All file paths used in the gulp file are inside this object
   var paths = {
      js: {
         source: projectRoot + '/src/js/',
         transpiled: transpileDir + '/js/',
         build: buildDir + '/js/',
         sourceRoot: '/js/',
         coreLibraryFile: projectRoot + '/node_modules/widget-core-library/dist/core.js'
      },
      css: {
         source: projectRoot + '/src/scss/',
         transpiled: transpileDir + '/css/',
         build: buildDir + '/css/',
         sourceRoot: '../../scss/'
      },
      i18n: {
         source: projectRoot + '/src/i18n/',
         coreLibrarySource: projectRoot + '/node_modules/widget-core-library/src/i18n/',
         transpiled: transpileDir + '/i18n/',
         build: buildDir + '/i18n/'
      },
      fonts: {
         source: projectRoot + '/node_modules/widget-core-library/src/fonts/**/*',
         transpiled: transpileDir + '/fonts/',
         build: buildDir + '/fonts/'
      },
      configFiles: [
         projectRoot + '/node_modules/widget-build-tools/widget_config/gitignore',
         projectRoot + '/node_modules/widget-build-tools/widget_config/.editorconfig',
         projectRoot + '/node_modules/widget-build-tools/widget_config/.jshintrc',
         projectRoot + '/node_modules/widget-build-tools/widget_config/.jscsrc',
         projectRoot + '/node_modules/widget-build-tools/widget_config/config.rb',
         projectRoot + '/node_modules/widget-build-tools/widget_config/LICENSE',
         projectRoot + '/node_modules/widget-build-tools/widget_config/.scss-lint.yml'
      ],
      staticFiles: [
         './src/**/*',
         '!./src/js/**',
         '!./src/js/',
         '!./src/scss/**',
         '!./src/scss/',
         '!./src/i18n/**',
         '!./src/i18n/',
         '!./src/transpiled/**',
         '!./src/transpiled/'
      ]
   };

   var buildParameters;
   try {
      buildParameters = JSON.parse(fs.readFileSync('./buildparameters.json'));
   } catch (e) {
      buildParameters = {};
   }

   /**
    * Copies project configuration files from the build tools into the project
    */
   gulp.task('copy-config-files', function () {
      return gulp.src(paths.configFiles)
         .pipe(rename(function ( path ) {
            // .gitignore has special handling because npm strips .gitignore files
            // when downloading dependencies
            if ( path.basename === 'gitignore' ) {
               path.basename = '.gitignore';
            }
         }))
         .pipe(vinylfs.dest(projectRoot, { overwrite: true })); // same as gulp.dest, but accepts an overwrite flag
   });

   gulp.task('clean-temp', function () {
      return del.sync(transpileDir);
   });

   /**
    * Cleans the project (deletes transpileDir and buildDir folders)
    */
   gulp.task('clean', ['clean-temp'], function () {
      return del.sync(buildDir);
   });

   /**
    * Cleans then builds
    */
   gulp.task('default', ['clean'], function () {
      return gulp.start('build');
   });

   /**
    * Tasks used by 'build' to run everything in the right order
    */
   gulp.task('build2', ['copy-config-files'], function () {
      return gulp.start('build3');
   });
   gulp.task('build3', ['compile'], function () {
      return gulp.start('build4');
   });
   gulp.task('build4', ['bundle-static', 'bundle-css', 'bundle-js', 'bundle-fonts'], function () {
      return gulp.start('build5');
   });
   gulp.task('build5', ['html-replace']);

   /**
    * Full build cycle with compilling and minifying
    */
   gulp.task('build', ['build2']);

   /**
    * Replaces references inside index.html to reference the minified and concatanated
    * js and css files
    */
   gulp.task('html-replace', function () {
      var resourcePaths;
      try {
         resourcePaths = JSON.parse(fs.readFileSync('./resourcepaths.json'));
      } catch (e) {
         throw new Error('could not read resourcepaths.json');
      }
      if (resourcePaths.htmlReplace == null) {
         resourcePaths.htmlReplace = {};
      }

      var coreLibConfig = JSON.parse(fs.readFileSync('./node_modules/widget-core-library/package.json'));

      var kambiAPIVersion = coreLibConfig['kambi-widget-api-version'] != null ? coreLibConfig['kambi-widget-api-version'] : '1.0.0.10';

      var kambiWidgetAPIUrl = 'https://c3-static.kambi.com/sb-mobileclient/widget-api/{{API_VERSION}}/kambi-widget-api.js'
         .replace('{{API_VERSION}}', kambiAPIVersion);

      var references = extendObj(
         {
            js: 'js/app.min.js',
            css: 'css/app.min.css',
            'kambi-widget-api': kambiWidgetAPIUrl,
            'third-party-libs': resourcePaths.thirdPartyLibs
         },
         resourcePaths.htmlReplace
      );
      return gulp.src('./src/index.html')
         .pipe(htmlReplace(references))
         .pipe(gulp.dest('./dist'));
   });

   /**
    * Compiles all scss files and places them in {transpileDir}/css/ folder
    */
   gulp.task('compile-scss', [], function () {
      return sass(paths.css.source + 'app.scss', {
            compass: true,
            style: 'expanded',
            lineComments: false,
            sourcemap: true
         })
         .pipe(sourcemaps.write('.', {
            includeContent: false,
            sourceRoot: paths.css.sourceRoot
         }))
         .pipe(gulp.dest(paths.css.transpiled));
   });

   /**
    * Compiles all js files using Babel and places them in {transpileDir} folder
    */
   gulp.task('compile-babel', [], function () {
      var sourceRootMap = function (file) {
         return '../' + path.relative(file.history[0], paths.js.source) + paths.js.sourceRoot;
      };
      return gulp.src(paths.js.source + '/**/*.js')
         .pipe(jshint('.jshintrc'))
         .pipe(jshint.reporter('default'))
         .pipe(jscs())
         .pipe(jscs.reporter())
         .pipe(sourcemaps.init())
         .pipe(babel({
            presets: ['es2015']
         }))
         .pipe(sourcemaps.write('.', {
            includeContent: false,
            sourceRoot: sourceRootMap
         }))
         .pipe(gulp.dest(paths.js.transpiled));
   });

   /**
    * Copies all static files (.html, .json, images) to transpileDir folder, i18n files are handled
    * by the compile-translations task
    */
   gulp.task('compile-static', [], function () {
      return gulp.src(paths.staticFiles)
         .pipe(gulp.dest(transpileDir));
   });

   /**
    * Copies all fonts from widget-core-library to transpileDir
    */
   gulp.task('compile-fonts', [], function () {
      return gulp.src(paths.fonts.source)
         .pipe(gulp.dest(paths.fonts.transpiled));
   });

   /**
    * Compiles all js, scss and i18n files and place them (alongside static files) in the dist
    * folder
    */
   gulp.task('compile', [
      'compile-babel',
      'compile-scss',
      'compile-translations',
      'compile-static',
      'compile-fonts'
   ]);

   /**
    * Watches for any change in the files inside /src/ folder and recompiles them
    */
   gulp.task('watch', [], function () {
      gulp.watch(paths.js.source + '/**/*.js', ['compile-babel']);
      gulp.watch(paths.css.source + '/**/*.scss', ['compile-scss']);
      gulp.watch(paths.i18n.source + '/**/*.json', ['compile-translations']);
      gulp.watch(paths.staticFiles, ['compile-static']);
      gulp.watch(paths.fonts.source, ['compile-fonts']);
   });

   /**
    * Minifies and concatenates all css files from {transpileDir} into {buildDir}
    */
   gulp.task('bundle-css', function () {
      return gulp.src(paths.css.transpiled + '/**/*.css')
         .pipe(concat('app.css'))
         .pipe(gulp.dest(paths.css.build))
         .pipe(cssnano())
         .pipe(rename('app.min.css'))
         .pipe(gulp.dest(paths.css.build));
   });

   /**
    * Minifies and concatenates all js files from {transpileDir} into {buildDir}
    */
   gulp.task('bundle-js', function () {
      return gulp.src([
            paths.js.coreLibraryFile,
            paths.js.transpiled + '**/*.js'
         ])
         .pipe(concat('app.js'))
         .pipe(stripDebug())
         .pipe(gulp.dest(paths.js.build))
         .pipe(uglify())
         .pipe(rename('app.min.js'))
         .pipe(gulp.dest(paths.js.build));
   });

   /**
    * Copies all static files (.html, .json, images) to buildDir folder, i18n files are handled
    * by the compile-translations task
    */
   gulp.task('bundle-static', [], function () {
      return gulp.src(paths.staticFiles)
         .pipe(gulp.dest(buildDir));
   });

   /**
    * Copies all font files from widget-core-library to buildDir folder
    */
   gulp.task('bundle-fonts', [], function () {
      return gulp.src(paths.fonts.source)
         .pipe(gulp.dest(paths.fonts.build));
   });

   /**
    * Merges widget i18n files with cherry-picked strings from the widget-core-library
    */
   gulp.task('compile-translations', function () {
      return gulp.src(paths.i18n.source + '/**/*.json')
         .pipe(foreach(function ( stream, file ) {
            var name = path.basename(file.path);
            var filePath = paths.i18n.coreLibrarySource + name;
            var srcJson = JSON.parse(file.contents.toString());
            var selectedFromKambi = {};

            try {
               fs.statSync(filePath); // throws error if file does not exist
               var coreLibraryJson = json_merger.fromFile(filePath);

               // buildParameters.localeStrings should be an object in the following format:
               // { "keyInI18nJSON": "pathToValueInKambiI18nJSON" }
               if (buildParameters.localeStrings != null) {
                  Object.keys(buildParameters.localeStrings).forEach(function ( key ) {
                     // creates a new function that retrieves the string specified by the path in localeStrings from the localeJson
                     /* jslint evil: true */
                     selectedFromKambi[key] = new Function('json', 'return json.' + buildParameters.localeStrings[key])(coreLibraryJson);
                  });
               }

               var result = extendObj(srcJson, selectedFromKambi);
               // TODO find a way to make this synchronous:
               gulpFile(name, JSON.stringify(result, null, 3), { src: true })
                  .pipe(gulp.dest(paths.i18n.transpiled))
                  .pipe(jsonminify())
                  .pipe(gulp.dest(paths.i18n.build));
            } catch (e) {
               console.warn('Warning: could not merge i18n file named: ' + name + ' with core file');
               console.warn(e);
               // TODO find a way to make this synchronous:
               // copying without merging
               gulp.src(paths.i18n.source + name)
                  .pipe(gulp.dest('./' + transpileDir + '/i18n/'))
                  .pipe(jsonminify())
                  .pipe(gulp.dest(paths.i18n.source.build));
            }

            return stream;
         }));
   });

   function extendObj ( obj, src ) {
      Object.keys(src).forEach(function ( key ) {
         obj[key] = src[key];
      });
      return obj;
   }

}).call(this);
<|endoftext|>


<commit_before>import 'tms-semantic-ui';
import 'semantic-ui-calendar';
import 'jquery-format';

export class App {

    constructor() {
        this.init();
        this.initCalendar();

        this.subscribe = ea.subscribe(nsCons.EVENT_APP_ROUTER_NAVIGATE, (payload) => {
            this.router && this.router.navigate(`${payload.to}`);
        });
    }

    attached() {

        // table export
        $('body').on('mouseenter', '.markdown-body table', (event) => {
            event.preventDefault();

            let $table = $(event.currentTarget);

            if (!$table.parent().is('.export-table-wrapper')) {

                let uid = new Date().getTime();

                $table.attr('id', `export-table-${uid}`);

                $table.wrap(`<div class="export-table-wrapper"></div>`);

                $table.after($(`<i class="export-btn download link icon" title="下载为CSV表格文件"></i>`));
            }

            $table.parent().children('.export-btn').show();

        });

        $('body').on('mouseleave', '.markdown-body table', (event) => {
            event.preventDefault();

            if ($(event.toElement).is('.export-btn')) return;

            let $table = $(event.currentTarget);

            if ($table.parent().is('.export-table-wrapper')) {
                $table.parent().children('.export-btn').hide();
            }

        });

        $('body').on('click', '.markdown-body .export-table-wrapper .export-btn', event => {
            event.preventDefault();
            let $item = $(event.currentTarget);
            tableExport($item.parents('.export-table-wrapper').children('table').attr('id'), `tms-export-table_${$.format.date(new Date(), "yyyy-MM-dd_hhmmss") }`, 'csv');
        });

        $('body').on('click', '.markdown-body li.task-item input:checkbox', event => {

            let $item = $(event.currentTarget);

            let $md = $item.parents('.markdown-body[data-case]');

            if (!$md || $md.length == 0) {
                event.preventDefault();
                return;
            }

            let $items = $md.find('li.task-item input:checkbox');

            ea.publish(nsCons.EVENT_MARKDOWN_TASK_ITEM_STATUS_TOGGLE, {
                event: event,
                id: $md.attr('data-id'),
                case: $md.attr('data-case'),
                from: $md.attr('data-from'),
                index: $items.index($item)
            });

        });

        // file online preview
        $('body').on('mouseenter', '.markdown-body a[href*="admin/file/download/"],a.tms-file-download-item', (event) => {
            event.preventDefault();

            if (!window.tmsSysConfig || !window.tmsSysConfig.fileViewUrl) return;

            let $a = $(event.currentTarget);

            if ($a.children('.tms-file-online-view-wrapper').length === 0) {
                $a.append(`<span class="tms-file-online-view-wrapper"><i class="unhide large black link icon" title="在线文件预览"></i></span>`);
            }

        });

        $('body').on('click', '.tms-file-online-view-wrapper i.unhide.icon', event => {
            event.preventDefault();

            if (!window.tmsSysConfig || !window.tmsSysConfig.fileViewUrl) return;

            let $item = $(event.currentTarget);

            let $a = $item.closest('a');

            if ($a.length === 0) return;

            let url = `${$a.attr('href')}?fullfilename=${$a.text()}`;

            window.open(`${window.tmsSysConfig.fileViewUrl}/onlinePreview?url=` + encodeURIComponent(url));
        });

    }

    /**
     * 当数据绑定引擎从视图解除绑定时被调用
     */
    unbind() {
        this.subscribe.dispose();
    }

    init() {

        $.fn.dropdown.settings.forceSelection = false;

        // ui form 验证提示信息国际化
        _.extend($.fn.form.settings.prompt, {
            empty: '{name}不能为空',
            checked: '{name}必须被勾选',
            email: '{name}必须是正确的邮件格式',
            url: '{name}必须是正确的URL格式',
            regExp: '{name}验证格式不正确',
            integer: '{name}必须为一个整数',
            decimal: '{name}必须为一个小数',
            number: '{name}必须设置为一个数字',
            is: '{name}必须符合规则"{ruleValue}"',
            isExactly: '{name}必须精确匹配"{ruleValue}"',
            not: '{name}不能设置为"{ruleValue}"',
            notExactly: '{name}不能准确设置为"{ruleValue}"',
            contain: '{name}需要包含"{ruleValue}"',
            containExactly: '{name}需要精确包含"{ruleValue}"',
            doesntContain: '{name}不能包含"{ruleValue}"',
            doesntContainExactly: '{name}不能精确包含"{ruleValue}"',
            minLength: '{name}必须至少包含{ruleValue}个字符',
            length: '{name}必须为{ruleValue}个字符',
            exactLength: '{name}必须为{ruleValue}个字符',
            maxLength: '{name}必须不能超过{ruleValue}个字符',
            match: '{name}必须匹配{ruleValue}字段',
            different: '{name}必须不同于{ruleValue}字段',
            creditCard: '{name}必须是一个正确的信用卡数字格式',
            minCount: '{name}必须至少包含{ruleValue}个选择项',
            exactCount: '{name}必须准确包含{ruleValue}个选择项',
            maxCount: '{name} 必须有{ruleValue}或者更少个选择项'
        });
    }

    initCalendar() {
        $.fn.calendar.settings.text = {
            days: ['日', '一', '二', '三', '四', '五', '六'],
            months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
            monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
            today: '今天',
            now: '现在',
            am: '上午',
            pm: '下午'
        };

        $.fn.calendar.settings.formatter.date = function(date, settings) {
            if (!date) return '';
            var day = date.getDate();
            var month = date.getMonth() + 1;
            var year = date.getFullYear();
            // return year + '/' + month + '/' + day;
            return $.format.date(date, 'yyyy-MM-dd');
        };

        return this;
    }

    /**
     * 配置路由
     * @param  {[object]} config 路由配置
     * @param  {[object]} router 路由
     */
    configureRouter(config, router) {

        let chatTo = null;
        if (localStorage) {
            chatTo = localStorage.getItem(nsCons.KEY_REMEMBER_LAST_CHAT_TO);
        }

        config.map([{
            route: ['pwd-reset'],
            name: 'reset',
            moduleId: 'user/user-pwd-reset',
            nav: false,
            title: '密码重置 | TMS'
        }, {
            route: ['register'],
            name: 'register',
            moduleId: 'user/user-register',
            nav: false,
            title: '用户注册 | TMS'
        }, {
            route: ['chat/:username'],
            name: 'chat',
            moduleId: 'chat/chat',
            nav: false,
            title: '私聊 | TMS'
        }, {
            route: ['blog'],
            name: 'chat',
            moduleId: 'blog/blog',
            nav: false,
            title: '博文 | TMS'
        }, {
            route: ['blog/:id'],
            name: 'chat',
            moduleId: 'blog/blog',
            nav: false,
            title: '博文 | TMS'
        }, {
            route: ['login'],
            name: 'login',
            moduleId: 'user/user-login',
            nav: false,
            title: '登录 | TMS'
        }, {
            route: ['test'],
            name: 'test',
            moduleId: 'test/test-lifecycle',
            nav: false,
            title: '测试 | TMS'
        }, {
            route: '',
            redirect: `chat/${chatTo ? chatTo : '@admin'}`
        }]);

        this.router = router;

    }

    /**
     * 在视图模型(ViewModel)展示前执行一些自定义代码逻辑
     * @param  {[object]} params                参数
     * @param  {[object]} routeConfig           路由配置
     * @param  {[object]} navigationInstruction 导航指令
     * @return {[promise]}                      你可以可选的返回一个延迟许诺(promise), 告诉路由等待执行bind和attach视图(view), 直到你完成你的处理工作.
     */
    activate(params, routeConfig, navigationInstruction) {

    }
}
<commit_msg>表格导出替换csv为excel<commit_after>import 'tms-semantic-ui';
import 'semantic-ui-calendar';
import 'jquery-format';

export class App {

    constructor() {
        this.init();
        this.initCalendar();

        this.subscribe = ea.subscribe(nsCons.EVENT_APP_ROUTER_NAVIGATE, (payload) => {
            this.router && this.router.navigate(`${payload.to}`);
        });
    }

    attached() {

        // table export
        $('body').on('mouseenter', '.markdown-body table', (event) => {
            event.preventDefault();

            let $table = $(event.currentTarget);

            if (!$table.parent().is('.export-table-wrapper')) {

                let uid = new Date().getTime();

                $table.attr('id', `export-table-${uid}`);

                $table.wrap(`<div class="export-table-wrapper"></div>`);

                $table.after($(`<i class="export-btn download link icon" title="下载表格文件"></i>`));
            }

            $table.parent().children('.export-btn').show();

        });

        $('body').on('mouseleave', '.markdown-body table', (event) => {
            event.preventDefault();

            if ($(event.toElement).is('.export-btn')) return;

            let $table = $(event.currentTarget);

            if ($table.parent().is('.export-table-wrapper')) {
                $table.parent().children('.export-btn').hide();
            }

        });

        $('body').on('click', '.markdown-body .export-table-wrapper .export-btn', event => {
            event.preventDefault();
            let $item = $(event.currentTarget);

            let sheet = XLSX.utils.table_to_sheet($item.parents('.export-table-wrapper').children('table')[0]);
            var out = XLSX.utils.book_new();
            XLSX.utils.book_append_sheet(out, sheet, `data`);
            XLSX.writeFile(out, `tms-export-table_${$.format.date(new Date(), "yyyy-MM-dd_hhmmss")}.xlsx`);

            // tableExport($item.parents('.export-table-wrapper').children('table').attr('id'), `tms-export-table_${$.format.date(new Date(), "yyyy-MM-dd_hhmmss") }`, 'csv');
        });

        $('body').on('click', '.markdown-body li.task-item input:checkbox', event => {

            let $item = $(event.currentTarget);

            let $md = $item.parents('.markdown-body[data-case]');

            if (!$md || $md.length == 0) {
                event.preventDefault();
                return;
            }

            let $items = $md.find('li.task-item input:checkbox');

            ea.publish(nsCons.EVENT_MARKDOWN_TASK_ITEM_STATUS_TOGGLE, {
                event: event,
                id: $md.attr('data-id'),
                case: $md.attr('data-case'),
                from: $md.attr('data-from'),
                index: $items.index($item)
            });

        });

        // file online preview
        $('body').on('mouseenter', '.markdown-body a[href*="admin/file/download/"],a.tms-file-download-item', (event) => {
            event.preventDefault();

            if (!window.tmsSysConfig || !window.tmsSysConfig.fileViewUrl) return;

            let $a = $(event.currentTarget);

            if ($a.children('.tms-file-online-view-wrapper').length === 0) {
                $a.append(`<span class="tms-file-online-view-wrapper"><i class="unhide large black link icon" title="在线文件预览"></i></span>`);
            }

        });

        $('body').on('click', '.tms-file-online-view-wrapper i.unhide.icon', event => {
            event.preventDefault();

            if (!window.tmsSysConfig || !window.tmsSysConfig.fileViewUrl) return;

            let $item = $(event.currentTarget);

            let $a = $item.closest('a');

            if ($a.length === 0) return;

            let url = `${$a.attr('href')}?fullfilename=${$a.text()}`;

            window.open(`${window.tmsSysConfig.fileViewUrl}/onlinePreview?url=` + encodeURIComponent(url));
        });

    }

    /**
     * 当数据绑定引擎从视图解除绑定时被调用
     */
    unbind() {
        this.subscribe.dispose();
    }

    init() {

        $.fn.dropdown.settings.forceSelection = false;

        // ui form 验证提示信息国际化
        _.extend($.fn.form.settings.prompt, {
            empty: '{name}不能为空',
            checked: '{name}必须被勾选',
            email: '{name}必须是正确的邮件格式',
            url: '{name}必须是正确的URL格式',
            regExp: '{name}验证格式不正确',
            integer: '{name}必须为一个整数',
            decimal: '{name}必须为一个小数',
            number: '{name}必须设置为一个数字',
            is: '{name}必须符合规则"{ruleValue}"',
            isExactly: '{name}必须精确匹配"{ruleValue}"',
            not: '{name}不能设置为"{ruleValue}"',
            notExactly: '{name}不能准确设置为"{ruleValue}"',
            contain: '{name}需要包含"{ruleValue}"',
            containExactly: '{name}需要精确包含"{ruleValue}"',
            doesntContain: '{name}不能包含"{ruleValue}"',
            doesntContainExactly: '{name}不能精确包含"{ruleValue}"',
            minLength: '{name}必须至少包含{ruleValue}个字符',
            length: '{name}必须为{ruleValue}个字符',
            exactLength: '{name}必须为{ruleValue}个字符',
            maxLength: '{name}必须不能超过{ruleValue}个字符',
            match: '{name}必须匹配{ruleValue}字段',
            different: '{name}必须不同于{ruleValue}字段',
            creditCard: '{name}必须是一个正确的信用卡数字格式',
            minCount: '{name}必须至少包含{ruleValue}个选择项',
            exactCount: '{name}必须准确包含{ruleValue}个选择项',
            maxCount: '{name} 必须有{ruleValue}或者更少个选择项'
        });
    }

    initCalendar() {
        $.fn.calendar.settings.text = {
            days: ['日', '一', '二', '三', '四', '五', '六'],
            months: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
            monthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
            today: '今天',
            now: '现在',
            am: '上午',
            pm: '下午'
        };

        $.fn.calendar.settings.formatter.date = function (date, settings) {
            if (!date) return '';
            var day = date.getDate();
            var month = date.getMonth() + 1;
            var year = date.getFullYear();
            // return year + '/' + month + '/' + day;
            return $.format.date(date, 'yyyy-MM-dd');
        };

        return this;
    }

    /**
     * 配置路由
     * @param  {[object]} config 路由配置
     * @param  {[object]} router 路由
     */
    configureRouter(config, router) {

        let chatTo = null;
        if (localStorage) {
            chatTo = localStorage.getItem(nsCons.KEY_REMEMBER_LAST_CHAT_TO);
        }

        config.map([{
            route: ['pwd-reset'],
            name: 'reset',
            moduleId: 'user/user-pwd-reset',
            nav: false,
            title: '密码重置 | TMS'
        }, {
            route: ['register'],
            name: 'register',
            moduleId: 'user/user-register',
            nav: false,
            title: '用户注册 | TMS'
        }, {
            route: ['chat/:username'],
            name: 'chat',
            moduleId: 'chat/chat',
            nav: false,
            title: '私聊 | TMS'
        }, {
            route: ['blog'],
            name: 'chat',
            moduleId: 'blog/blog',
            nav: false,
            title: '博文 | TMS'
        }, {
            route: ['blog/:id'],
            name: 'chat',
            moduleId: 'blog/blog',
            nav: false,
            title: '博文 | TMS'
        }, {
            route: ['login'],
            name: 'login',
            moduleId: 'user/user-login',
            nav: false,
            title: '登录 | TMS'
        }, {
            route: ['test'],
            name: 'test',
            moduleId: 'test/test-lifecycle',
            nav: false,
            title: '测试 | TMS'
        }, {
            route: '',
            redirect: `chat/${chatTo ? chatTo : '@admin'}`
        }]);

        this.router = router;

    }

    /**
     * 在视图模型(ViewModel)展示前执行一些自定义代码逻辑
     * @param  {[object]} params                参数
     * @param  {[object]} routeConfig           路由配置
     * @param  {[object]} navigationInstruction 导航指令
     * @return {[promise]}                      你可以可选的返回一个延迟许诺(promise), 告诉路由等待执行bind和attach视图(view), 直到你完成你的处理工作.
     */
    activate(params, routeConfig, navigationInstruction) {

    }
}
<|endoftext|>


<commit_before>const _string2slug = (str='') => {
    str = str.replace(/^\s+|\s+$/g, ''); // trim
    str = str.toLowerCase();

    // remove accents, swap ñ for n, etc
    var from = "ãàáäâẽèéëêìíïîõòóöôùúüûñç·/_,:;";
    var to   = "aaaaaeeeeeiiiiooooouuuunc------";
    for (var i=0, l=from.length ; i<l ; i++) {
        str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
    }

    str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
        .replace(/\s+/g, '-') // collapse whitespace and replace by -
        .replace(/-+/g, '-'); // collapse dashes

    return str;
};

const _userEmail = (id=Meteor.userId()) => {
    const user = Meteor.users.findOne(id);
    if (user && user.emails && user.emails.length>0 && user.emails[0] && user.emails[0].address) {
        return user.emails[0].address;
    } else {
        return '';
    }
};

const _userZarazi = () => {
    return Modules.both.utilities.userEmail()==='zarazi@gmail.com';
}

const _userName = (id) => {
    let email = _userEmail(id);
    return email.split('@')[0];
}

Modules.both.utilities = {};
Modules.both.utilities.string2slug = _string2slug;
Modules.both.utilities.userEmail = _userEmail;
Modules.both.utilities.userZarazi = _userZarazi;
Modules.both.utilities.userName = _userName;<commit_msg>Fix invalid userEmail().<commit_after>const _string2slug = (str='') => {
    str = str.replace(/^\s+|\s+$/g, ''); // trim
    str = str.toLowerCase();

    // remove accents, swap ñ for n, etc
    var from = "ãàáäâẽèéëêìíïîõòóöôùúüûñç·/_,:;";
    var to   = "aaaaaeeeeeiiiiooooouuuunc------";
    for (var i=0, l=from.length ; i<l ; i++) {
        str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
    }

    str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
        .replace(/\s+/g, '-') // collapse whitespace and replace by -
        .replace(/-+/g, '-'); // collapse dashes

    return str;
};

const _userEmail = (id) => {
    const user = Meteor.users.findOne(id);
    if (user && user.emails && user.emails.length>0 && user.emails[0] && user.emails[0].address) {
        return user.emails[0].address;
    } else {
        return '';
    }
};

const _userZarazi = () => {
    return Modules.both.utilities.userEmail(Meteor.userId())==='zarazi@gmail.com';
}

const _userName = (id) => {
    let email = _userEmail(id);
    return email.split('@')[0];
}

Modules.both.utilities = {};
Modules.both.utilities.string2slug = _string2slug;
Modules.both.utilities.userEmail = _userEmail;
Modules.both.utilities.userZarazi = _userZarazi;
Modules.both.utilities.userName = _userName;<|endoftext|>


<commit_before>/*
 * Created for OpenROV:  www.openrov.com
 * Author:  Bran Sorem (www.bransorem.com)
 * Date: 04/21/12
 *
 * Description:
 * This script is the Node.js server for OpenROV.  It creates a server and instantiates an OpenROV
 * and sets the interval to grab frames.  The interval is set with the DELAY variable which is in
 * milliseconds.
 *
 * License
 * This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a
 * letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
 */

var express = require('express');

var app = express.createServer(express.static(__dirname + '/static'))
  , io = require('socket.io').listen(app)
  , fs = require('fs')
  , OpenROVCamera = require('./lib/OpenROVCamera')
  , OpenROVController = require('./lib/OpenROVController')
  ;

var CONFIG = require('./lib/config');

var DELAY = Math.round(1000 / CONFIG.video_frame_rate);
var camera = new OpenROVCamera({delay : DELAY});
var controller = new OpenROVController();

app.get('/config.js', function(req, res) {
  res.send('var CONFIG = ' + JSON.stringify(CONFIG));
});

// no debug messages
io.configure(function(){ io.set('log level', 1); });

var connections = 0;
// SOCKET connection ==============================
io.sockets.on('connection', function (socket) {
  connections++;

  socket.send('initialize');  // opens socket with client

  socket.on('control_update', function(controls) {
    controller.sendCommand(controls.throttle, controls.yaw, controls.lift);
  });
  camera.capture(function(err) {
    if (err) {
      connections--;
      camera.close();
      return console.error('couldn\'t initialize camera. got:', err);
    }
    // when frame emits, send it
    camera.on('frame', function(img){
      if (CONFIG.debug) console.log('emitting frame')
      socket.volatile.emit('frame', img);
    });
  });
});

// SOCKET disconnection ==============================
io.sockets.on('disconnect', function(socket){
  connections--;
  if(connections === 0) rov.close();
});

camera.on('error.device', function(err) {
  console.error('camera emitted an error:', err);
});

process.on('SIGTERM', function() {
  console.error('got SIGTERM, shutting down...');
  camera.close();
  process.exit(0);
});

process.on('SIGINT', function() {
  console.error('got SIGINT, shutting down...');
  camera.close();
  process.exit(0);
})

app.listen(CONFIG.port);<commit_msg>setup logging<commit_after>/*
 * Created for OpenROV:  www.openrov.com
 * Author:  Bran Sorem (www.bransorem.com)
 * Date: 04/21/12
 *
 * Description:
 * This script is the Node.js server for OpenROV.  It creates a server and instantiates an OpenROV
 * and sets the interval to grab frames.  The interval is set with the DELAY variable which is in
 * milliseconds.
 *
 * License
 * This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a
 * letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
 */

var express = require('express');

var app = express.createServer(express.static(__dirname + '/static'))
  , io = require('socket.io').listen(app)
  , fs = require('fs')
  , OpenROVCamera = require('./lib/OpenROVCamera')
  , OpenROVController = require('./lib/OpenROVController')
  ;

var CONFIG = require('./lib/config');

var DELAY = Math.round(1000 / CONFIG.video_frame_rate);
var camera = new OpenROVCamera({delay : DELAY});
var controller = new OpenROVController();

app.get('/config.js', function(req, res) {
  res.send('var CONFIG = ' + JSON.stringify(CONFIG));
});

// no debug messages
io.configure(function(){ io.set('log level', 1); });

var connections = 0;
// SOCKET connection ==============================
io.sockets.on('connection', function (socket) {
  connections++;

  socket.send('initialize');  // opens socket with client

  socket.on('control_update', function(controls) {
    controller.sendCommand(controls.throttle, controls.yaw, controls.lift);
  });
  camera.capture(function(err) {
    if (err) {
      connections--;
      camera.close();
      return console.error('couldn\'t initialize camera. got:', err);
    }

    console.log('initialized camera, adding listener for \'frame\' event');
    // when frame emits, send it
    camera.on('frame', function(img){
      if (CONFIG.debug) console.log('emitting frame')
      socket.volatile.emit('frame', img);
    });
  });
});

// SOCKET disconnection ==============================
io.sockets.on('disconnect', function(socket){
  connections--;
  if(connections === 0) rov.close();
});

camera.on('error.device', function(err) {
  console.error('camera emitted an error:', err);
});

process.on('SIGTERM', function() {
  console.error('got SIGTERM, shutting down...');
  camera.close();
  process.exit(0);
});

process.on('SIGINT', function() {
  console.error('got SIGINT, shutting down...');
  camera.close();
  process.exit(0);
})

app.listen(CONFIG.port);<|endoftext|>


<commit_before>import {run} from '@cycle/core';
import CycleDOM from '@cycle/dom';
import {Observable} from 'rx';
import storageDriver from '@cycle/storage';
// THE MAIN FUNCTION
// This is the todo list component.
import Todos from './components/Todos/index';

const main = Todos;

// THE ENTRY POINT
// This is where the whole story starts.
// `run` receives a main function and an object
// with the drivers.
run(main, {
  // THE DOM DRIVER
  // We create a DOM driver by passing
  // a DOM selector to the `makeDOMDriver` function.
  DOM: CycleDOM.makeDOMDriver('.todoapp'),
  // THE INITAL HASH STREAM
  // A stream that only delivers the initial hash value.
  initialHash: () => Observable.just(window.location.hash),
  // THE HASH CHANGE STREAM
  // A stream that delivers the hash value on the hashChange event.
  hashchange: () => Observable.fromEvent(window, 'hashchange'),
  // THE STORAGE DRIVER
  // The storage driver which can be used to access values for
  // local- and sessionStorage keys as streams.
  storage: storageDriver
});
<commit_msg>comment fix<commit_after>import {run} from '@cycle/core';
import CycleDOM from '@cycle/dom';
import {Observable} from 'rx';
import storageDriver from '@cycle/storage';
// THE MAIN FUNCTION
// This is the todo list component.
import Todos from './components/Todos/index';

const main = Todos;

// THE ENTRY POINT
// This is where the whole story starts.
// `run` receives a main function and an object
// with the drivers.
run(main, {
  // THE DOM DRIVER
  // `makeDOMDriver(container)` from Cycle DOM returns a
  // driver function to interact with the DOM.
  DOM: CycleDOM.makeDOMDriver('.todoapp'),
  // THE INITAL HASH STREAM
  // A stream that only delivers the initial hash value.
  initialHash: () => Observable.just(window.location.hash),
  // THE HASH CHANGE STREAM
  // A stream that delivers the hash value on the hashChange event.
  hashchange: () => Observable.fromEvent(window, 'hashchange'),
  // THE STORAGE DRIVER
  // The storage driver which can be used to access values for
  // local- and sessionStorage keys as streams.
  storage: storageDriver
});
<|endoftext|>


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

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

  function init () {

    grunt.initConfig({
      availabletasks: {
        tasks: {
          options: {
            descriptions: {
              'help': 'Task list helper for your Grunt enabled projects.',
              'clean': 'Deletes the content of the dist directory.',
              'build': 'Builds the project (including documentation) into the dist directory. You can specify modules to be built as arguments (' +
                'grunt build:buttons:notification) otherwise all available modules are built.',
              'test': 'Executes the karma testsuite.',
              'watch': 'Whenever js source files (from the src directory) change, the tasks executes jslint and documentation build.',
              'ngdocs': 'Builds documentation into dist/docs.',
              'ngdocs:view': 'Builds documentation into dist/docs and runs a web server. The docs can be accessed on http://localhost:8000/'
            },
            groups: {
              'Basic project tasks': ['help', 'clean', 'build', 'test'],
              'Documentation tasks': ['ngdocs', 'ngdocs:view']
            }
          }
        }
      },
      clean: {
        docs: ['dist/docs'],
        templates: ['templates/'],
        all: ['dist/*']
      },
      concat: {
        options: {
          separator: ';'
        },
        dist: {
          src: ['src/**/*.module.js', 'src/**/*.js', 'templates/*.js'],
          dest: 'dist/angular-patternfly.js'
        }
      },
      connect: {
        docs: {
          options: {
            base: 'dist/docs',
            livereload: true,
            open: true
          }
        }
      },
      copy: {
        docdata: {
          cwd: 'lib/patternfly/dist',
          src: ['fonts/*', 'img/*'],
          dest: 'dist/docs',
          expand: true
        },
        fa: {
          cwd: 'lib/patternfly/',
          src: ['components/font-awesome/**'],
          dest: 'dist/docs',
          expand: true
        },
        styles: {
          cwd: 'styles/',
          src: ['*.css', '!*.min.css'],
          dest: 'dist/styles',
          expand: true
        },
        img: {
          cwd: 'misc/',
          src: 'patternfly-orb.svg',
          dest: 'dist/docs/img',
          expand: true
        }
      },
      cssmin: {
        target: {
          files: [{
            expand: true,
            cwd: 'styles',
            src: ['*.css', '!*.min.css'],
            dest: 'dist/styles',
            ext: '.min.css'
          }]
        }
      },
      htmlhint: {
        html: {
          src: ['src/**/*.html'],
          options: {
            htmlhintrc: '.htmlhintrc'
          }
        }
      },
      eslint: {
        options: {
          configFile: 'eslint.yaml'
        },
        target: [
          'Gruntfile.js',
          'src/**/*.js'
        ]
      },
      karma: {
        unit: {
          configFile: 'test/karma.conf.js',
          singleRun: true,
          browsers: ['PhantomJS']
        }
      },
      ngdocs: {
        options: {
          title: 'Angular Patternfly Documentation',
          dest: 'dist/docs',
          image: 'misc/logo-alt.svg',
          scripts: ['lib/patternfly/components/jquery/dist/jquery.js',
            'lib/patternfly/components/bootstrap/dist/js/bootstrap.js',
            'lib/patternfly/components/bootstrap-combobox/js/bootstrap-combobox.js',
            'lib/patternfly/components/bootstrap-datepicker/dist/js/bootstrap-datepicker.js',
            'lib/patternfly/components/bootstrap-select/js/bootstrap-select.js',
            'lib/patternfly/components/bootstrap-treeview/src/js/bootstrap-treeview.js',
            'lib/patternfly/components/c3/c3.js',
            'lib/patternfly/components/d3/d3.js',
            'lib/angular/angular.js',
            'lib/angular-animate/angular-animate.js',
            'lib/angular-bootstrap/ui-bootstrap-tpls.js',
            'misc/angular-bootstrap-prettify.js',
            'lib/lodash/lodash.min.js',
            'dist/angular-patternfly.js',
            'lib/patternfly/dist/js/patternfly.js'],
          html5Mode: false,
          template: 'grunt-ngdocs-index.tmpl',
          styles: ['lib/patternfly/dist/css/patternfly.css', 'lib/patternfly/dist/css/patternfly-additions.css',
            'dist/styles/angular-patternfly.css', 'misc/ng-docs.css', 'misc/examples.css']
        },

        all: ['src/**/*.js']
      },
      ngtemplates: {
        options: {
          htmlmin: {
            collapseBooleanAttributes:      true,
            collapseWhitespace:             true,
            removeAttributeQuotes:          true,
            removeComments:                 false,
            removeEmptyAttributes:          true,
            removeRedundantAttributes:      true,
            removeScriptTypeAttributes:     true,
            removeStyleLinkTypeAttributes:  true
          }
        },
        'patternfly.form': {
          cwd: 'src/',
          src: ['form/**/*.html'],
          dest: 'templates/form.js'
        },
        'patternfly.notification': {
          cwd: 'src/',
          src: ['notification/**/*.html'],
          dest: 'templates/notification.js'
        },
        'patternfly.card': {
          cwd: 'src/',
          src: ['card/**/*.html'],
          dest: 'templates/card.js'
        },
        'patternfly.charts': {
          cwd: 'src/',
          src: ['charts/**/*.html'],
          dest: 'templates/charts.js'
        },
        'patternfly.filters': {
          cwd: 'src/',
          src: ['filters/**/*.html'],
          dest: 'templates/filters.js'
        },
        'patternfly.sort': {
          cwd: 'src/',
          src: ['sort/**/*.html'],
          dest: 'templates/sort.js'
        },
        'patternfly.views': {
          cwd: 'src/',
          src: ['views/**/*.html'],
          dest: 'templates/views.js'
        }
      },
      // ng-annotate tries to make the code safe for minification automatically
      // by using the Angular long form for dependency injection.
      ngAnnotate: {
        dist: {
          files: [{
            src: 'dist/angular-patternfly.js',
            dest: 'dist/angular-patternfly.js'
          }]
        }
      },
      uglify: {
        options: {
          mangle: false
        },
        build: {
          files: {},
          src: 'dist/angular-patternfly.js',
          dest: 'dist/angular-patternfly.min.js'
        }
      },
      watch: {
        main: {
          files: ['Gruntfile.js'],
          tasks: ['eslint']
        },
        all: {
          files: ['Gruntfile.js', 'src/**/*.js', 'src/**/*.html', 'styles/**/*.css'],
          tasks: ['build'],
          options: {
            livereload: true
          }
        }
      }
    });

    // You can specify which modules to build as arguments of the build task.
    grunt.registerTask('build', 'Create bootstrap build files', function () {
      var concatSrc = [];

      if (this.args.length) {
        this.args.forEach(function (file) {
          if (grunt.file.exists('./src/' + file)) {
            grunt.log.ok('Adding ' + file + ' to the build queue.');
            concatSrc.push('src/' + file + '/*.js');
          } else {
            grunt.fail.warn('Unable to build module \'' + file + '\'. The module doesn\'t exist.');
          }
        });

      } else {
        concatSrc = 'src/**/*.js';
      }

      grunt.task.run(['clean', 'lint', 'test', 'ngtemplates', 'concat', 'ngAnnotate', 'uglify:build', 'cssmin', 'copy', 'ngdocs', 'clean:templates']);
    });

    // Runs all the tasks of build with the exception of tests
    grunt.registerTask('deploy', 'Prepares the project for deployment. Does not run unit tests', function () {
      var concatSrc = 'src/**/*.js';
      grunt.task.run(['clean', 'lint', 'ngtemplates', 'concat', 'ngAnnotate', 'uglify:build', 'cssmin', 'copy', 'ngdocs', 'clean:templates']);
    });

    grunt.registerTask('default', ['build']);
    grunt.registerTask('ngdocs:view', ['build', 'connect:docs', 'watch']);
    grunt.registerTask('lint', ['eslint', 'htmlhint']);
    grunt.registerTask('test', ['karma']);
    grunt.registerTask('check', ['lint', 'test']);
    grunt.registerTask('help', ['availabletasks']);

  }

  init({});

};
<commit_msg>Changes to allow outside access to dev urls, and changed livereload port to avoid conflicts with other servers.<commit_after>module.exports = function (grunt) {
  'use strict';

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

  function init () {

    grunt.initConfig({
      availabletasks: {
        tasks: {
          options: {
            descriptions: {
              'help': 'Task list helper for your Grunt enabled projects.',
              'clean': 'Deletes the content of the dist directory.',
              'build': 'Builds the project (including documentation) into the dist directory. You can specify modules to be built as arguments (' +
                'grunt build:buttons:notification) otherwise all available modules are built.',
              'test': 'Executes the karma testsuite.',
              'watch': 'Whenever js source files (from the src directory) change, the tasks executes jslint and documentation build.',
              'ngdocs': 'Builds documentation into dist/docs.',
              'ngdocs:view': 'Builds documentation into dist/docs and runs a web server. The docs can be accessed on http://localhost:8000/'
            },
            groups: {
              'Basic project tasks': ['help', 'clean', 'build', 'test'],
              'Documentation tasks': ['ngdocs', 'ngdocs:view']
            }
          }
        }
      },
      clean: {
        docs: ['dist/docs'],
        templates: ['templates/'],
        all: ['dist/*']
      },
      concat: {
        options: {
          separator: ';'
        },
        dist: {
          src: ['src/**/*.module.js', 'src/**/*.js', 'templates/*.js'],
          dest: 'dist/angular-patternfly.js'
        }
      },
      connect: {
        docs: {
          options: {
            hostname: '0.0.0.0',
            base: 'dist/docs',
            livereload: true,
            open: true
          }
        }
      },
      copy: {
        docdata: {
          cwd: 'lib/patternfly/dist',
          src: ['fonts/*', 'img/*'],
          dest: 'dist/docs',
          expand: true
        },
        fa: {
          cwd: 'lib/patternfly/',
          src: ['components/font-awesome/**'],
          dest: 'dist/docs',
          expand: true
        },
        styles: {
          cwd: 'styles/',
          src: ['*.css', '!*.min.css'],
          dest: 'dist/styles',
          expand: true
        },
        img: {
          cwd: 'misc/',
          src: 'patternfly-orb.svg',
          dest: 'dist/docs/img',
          expand: true
        }
      },
      cssmin: {
        target: {
          files: [{
            expand: true,
            cwd: 'styles',
            src: ['*.css', '!*.min.css'],
            dest: 'dist/styles',
            ext: '.min.css'
          }]
        }
      },
      htmlhint: {
        html: {
          src: ['src/**/*.html'],
          options: {
            htmlhintrc: '.htmlhintrc'
          }
        }
      },
      eslint: {
        options: {
          configFile: 'eslint.yaml'
        },
        target: [
          'Gruntfile.js',
          'src/**/*.js'
        ]
      },
      karma: {
        unit: {
          configFile: 'test/karma.conf.js',
          singleRun: true,
          browsers: ['PhantomJS']
        }
      },
      ngdocs: {
        options: {
          title: 'Angular Patternfly Documentation',
          dest: 'dist/docs',
          image: 'misc/logo-alt.svg',
          scripts: ['lib/patternfly/components/jquery/dist/jquery.js',
            'lib/patternfly/components/bootstrap/dist/js/bootstrap.js',
            'lib/patternfly/components/bootstrap-combobox/js/bootstrap-combobox.js',
            'lib/patternfly/components/bootstrap-datepicker/dist/js/bootstrap-datepicker.js',
            'lib/patternfly/components/bootstrap-select/js/bootstrap-select.js',
            'lib/patternfly/components/bootstrap-treeview/src/js/bootstrap-treeview.js',
            'lib/patternfly/components/c3/c3.js',
            'lib/patternfly/components/d3/d3.js',
            'lib/angular/angular.js',
            'lib/angular-animate/angular-animate.js',
            'lib/angular-bootstrap/ui-bootstrap-tpls.js',
            'misc/angular-bootstrap-prettify.js',
            'lib/lodash/lodash.min.js',
            'dist/angular-patternfly.js',
            'lib/patternfly/dist/js/patternfly.js'],
          html5Mode: false,
          template: 'grunt-ngdocs-index.tmpl',
          styles: ['lib/patternfly/dist/css/patternfly.css', 'lib/patternfly/dist/css/patternfly-additions.css',
            'dist/styles/angular-patternfly.css', 'misc/ng-docs.css', 'misc/examples.css']
        },

        all: ['src/**/*.js']
      },
      ngtemplates: {
        options: {
          htmlmin: {
            collapseBooleanAttributes:      true,
            collapseWhitespace:             true,
            removeAttributeQuotes:          true,
            removeComments:                 false,
            removeEmptyAttributes:          true,
            removeRedundantAttributes:      true,
            removeScriptTypeAttributes:     true,
            removeStyleLinkTypeAttributes:  true
          }
        },
        'patternfly.form': {
          cwd: 'src/',
          src: ['form/**/*.html'],
          dest: 'templates/form.js'
        },
        'patternfly.notification': {
          cwd: 'src/',
          src: ['notification/**/*.html'],
          dest: 'templates/notification.js'
        },
        'patternfly.card': {
          cwd: 'src/',
          src: ['card/**/*.html'],
          dest: 'templates/card.js'
        },
        'patternfly.charts': {
          cwd: 'src/',
          src: ['charts/**/*.html'],
          dest: 'templates/charts.js'
        },
        'patternfly.filters': {
          cwd: 'src/',
          src: ['filters/**/*.html'],
          dest: 'templates/filters.js'
        },
        'patternfly.sort': {
          cwd: 'src/',
          src: ['sort/**/*.html'],
          dest: 'templates/sort.js'
        },
        'patternfly.views': {
          cwd: 'src/',
          src: ['views/**/*.html'],
          dest: 'templates/views.js'
        }
      },
      // ng-annotate tries to make the code safe for minification automatically
      // by using the Angular long form for dependency injection.
      ngAnnotate: {
        dist: {
          files: [{
            src: 'dist/angular-patternfly.js',
            dest: 'dist/angular-patternfly.js'
          }]
        }
      },
      uglify: {
        options: {
          mangle: false
        },
        build: {
          files: {},
          src: 'dist/angular-patternfly.js',
          dest: 'dist/angular-patternfly.min.js'
        }
      },
      watch: {
        main: {
          files: ['Gruntfile.js'],
          tasks: ['eslint']
        },
        all: {
          files: ['Gruntfile.js', 'src/**/*.js', 'src/**/*.html', 'styles/**/*.css'],
          tasks: ['build'],
          options: {
            livereload: 35722
          }
        }
      }
    });

    // You can specify which modules to build as arguments of the build task.
    grunt.registerTask('build', 'Create bootstrap build files', function () {
      var concatSrc = [];

      if (this.args.length) {
        this.args.forEach(function (file) {
          if (grunt.file.exists('./src/' + file)) {
            grunt.log.ok('Adding ' + file + ' to the build queue.');
            concatSrc.push('src/' + file + '/*.js');
          } else {
            grunt.fail.warn('Unable to build module \'' + file + '\'. The module doesn\'t exist.');
          }
        });

      } else {
        concatSrc = 'src/**/*.js';
      }

      grunt.task.run(['clean', 'lint', 'test', 'ngtemplates', 'concat', 'ngAnnotate', 'uglify:build', 'cssmin', 'copy', 'ngdocs', 'clean:templates']);
    });

    // Runs all the tasks of build with the exception of tests
    grunt.registerTask('deploy', 'Prepares the project for deployment. Does not run unit tests', function () {
      var concatSrc = 'src/**/*.js';
      grunt.task.run(['clean', 'lint', 'ngtemplates', 'concat', 'ngAnnotate', 'uglify:build', 'cssmin', 'copy', 'ngdocs', 'clean:templates']);
    });

    grunt.registerTask('default', ['build']);
    grunt.registerTask('ngdocs:view', ['build', 'connect:docs', 'watch']);
    grunt.registerTask('lint', ['eslint', 'htmlhint']);
    grunt.registerTask('test', ['karma']);
    grunt.registerTask('check', ['lint', 'test']);
    grunt.registerTask('help', ['availabletasks']);

  }

  init({});

};
<|endoftext|>


<commit_before>import React from 'react'
const el = React.createElement

const selectInput = function ({ options, multiple = false }) {
  if (!multiple) options = [['$null', ""]].concat(options)
  return function ({ value, onChange }) {
    return el('select', {
      multiple,
      value: normalizeValue(value, multiple),
      onChange: (ev) => onChange(normalizeEvent(ev, multiple)),
    }, options.map(op => el('option', {key: op[0], value: op[0]}, op[1])))
  }
}

export default function(arg) {
  let { options, multiple } = arg
  if (!options) {
    options = arg
  }
  return selectInput({
    options,
    multiple,
  })
}

function normalizeValue(val, multiple) {
  return multiple ? normalizeMultiValue(val) : normalizeMonoValue(val)
}

function normalizeMultiValue(value) {
  if (value === undefined) return []
  if (value === null) return []
  return Array.isArray(value) ? value: [value]
}
function normalizeMonoValue(value) {
  return !value ? '$null' : value
}

function normalizeEvent(ev, multiple) {
  return multiple ?
    [...ev.target.selectedOptions].map(opt => opt.value) :
    ev.target.value === '$null' ? null : ev.target.value
}
<commit_msg>formPart select: fix for falsy values<commit_after>import React from 'react'
const el = React.createElement

export const selectInput = function ({ options, multiple = false, nullLabel="" }) {
  if (!multiple) options = [['$null', nullLabel]].concat(options)
  return function ({ value, onChange }) {
    return el('select', {
      multiple,
      value: normalizeValue(value, multiple),
      onChange: (ev) => onChange(normalizeEvent(ev, multiple)),
    }, options.map(op => el('option', {key: op[0], value: op[0]}, op[1])))
  }
}

export default function(arg) {
  let { options, multiple } = arg
  if (!options) {
    options = arg
  }
  return selectInput({
    options,
    multiple,
  })
}

function normalizeValue(val, multiple) {
  return multiple ? normalizeMultiValue(val) : normalizeMonoValue(val)
}

function normalizeMultiValue(value) {
  if (value === undefined) return []
  if (value === null) return []
  return Array.isArray(value) ? value: [value]
}
function normalizeMonoValue(value) {
  return (value === undefined) ? '$null' : value
}

function normalizeEvent(ev, multiple) {
  return multiple ?
    [...ev.target.selectedOptions].map(opt => opt.value) :
    ev.target.value === '$null' ? null : ev.target.value
}
<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var mainBowerFiles = require('gulp-main-bower-files');
var changed = require('gulp-changed');
var stylus = require('gulp-stylus');
var del = require('del');
const babel = require('gulp-babel');

var options = {
  dist: 'www/',
  src: 'src/'
}

gulp.task('clean', function () {
  return del([options.dist + '**/*'], {force:true});
});

gulp.task('build:bower', () => {
  gulp.src('./bower.json')
    .pipe(mainBowerFiles())
    .pipe(changed(options.dist))
    .pipe(gulp.dest(options.dist + '/bower'));
});

gulp.task('build:js', () => {
  return gulp.src(options.src + '/js/**/*.js', {base:options.src})
    // .pipe(babel())
    .pipe(changed(options.dist))
    .pipe(gulp.dest(options.dist));
});

gulp.task('build:css', () => {
  return gulp.src(options.src + '**/*.styl', {base:options.src})
    .pipe(changed(options.dist), {extension: '.css'})
    .pipe(stylus({'include css': true}))
    .pipe(gulp.dest(options.dist));
});

gulp.task('build:html', () => {
  return gulp.src(options.src + '**/*.html', {base:options.src})
    .pipe(changed(options.dist))
    .pipe(gulp.dest(options.dist));
});

gulp.task('build', ['build:bower', 'build:js', 'build:html', 'build:css']);

gulp.task('default', ['build']);
<commit_msg>added babel and image building to the build system<commit_after>'use strict';

var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var mainBowerFiles = require('gulp-main-bower-files');
var changed = require('gulp-changed');
var stylus = require('gulp-stylus');
var del = require('del');
const babel = require('gulp-babel');

var options = {
  dist: 'www/',
  src: 'src/'
}

gulp.task('clean', function () {
  return del([options.dist + '**/*'], {force:true});
});

gulp.task('build:bower', () => {
  gulp.src('./bower.json')
    .pipe(mainBowerFiles())
    .pipe(changed(options.dist))
    .pipe(gulp.dest(options.dist + '/bower'));
});

gulp.task('build:js', () => {
  return gulp.src(options.src + '/js/**/*.js', {base:options.src})
    .pipe(changed(options.dist))
    .pipe(sourcemaps.init())
    .pipe(babel())
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest(options.dist));
});

gulp.task('build:css', () => {
  return gulp.src(options.src + '**/*.styl', {base:options.src})
    .pipe(changed(options.dist), {extension: '.css'})
    .pipe(stylus({'include css': true}))
    .pipe(gulp.dest(options.dist));
});

gulp.task('build:html', () => {
  return gulp.src(options.src + '**/*.html', {base:options.src})
    .pipe(changed(options.dist))
    .pipe(gulp.dest(options.dist));
});

gulp.task('build:img', () => {
  return gulp.src(options.src + 'img/**/*', {base:options.src})
    .pipe(changed(options.dist))
    .pipe(gulp.dest(options.dist));
});

gulp.task('build', ['build:bower', 'build:js', 'build:html', 'build:css', 'build:img']);

gulp.task('default', ['build']);
<|endoftext|>