<commit_before>define(['js/svg/SvgElement', 'xaml!sprd/view/svg/ConfigurationViewer', 'js/core/List'], function (SvgElement, ConfigurationViewer, List) {

    return SvgElement.inherit('sprd.view.svg.PrintAreaViewerClass', {

        defaults: {
            tagName: "g",
            componentClass: "print-area",

            productTypeViewViewer: null,
            product: null,
            productViewer: null,

            snapLines: null,

            snapLinesGroup: null,

            _viewMap: null,

            imageService: null
        },

        $classAttributes: ["product", "productTypeViewViewer", "productViewer", "snapLines", "snapLinesGroup", "imageService"],

        ctor: function () {

            this.$configurationViewerCache = {};
            this.callBase();
        },

        _commitProductViewer: function(productViewer) {

            if (productViewer && productViewer.$.editable) {
                this.$.snapLines = new List();
            } else {
                this.$.snapLines = null;
            }

        },

        _initializeRenderer: function () {

            // Could be done via binding, but viewMaps don't change at runtime and so just evalulating
            this.translate(this.get("_viewMap.offset.x"), this.get("_viewMap.offset.y"));

            var transformations = this.get("_viewMap.transformations.operations");
            if (transformations) {
                this.$.transformations.add(new SvgElement.Transform({
                    transform: transformations
                }));
            }

            var border = this.createComponent(SvgElement, {
                tagName: "rect",
                componentClass: "print-area-border",
                width: this.get('_viewMap.printArea.boundary.size.width'),
                height: this.get('_viewMap.printArea.boundary.size.height')
            });

            var softBoundary = this.get("_viewMap.printArea.boundary.soft.content.svg.path.d");

            if (softBoundary) {
                softBoundary = this.createComponent(SvgElement, {
                    tagName: "path",
                    componentClass: "soft-boundary-border",
                    d: softBoundary
                });
            }

            var defaultBox = this.get("_viewMap.printArea.defaultBox");
            if (defaultBox) {
                defaultBox = this.createComponent(SvgElement, {
                    tagName: "rect",
                    componentClass: "print-area-default-box",
                    x: defaultBox.x,
                    y: defaultBox.y,
                    width: defaultBox.width,
                    height: defaultBox.height
                });
            }

            this.addChild(border);

            defaultBox && this.addChild(defaultBox);
            softBoundary && this.addChild(softBoundary);

            var productViewer = this.$.productViewer;

            if (productViewer && productViewer.$.editable) {
                this.addChild(this.$.snapLinesGroup);
            }

            this.callBase();
        },

        initialize: function () {
            this.bind('product.configurations', 'add', this._onConfigurationAdded, this);
            this.bind('product.configurations', 'item:change:printArea', this._onConfigurationChanged, this);
            this.bind('product.configurations', 'remove', this._onConfigurationRemoved, this);
            this.bind('product.configurations', 'reset', this._onConfigurationsReset, this);
            this.bind('product', 'change:configurations', this._onConfigurationsReset, this);
            this.callBase();
        },

        _onConfigurationsReset: function (e) {
            var self = this;

            this._removeConfigurationViewer();
            if (this.$.product && this.$.product.$.configurations) {
                this.$.product.$.configurations.each(function (configuration) {
                    self._addConfiguration(configuration);
                });
            }
        },

        _onConfigurationAdded: function (e) {
            this._addConfiguration(e.$.item);
        },

        _onConfigurationRemoved: function (e) {
            this._removeConfiguration(e.$.item);
        },

        _addConfiguration: function (configuration) {

            if (!configuration) {
                return;
            }

            if (!configuration.$.printArea) {
                return;
            }

            if (configuration.$.printArea.$.id !== this.get('_viewMap.printArea.id')) {
                // not for this print area
                return;
            }

            var configurationId = configuration.$cid;

            if (!this.$configurationViewerCache.hasOwnProperty(configurationId)) {
                var viewer = this.$configurationViewerCache[configurationId] = this.createComponent(ConfigurationViewer, {
                    product: this.$.product,
                    printAreaViewer: this,
                    _viewMap: this.get("_viewMap"),
                    productViewer: this.$.productViewer,

                    configuration: configuration,

                    imageService: this.$.imageService
                });

                this.addChild(viewer);

                this.$.productViewer.trigger('add:configurationViewer',viewer);

            }
        },

        getViewerForConfiguration: function (configuration) {
            for (var key in this.$configurationViewerCache) {
                if (this.$configurationViewerCache.hasOwnProperty(key) && (this.$configurationViewerCache[key].$.configuration === configuration)) {
                    return this.$configurationViewerCache[key];
                }
            }
            return null;
        },

        _renderProduct: function (product, oldProduct) {

            if (oldProduct) {
                this._removeConfigurationViewer();
            }

            var self = this;
            if (product && product.$.configurations) {
                product.$.configurations.each(function (configuration) {
                    self._addConfiguration(configuration);
                });
            }
        },

        _removeConfiguration: function (configuration) {

            if (!configuration) {
                return;
            }

            var viewer = this.$configurationViewerCache[configuration.$cid];
            if (viewer) {
                viewer.remove();
                viewer.destroy();
            }
        },

        _removeConfigurationViewer: function () {
            for (var key in this.$configurationViewerCache) {
                if (this.$configurationViewerCache.hasOwnProperty(key)) {
                    var viewer = this.$configurationViewerCache[key];
                    viewer.remove();
                    viewer.destroy();
                }
            }

            this.$configurationViewerCache = {};
        },

        _onConfigurationChanged: function (e) {
            // remove or add
            var configuration = e.$.item;
            if (configuration.$.printArea === this.get('_viewMap.printArea')) {
                this._addConfiguration(configuration);
            } else {
                this._removeConfiguration(configuration);
            }
        }

    });
});<commit_msg>fixed remove ConfigurationViewer<commit_after>define(['js/svg/SvgElement', 'xaml!sprd/view/svg/ConfigurationViewer', 'js/core/List'], function (SvgElement, ConfigurationViewer, List) {

    return SvgElement.inherit('sprd.view.svg.PrintAreaViewerClass', {

        defaults: {
            tagName: "g",
            componentClass: "print-area",

            productTypeViewViewer: null,
            product: null,
            productViewer: null,

            snapLines: null,

            snapLinesGroup: null,

            _viewMap: null,

            imageService: null
        },

        $classAttributes: ["product", "productTypeViewViewer", "productViewer", "snapLines", "snapLinesGroup", "imageService"],

        ctor: function () {

            this.$configurationViewerCache = {};
            this.callBase();
        },

        _commitProductViewer: function(productViewer) {

            if (productViewer && productViewer.$.editable) {
                this.$.snapLines = new List();
            } else {
                this.$.snapLines = null;
            }

        },

        _initializeRenderer: function () {

            // Could be done via binding, but viewMaps don't change at runtime and so just evalulating
            this.translate(this.get("_viewMap.offset.x"), this.get("_viewMap.offset.y"));

            var transformations = this.get("_viewMap.transformations.operations");
            if (transformations) {
                this.$.transformations.add(new SvgElement.Transform({
                    transform: transformations
                }));
            }

            var border = this.createComponent(SvgElement, {
                tagName: "rect",
                componentClass: "print-area-border",
                width: this.get('_viewMap.printArea.boundary.size.width'),
                height: this.get('_viewMap.printArea.boundary.size.height')
            });

            var softBoundary = this.get("_viewMap.printArea.boundary.soft.content.svg.path.d");

            if (softBoundary) {
                softBoundary = this.createComponent(SvgElement, {
                    tagName: "path",
                    componentClass: "soft-boundary-border",
                    d: softBoundary
                });
            }

            var defaultBox = this.get("_viewMap.printArea.defaultBox");
            if (defaultBox) {
                defaultBox = this.createComponent(SvgElement, {
                    tagName: "rect",
                    componentClass: "print-area-default-box",
                    x: defaultBox.x,
                    y: defaultBox.y,
                    width: defaultBox.width,
                    height: defaultBox.height
                });
            }

            this.addChild(border);

            defaultBox && this.addChild(defaultBox);
            softBoundary && this.addChild(softBoundary);

            var productViewer = this.$.productViewer;

            if (productViewer && productViewer.$.editable) {
                this.addChild(this.$.snapLinesGroup);
            }

            this.callBase();
        },

        initialize: function () {
            this.bind('product.configurations', 'add', this._onConfigurationAdded, this);
            this.bind('product.configurations', 'item:change:printArea', this._onConfigurationChanged, this);
            this.bind('product.configurations', 'remove', this._onConfigurationRemoved, this);
            this.bind('product.configurations', 'reset', this._onConfigurationsReset, this);
            this.bind('product', 'change:configurations', this._onConfigurationsReset, this);
            this.callBase();
        },

        _onConfigurationsReset: function (e) {
            var self = this;

            this._removeConfigurationViewer();
            if (this.$.product && this.$.product.$.configurations) {
                this.$.product.$.configurations.each(function (configuration) {
                    self._addConfiguration(configuration);
                });
            }
        },

        _onConfigurationAdded: function (e) {
            this._addConfiguration(e.$.item);
        },

        _onConfigurationRemoved: function (e) {
            this._removeConfiguration(e.$.item);
        },

        _addConfiguration: function (configuration) {

            if (!configuration) {
                return;
            }

            if (!configuration.$.printArea) {
                return;
            }

            if (configuration.$.printArea.$.id !== this.get('_viewMap.printArea.id')) {
                // not for this print area
                return;
            }

            var configurationId = configuration.$cid;

            if (!this.$configurationViewerCache.hasOwnProperty(configurationId)) {
                var viewer = this.$configurationViewerCache[configurationId] = this.createComponent(ConfigurationViewer, {
                    product: this.$.product,
                    printAreaViewer: this,
                    _viewMap: this.get("_viewMap"),
                    productViewer: this.$.productViewer,

                    configuration: configuration,

                    imageService: this.$.imageService
                });

                this.addChild(viewer);

                this.$.productViewer.trigger('add:configurationViewer',viewer);

            }
        },

        getViewerForConfiguration: function (configuration) {
            for (var key in this.$configurationViewerCache) {
                if (this.$configurationViewerCache.hasOwnProperty(key) && (this.$configurationViewerCache[key].$.configuration === configuration)) {
                    return this.$configurationViewerCache[key];
                }
            }
            return null;
        },

        _renderProduct: function (product, oldProduct) {

            if (oldProduct) {
                this._removeConfigurationViewer();
            }

            var self = this;
            if (product && product.$.configurations) {
                product.$.configurations.each(function (configuration) {
                    self._addConfiguration(configuration);
                });
            }
        },

        _removeConfiguration: function (configuration) {

            if (!configuration) {
                return;
            }

            var viewer = this.$configurationViewerCache[configuration.$cid];
            if (viewer) {
                delete this.$configurationViewerCache[configuration.$cid];
                viewer.remove();
                viewer.destroy();
            }
        },

        _removeConfigurationViewer: function () {
            for (var key in this.$configurationViewerCache) {
                if (this.$configurationViewerCache.hasOwnProperty(key)) {
                    var viewer = this.$configurationViewerCache[key];
                    viewer.remove();
                    viewer.destroy();
                }
            }

            this.$configurationViewerCache = {};
        },

        _onConfigurationChanged: function (e) {
            // remove or add
            var configuration = e.$.item;
            if (configuration.$.printArea === this.get('_viewMap.printArea')) {
                this._addConfiguration(configuration);
            } else {
                this._removeConfiguration(configuration);
            }
        }

    });
});<|endoftext|>


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

	// Initialize config
	grunt.initConfig({

		// Load package.json
		pkg: require('./package.json'),

		// Project paths
		project: {
			assets: 'assets',
			styles: '<%= project.assets %>/stylesheets',
			styles_scss: '<%= project.styles %>/scss',
			styles_dev: '<%= project.styles %>/dev',
			styles_min: '<%= project.styles %>/min',
			styles_critical: '<%= project.styles %>/critical',
			scripts: '<%= project.assets %>/javascript',
			scripts_dev: '<%= project.scripts %>/dev',
			scripts_min: '<%= project.scripts %>/min',
			scripts_modules: '<%= project.scripts %>/modules',
			scripts_plugins: '<%= project.scripts %>/lib/plugins',
			scripts_polyfills: '<%= project.scripts %>/lib/polyfills',
			scripts_utils: '<%= project.scripts %>/lib/utils',
		},

		// Project banner
		tag: {
			banner_basic: '/**\n' +
					' * <%= pkg.description %> — v<%= pkg.version %> — <%= grunt.template.today("yyyy-mm-dd") %>\n' +
					' * <%= pkg.url %>\n' +
					' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.copyright %>\n' +
					' */\n',
			banner_extended: '/**\n' +
					' * <%= pkg.description %>\n' +
					' *\n' +
					' * @authors   <%= pkg.author %>\n' +
					' * @link      <%= pkg.url %>\n' +
					' * @version   <%= pkg.version %>\n' +
					' * @generated <%= grunt.template.today("yyyy-mm-dd:hh:mm") %>\n' +
					' * @copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.copyright %>\n' +
					' * @license   <%= pkg.license %>\n' +
					' */\n'
		},

		// JS files and order
		jsfiles: {
			head: [
				'<%= project.scripts_plugins %>/enhance/enhance.js',
				'<%= project.scripts_plugins %>/modernizr/modernizr.dev.js',
				// '<%= project.scripts_plugins %>/modernizr/modernizr.min.js',    // ALWAYS use custom build modernizr in production!
				'<%= project.scripts %>/head.scripts.js',
			],
			main: {
				plugins: [
					'<%= project.scripts_plugins %>/domready/domready.js',
					'<%= project.scripts_plugins %>/fontfaceobserver/fontfaceobserver.js',
					'<%= project.scripts_plugins %>/imageset/imageset.js',      // Out-comment when using imageset's lazyload
					// '<%= project.scripts_plugins %>/imageset/ls.bgset.js',      // Out-comment when using imageset's lazyload + background images with a width descriptor, similar to how `srcset` works (e.g. for Safari 10.x)
					// '<%= project.scripts_plugins %>/imageset/ls.parent-fit.js', // Out-comment when using imageset's lazyload + background images; when `bgset` plugin (background images) is used in combination with data-sizes="auto" and `background-size: cover|contain` (e.g. for Edge, IE11 and older, iOS 9, etc.)
					'<%= project.scripts_plugins %>/transitionend/transitionend.js',
					'<%= project.scripts_plugins %>/smooth-scroll/smooth-scroll.js',
					// '<%= project.scripts_plugins %>/gumshoe/gumshoe.js',
				],
				polyfills: [
					'<%= project.scripts_polyfills %>/classlist.js',
					// '<%= project.scripts_polyfills %>/promise.js',
					// '<%= project.scripts_polyfills %>/respimage.js',            // Out-comment when using imageset's lazyload, to add support for the `srcset` and `picture` element to browsers that do not provide native support (e.g. for IE11 and older, iOS 9.2 and older, Opera Mini, etc.)!!1
				],
				utils: [
					// '<%= project.scripts_utils %>/ajax.util.js',
					// '<%= project.scripts_utils %>/cookie.util.js',              // Out-comment when enhance (and thus enhance.cookie) is not used
					'<%= project.scripts_utils %>/domparents.util.js',
					'<%= project.scripts_utils %>/extend.util.js',
				],
				modules: [
					'<%= project.scripts_modules %>/alerts.module.js',
					'<%= project.scripts_modules %>/expand.module.js',
					'<%= project.scripts_modules %>/fontobserver.module.js',
					'<%= project.scripts_modules %>/navmain.module.js',
					'<%= project.scripts_modules %>/popup.module.js',
				// Main
					'<%= project.scripts %>/main.scripts.js',
				],
			},
			mobile: {
				plugins: [
					'<%= project.scripts_plugins %>/domready/domready.js',
					'<%= project.scripts_plugins %>/fontfaceobserver/fontfaceobserver.js',
					'<%= project.scripts_plugins %>/imageset/imageset.js',      // Out-comment when using imageset's lazyload
					// '<%= project.scripts_plugins %>/imageset/ls.bgset.js',      // Out-comment when using imageset's lazyload + background images with a width descriptor, similar to how `srcset` works (e.g. for Safari 10.x)
					// '<%= project.scripts_plugins %>/imageset/ls.parent-fit.js', // Out-comment when using imageset's lazyload + background images; when `bgset` plugin (background images) is used in combination with data-sizes="auto" and `background-size: cover|contain` (e.g. for Edge, IE11 and older, iOS 9, etc.)
					'<%= project.scripts_plugins %>/transitionend/transitionend.js',
					'<%= project.scripts_plugins %>/smooth-scroll/smooth-scroll.js',
				],
				polyfills: [
					'<%= project.scripts_polyfills %>/classlist.js',
					// '<%= project.scripts_polyfills %>/promise.js',
					// '<%= project.scripts_polyfills %>/respimage.js',            // Out-comment when using imageset's lazyload, to add support for the `srcset` and `picture` element to browsers that do not provide native support (e.g. for IE11 and older, iOS 9.2 and older, Opera Mini, etc.)!!1
				],
				utils: [
					// '<%= project.scripts_utils %>/ajax.util.js',
					// '<%= project.scripts_utils %>/cookie.util.js',              // Out-comment when enhance (and thus enhance.cookie) is not used
					'<%= project.scripts_utils %>/domparents.util.js',
					'<%= project.scripts_utils %>/extend.util.js',
				],
				modules: [
					'<%= project.scripts_modules %>/alerts.module.js',
					'<%= project.scripts_modules %>/expand.module.js',
					'<%= project.scripts_modules %>/fontobserver.module.js',
					'<%= project.scripts_modules %>/navmain.module.js',
				// Main
					'<%= project.scripts %>/mobile.scripts.js',
				],
			},
		},
	});

	// Load per-task config from separate files
	grunt.loadTasks('grunt/config');

	// Register alias tasks from separate files
	grunt.loadTasks('grunt/tasks');

	// Register default task
	grunt.registerTask('default', ['develop']);

};
<commit_msg>Add (better) comments.<commit_after>module.exports = function(grunt) {

	// Initialize config
	grunt.initConfig({

		// Load package.json
		pkg: require('./package.json'),

		// Project paths
		project: {
			assets: 'assets',
			styles: '<%= project.assets %>/stylesheets',
			styles_scss: '<%= project.styles %>/scss',
			styles_dev: '<%= project.styles %>/dev',
			styles_min: '<%= project.styles %>/min',
			styles_critical: '<%= project.styles %>/critical',
			scripts: '<%= project.assets %>/javascript',
			scripts_dev: '<%= project.scripts %>/dev',
			scripts_min: '<%= project.scripts %>/min',
			scripts_modules: '<%= project.scripts %>/modules',
			scripts_plugins: '<%= project.scripts %>/lib/plugins',
			scripts_polyfills: '<%= project.scripts %>/lib/polyfills',
			scripts_utils: '<%= project.scripts %>/lib/utils',
		},

		// Project banner
		tag: {
			banner_basic: '/**\n' +
					' * <%= pkg.description %> — v<%= pkg.version %> — <%= grunt.template.today("yyyy-mm-dd") %>\n' +
					' * <%= pkg.url %>\n' +
					' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.copyright %>\n' +
					' */\n',
			banner_extended: '/**\n' +
					' * <%= pkg.description %>\n' +
					' *\n' +
					' * @authors   <%= pkg.author %>\n' +
					' * @link      <%= pkg.url %>\n' +
					' * @version   <%= pkg.version %>\n' +
					' * @generated <%= grunt.template.today("yyyy-mm-dd:hh:mm") %>\n' +
					' * @copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.copyright %>\n' +
					' * @license   <%= pkg.license %>\n' +
					' */\n'
		},

		// JS files and order
		jsfiles: {
			head: [
				'<%= project.scripts_plugins %>/enhance/enhance.js',
				'<%= project.scripts_plugins %>/modernizr/modernizr.dev.js',
				// '<%= project.scripts_plugins %>/modernizr/modernizr.min.js',    // ALWAYS use custom build modernizr in production!
				'<%= project.scripts %>/head.scripts.js',
			],
			main: {
				plugins: [
					'<%= project.scripts_plugins %>/domready/domready.js',      // ALWAYS out-comment. It is used in the `main` and `mobile` scripts files!
					'<%= project.scripts_plugins %>/fontfaceobserver/fontfaceobserver.js', // Out-comment when loading fonts
					'<%= project.scripts_plugins %>/imageset/imageset.js',      // Out-comment when using imageset's lazyload
					// '<%= project.scripts_plugins %>/imageset/ls.bgset.js',      // Out-comment when using imageset's lazyload + background images with a width descriptor, similar to how `srcset` works (e.g. for Safari 10.x)
					// '<%= project.scripts_plugins %>/imageset/ls.parent-fit.js', // Out-comment when using imageset's lazyload + background images; when `bgset` plugin (background images) is used in combination with data-sizes="auto" and `background-size: cover|contain` (e.g. for Edge, IE11 and older, iOS 9, etc.)
					'<%= project.scripts_plugins %>/transitionend/transitionend.js', // Out-comment when using alerts or navmain module!
					'<%= project.scripts_plugins %>/smooth-scroll/smooth-scroll.js',
					// '<%= project.scripts_plugins %>/gumshoe/gumshoe.js',
				],
				polyfills: [
					'<%= project.scripts_polyfills %>/classlist.js',            // Adds cross-browser full `element.classList` support (IE11)
					// '<%= project.scripts_polyfills %>/promise.js',
					// '<%= project.scripts_polyfills %>/respimage.js',            // Out-comment when using imageset's lazyload, to add support for the `srcset` and `picture` element to browsers that do not provide native support (e.g. for IE11 and older, iOS 9.2 and older, Opera Mini, etc.)!!1
				],
				utils: [
					// '<%= project.scripts_utils %>/ajax.util.js',
					// '<%= project.scripts_utils %>/cookie.util.js',              // Out-comment when enhance (and thus enhance.cookie) is not used
					// '<%= project.scripts_utils %>/domparents.util.js',
					'<%= project.scripts_utils %>/extend.util.js',              // Out-comment when using alerts module!
				],
				modules: [
					'<%= project.scripts_modules %>/alerts.module.js',
					'<%= project.scripts_modules %>/expand.module.js',
					'<%= project.scripts_modules %>/fontobserver.module.js',
					'<%= project.scripts_modules %>/navmain.module.js',
					'<%= project.scripts_modules %>/popup.module.js',
				// Main
					'<%= project.scripts %>/main.scripts.js',
				],
			},
			mobile: {
				plugins: [
					'<%= project.scripts_plugins %>/domready/domready.js',      // ALWAYS out-comment! It is used in the `main` and `mobile` scripts files!
					'<%= project.scripts_plugins %>/fontfaceobserver/fontfaceobserver.js', // Out-comment when loading fonts
					'<%= project.scripts_plugins %>/imageset/imageset.js',      // Out-comment when using imageset's lazyload
					// '<%= project.scripts_plugins %>/imageset/ls.bgset.js',      // Out-comment when using imageset's lazyload + background images with a width descriptor, similar to how `srcset` works (e.g. for Safari 10.x)
					// '<%= project.scripts_plugins %>/imageset/ls.parent-fit.js', // Out-comment when using imageset's lazyload + background images; when `bgset` plugin (background images) is used in combination with data-sizes="auto" and `background-size: cover|contain` (e.g. for Edge, IE11 and older, iOS 9, etc.)
					'<%= project.scripts_plugins %>/transitionend/transitionend.js', // Out-comment when using alerts or navmain module!
					'<%= project.scripts_plugins %>/smooth-scroll/smooth-scroll.js',
				],
				polyfills: [
					'<%= project.scripts_polyfills %>/classlist.js',            // Adds cross-browser full `element.classList` support (IE11)
					// '<%= project.scripts_polyfills %>/promise.js',
					// '<%= project.scripts_polyfills %>/respimage.js',            // Out-comment when using imageset's lazyload, to add support for the `srcset` and `picture` element to browsers that do not provide native support (e.g. for IE11 and older, iOS 9.2 and older, Opera Mini, etc.)!!1
				],
				utils: [
					// '<%= project.scripts_utils %>/ajax.util.js',
					// '<%= project.scripts_utils %>/cookie.util.js',              // Out-comment when enhance (and thus enhance.cookie) is not used
					// '<%= project.scripts_utils %>/domparents.util.js',
					'<%= project.scripts_utils %>/extend.util.js',              // Out-comment when using alerts module!
				],
				modules: [
					'<%= project.scripts_modules %>/alerts.module.js',
					'<%= project.scripts_modules %>/expand.module.js',
					'<%= project.scripts_modules %>/fontobserver.module.js',
					'<%= project.scripts_modules %>/navmain.module.js',
				// Main
					'<%= project.scripts %>/mobile.scripts.js',
				],
			},
		},
	});

	// Load per-task config from separate files
	grunt.loadTasks('grunt/config');

	// Register alias tasks from separate files
	grunt.loadTasks('grunt/tasks');

	// Register default task
	grunt.registerTask('default', ['develop']);

};
<|endoftext|>


<commit_before>var Url = require('url');
var Http = require('http');
var Https = require('https');
var e = require('../Exceptions');

var HeadRequest = function (url, options) {
	options = options || {};

	this.url = Url.parse(url);
	this.port = options.port || 80;

	// support https download start
	this.https = false;
	if (url.indexOf("https://") > -1){
		this.port = 443;
		this.https = true;
	}
	// suport https download end

	this.headers = options.headers || {};
};

var _execute = function (callback) {
	var self = this;
	this.callback = callback;
	Http.globalAgent.maxSockets = 200;
	Http.Agent.defaultMaxSockets = 200;
	var onError = self.onError.bind(self);

	var onHead = function (response) {

		var fileSize = Number(response.headers['content-length']);
		response.destroy();

		if (isNaN(fileSize)) {
			self.callback(e(1008, self.url.host));
			return;
		}

		var result = {
			fileSize: fileSize,
			headers: response.headers
		};
		self.callback(null, result);
	};

	requestOptions = {
		hostname: self.url.hostname,
		path: self.url.path,
		method: 'HEAD',
		port: self.port,
		headers: self.headers
	};
	// support https download start
	if (self.https){
		Https.request(requestOptions, onHead)
			.on('error', onError)
			.end();
	} else {
		Http.request(requestOptions, onHead)
			.on('error', onError)
			.end();
	}
	// suport https download start

};

HeadRequest.prototype.execute = _execute;
HeadRequest.prototype.onError = function (err) {
	this.callback(e(1004, this.url.host));
};

module.exports = HeadRequest;
<commit_msg>add statusCode in head request<commit_after>var Url = require('url');
var Http = require('http');
var Https = require('https');
var e = require('../Exceptions');

var HeadRequest = function (url, options) {
	options = options || {};

	this.url = Url.parse(url);
	this.port = options.port || 80;

	// support https download start
	this.https = false;
	if (url.indexOf("https://") > -1){
		this.port = 443;
		this.https = true;
	}
	// suport https download end

	this.headers = options.headers || {};
};

var _execute = function (callback) {
	var self = this;
	this.callback = callback;
	Http.globalAgent.maxSockets = 200;
	Http.Agent.defaultMaxSockets = 200;
	var onError = self.onError.bind(self);

	var onHead = function (response) {

		var fileSize = Number(response.headers['content-length']);
		response.destroy();

		if (isNaN(fileSize)) {
			self.callback(e(1008, self.url.host));
			return;
		}
		// add statusCode in head request result
		// to check if download is ok
		var result = {
			fileSize: fileSize,
			statusCode: response.statusCode,
			headers: response.headers
		};
		self.callback(null, result);
	};

	requestOptions = {
		hostname: self.url.hostname,
		path: self.url.path,
		method: 'HEAD',
		port: self.port,
		headers: self.headers
	};
	// support https download start
	if (self.https){
		Https.request(requestOptions, onHead)
			.on('error', onError)
			.end();
	} else {
		Http.request(requestOptions, onHead)
			.on('error', onError)
			.end();
	}
	// suport https download start

};

HeadRequest.prototype.execute = _execute;
HeadRequest.prototype.onError = function (err) {
	this.callback(e(1004, this.url.host));
};

module.exports = HeadRequest;
<|endoftext|>


<commit_before>/*******************************
          Build Task
*******************************/

var
  gulp         = require('gulp'),

  // node dependencies
  console      = require('better-console'),
  fs           = require('fs'),

  // gulp dependencies
  autoprefixer = require('gulp-autoprefixer'),
  chmod        = require('gulp-chmod'),
  clone        = require('gulp-clone'),
  flatten      = require('gulp-flatten'),
  gulpif       = require('gulp-if'),
  less         = require('gulp-less'),
  minifyCSS    = require('gulp-minify-css'),
  plumber      = require('gulp-plumber'),
  print        = require('gulp-print'),
  rename       = require('gulp-rename'),
  replace      = require('gulp-replace'),
  uglify       = require('gulp-uglify'),

  // config
  config       = require('./config/user'),
  tasks        = require('./config/project/tasks'),
  install      = require('./config/project/install'),

  // shorthand
  globs        = config.globs,
  assets       = config.paths.assets,
  output       = config.paths.output,
  source       = config.paths.source,

  banner       = tasks.banner,
  comments     = tasks.regExp.comments,
  log          = tasks.log,
  settings     = tasks.settings
;

// add internal tasks (concat release)
require('./collections/internal')(gulp);

module.exports = function(callback) {

  var
    stream,
    compressedStream,
    uncompressedStream
  ;

  console.info('Building Semantic');

  if( !install.isSetup() ) {
    console.error('Cannot build files. Run "gulp install" to set-up Semantic');
    return;
  }

  // check for right-to-left language
  if(config.rtl === true || config.rtl === 'Yes') {
    gulp.start('build-rtl');
    return;
  }

  // unified css stream
  stream = gulp.src(source.definitions + '/**/' + globs.components + '.less')
    .pipe(plumber())
    .pipe(less(settings.less))
    .pipe(autoprefixer(settings.prefix))
    .pipe(replace(comments.variables.in, comments.variables.out))
    .pipe(replace(comments.license.in, comments.license.out))
    .pipe(replace(comments.large.in, comments.large.out))
    .pipe(replace(comments.small.in, comments.small.out))
    .pipe(replace(comments.tiny.in, comments.tiny.out))
    .pipe(flatten())
  ;

  // two concurrent streams from same source to concat release
  uncompressedStream = stream.pipe(clone());
  compressedStream   = stream.pipe(clone());

  // uncompressed component css
  uncompressedStream
    .pipe(plumber())
    .pipe(replace(assets.source, assets.uncompressed))
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(gulp.dest(output.uncompressed))
    .pipe(print(log.created))
    .on('end', function() {
      gulp.start('package uncompressed css');
    })
  ;

  // compressed component css
  compressedStream = stream
    .pipe(plumber())
    .pipe(clone())
    .pipe(replace(assets.source, assets.compressed))
    .pipe(minifyCSS(settings.minify))
    .pipe(rename(settings.rename.minCSS))
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(gulp.dest(output.compressed))
    .pipe(print(log.created))
    .on('end', function() {
      callback();
      gulp.start('package compressed css');
    })
  ;

  // copy assets
  gulp.src(source.themes + '/**/assets/**/' + globs.components + '?(s).*')
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(gulp.dest(output.themes))
  ;

  // copy source javascript
  gulp.src(source.definitions + '/**/' + globs.components + '.js')
    .pipe(plumber())
    .pipe(flatten())
    .pipe(replace(comments.license.in, comments.license.out))
    .pipe(gulp.dest(output.uncompressed))
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(print(log.created))
    .pipe(uglify(settings.uglify))
    .pipe(rename(settings.rename.minJS))
    .pipe(gulp.dest(output.compressed))
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(print(log.created))
    .on('end', function() {
      gulp.start('package compressed js');
      gulp.start('package uncompressed js');
    })
  ;

};<commit_msg>Add #2102 to 1.x<commit_after>/*******************************
          Build Task
*******************************/

var
  gulp         = require('gulp'),

  // node dependencies
  console      = require('better-console'),
  fs           = require('fs'),

  // gulp dependencies
  autoprefixer = require('gulp-autoprefixer'),
  chmod        = require('gulp-chmod'),
  clone        = require('gulp-clone'),
  flatten      = require('gulp-flatten'),
  gulpif       = require('gulp-if'),
  less         = require('gulp-less'),
  minifyCSS    = require('gulp-minify-css'),
  plumber      = require('gulp-plumber'),
  print        = require('gulp-print'),
  rename       = require('gulp-rename'),
  replace      = require('gulp-replace'),
  uglify       = require('gulp-uglify'),

  // config
  config       = require('./config/user'),
  tasks        = require('./config/project/tasks'),
  install      = require('./config/project/install'),

  // shorthand
  globs        = config.globs,
  assets       = config.paths.assets,
  output       = config.paths.output,
  source       = config.paths.source,

  banner       = tasks.banner,
  comments     = tasks.regExp.comments,
  log          = tasks.log,
  settings     = tasks.settings
;

// add internal tasks (concat release)
require('./collections/internal')(gulp);

module.exports = function(callback) {

  var
    stream,
    compressedStream,
    uncompressedStream
  ;

  console.info('Building Semantic');

  if( !install.isSetup() ) {
    console.error('Cannot find semantic.json. Run "gulp install" to set-up Semantic');
    return;
  }

  // check for right-to-left language
  if(config.rtl === true || config.rtl === 'Yes') {
    gulp.start('build-rtl');
    return;
  }

  // unified css stream
  stream = gulp.src(source.definitions + '/**/' + globs.components + '.less')
    .pipe(plumber())
    .pipe(less(settings.less))
    .pipe(autoprefixer(settings.prefix))
    .pipe(replace(comments.variables.in, comments.variables.out))
    .pipe(replace(comments.license.in, comments.license.out))
    .pipe(replace(comments.large.in, comments.large.out))
    .pipe(replace(comments.small.in, comments.small.out))
    .pipe(replace(comments.tiny.in, comments.tiny.out))
    .pipe(flatten())
  ;

  // two concurrent streams from same source to concat release
  uncompressedStream = stream.pipe(clone());
  compressedStream   = stream.pipe(clone());

  // uncompressed component css
  uncompressedStream
    .pipe(plumber())
    .pipe(replace(assets.source, assets.uncompressed))
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(gulp.dest(output.uncompressed))
    .pipe(print(log.created))
    .on('end', function() {
      gulp.start('package uncompressed css');
    })
  ;

  // compressed component css
  compressedStream = stream
    .pipe(plumber())
    .pipe(clone())
    .pipe(replace(assets.source, assets.compressed))
    .pipe(minifyCSS(settings.minify))
    .pipe(rename(settings.rename.minCSS))
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(gulp.dest(output.compressed))
    .pipe(print(log.created))
    .on('end', function() {
      callback();
      gulp.start('package compressed css');
    })
  ;

  // copy assets
  gulp.src(source.themes + '/**/assets/**/' + globs.components + '?(s).*')
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(gulp.dest(output.themes))
  ;

  // copy source javascript
  gulp.src(source.definitions + '/**/' + globs.components + '.js')
    .pipe(plumber())
    .pipe(flatten())
    .pipe(replace(comments.license.in, comments.license.out))
    .pipe(gulp.dest(output.uncompressed))
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(print(log.created))
    .pipe(uglify(settings.uglify))
    .pipe(rename(settings.rename.minJS))
    .pipe(gulp.dest(output.compressed))
    .pipe(gulpif(config.hasPermission, chmod(config.permission)))
    .pipe(print(log.created))
    .on('end', function() {
      gulp.start('package compressed js');
      gulp.start('package uncompressed js');
    })
  ;

};<|endoftext|>


<commit_before>const _ = require('underscore-plus');
const {Range, CompositeDisposable} = require('atom');
const ResultView = require('./result-view');
const etch = require('etch')
const $ = require('../dom-helpers')

const reverseDirections = {
  left: 'right',
  right: 'left',
  up: 'down',
  down: 'up'
};

module.exports =
class ResultsView {
  constructor({model}) {
    this.model = model;
    this.pixelOverdraw = 100;
    this.searchResults = [];
    this.selectedResultIndex = 0;
    this.selectedMatchIndex = -1;
    this.collapsedResultIndices = [];

    etch.initialize(this);

    this.element.addEventListener('mousedown', this.handleClick.bind(this));
    this.element.addEventListener('scroll', () => this.renderResults())
    this.element.addEventListener('resize', () => this.renderResults())

    this.subscriptions = new CompositeDisposable(
      this.model.onDidAddResult(this.addResult.bind(this)),
      this.model.onDidRemoveResult(this.removeResult.bind(this)),
      this.model.onDidClearSearchState(this.clear.bind(this)),
      this.model.getFindOptions().onDidChangeReplacePattern(() => etch.update(this)),

      atom.commands.add(this.element, {
        'core:move-up': this.moveUp.bind(this),
        'core:move-down': this.moveDown.bind(this),
        'core:move-left': this.collapseResult.bind(this),
        'core:move-right': this.expandResult.bind(this),
        'core:page-up': this.pageUp.bind(this),
        'core:page-down': this.pageDown.bind(this),
        'core:move-to-top': this.moveToTop.bind(this),
        'core:move-to-bottom': this.moveToBottom.bind(this),
        'core:confirm': this.confirmResult.bind(this),
        'core:copy': this.copyResult.bind(this),
        'find-and-replace:copy-path': this.copyPath.bind(this)
      })
    );

    this.renderResults();
  }

  update() {}

  destroy() {
    this.subscriptions.dispose();
  }

  clear() {
    this.searchResults = [];
    this.selectedResultIndex = -1;
    this.selectedMatchIndex = -1;
    etch.update(this);
  }

  render () {
    let regex = null, replacePattern = null;
    if (this.model.replacedPathCount == null) {
      regex = this.model.regex;
      replacePattern = this.model.getFindOptions().replacePattern;
    }

    return (
      $.ol(
        {
          className: 'results-view list-tree focusable-panel has-collapsable-children',
          tabIndex: -1
        },

        ...this.searchResults.map(({filePath, matches}, i) => {
          const isSelected = (i === this.selectedResultIndex);
          const isExpanded = !this.collapsedResultIndices[i];
          const selectedMatchIndex = isSelected && this.selectedMatchIndex;

          return $(ResultView, {
            filePath, matches, isSelected, isExpanded, selectedMatchIndex,
            regex, replacePattern
          });
        })
      )
    );
  }

  addResult({filePath, result, filePathInsertedIndex}) {
    result = Object.assign({filePath}, result);

    const existingIndex = this.searchResults.findIndex(existingResult =>
      existingResult.filePath === filePath
    );
    if (existingIndex !== -1) {
      this.searchResults[existingIndex] = result;
      return;
    }

    if (filePathInsertedIndex < this.searchResults.length || this.shouldRenderMoreResults()) {
      this.searchResults.splice(filePathInsertedIndex, 0, result);
    }

    if (!this.userMovedSelection || this.model.getPathCount() === 1) {
      this.selectFirstResult();
    }

    etch.update(this);
  }

  removeResult({filePath}) {
    const index = this.results.findIndex(result => result.filePath === filePath);
    if (index !== -1) {
      this.results.splice(index, 1);
      etch.update(this);
    }
  }

  renderResults(scrollTop) {
    for (const filePath of this.model.getPaths().slice(this.searchResults.length)) {
      if (!this.shouldRenderMoreResults(scrollTop)) break;
      this.searchResults.push(this.model.getResult(filePath));
    }

    return etch.update(this);
  }

  shouldRenderMoreResults(scrollTop) {
    if (scrollTop == null) scrollTop = this.element.scrollTop;
    const pathDetailsElement = this.element.querySelector('.path-details');
    const matchElement = this.element.querySelector('.path:not(.collapsed) .search-result');
    const pathDetailsHeight = pathDetailsElement ? pathDetailsElement.offsetHeight : 0;
    const matchHeight = matchElement ? matchElement.offsetHeight : 0;

    let renderedHeight = 0;
    for (let i = 0; i < this.searchResults.length; i++) {
      renderedHeight += pathDetailsHeight;
      if (!this.collapsedResultIndices[i]) {
        renderedHeight += this.searchResults[i].matches.length * matchHeight;
      }
    }

    return renderedHeight < scrollTop + this.element.offsetHeight + this.pixelOverdraw;
  }

  handleClick(event) {
    const clickedResultElement = event.target.closest('.path');
    const clickedMatchElement = event.target.closest('.search-result');
    if (event.ctrlKey || !clickedResultElement) return;

    const clickedFilePath = clickedResultElement.dataset.path;
    this.selectedResultIndex = this.searchResults.findIndex(searchResult =>
      searchResult.filePath === clickedFilePath
    );
    const clickedResult = this.searchResults[this.selectedResultIndex];

    if (clickedMatchElement) {
      const clickedRange = clickedMatchElement.dataset.range;
      this.selectedMatchIndex = clickedResult.matches.findIndex(match =>
        Range.fromObject(match.range).toString() === clickedRange
      );
      this.confirmResult({pending: event.detail === 1});
    } else {
      this.selectedMatchIndex = -1;
      this.confirmResult();
    }

    this.renderResults();
  }

  selectFirstResult() {
    this.selectedResultIndex = 0;
    if (this.collapsedResultIndices[0]) {
      this.selectedMatchIndex = -1;
    } else {
      this.selectedMatchIndex = 0;
    }
    etch.update(this);
  }

  moveToTop() {
    this.element.scrollTop = 0;
    this.selectFirstResult();
  }

  moveToBottom() {
    return this.renderResults(Infinity).then(() => {
      this.selectedResultIndex = this.searchResults.length - 1;
      if (this.collapsedResultIndices[this.selectedResultIndex]) {
        this.selectedMatchIndex = -1;
      } else {
        this.selectedMatchIndex = this.searchResults[this.selectedResultIndex].matches.length - 1;
      }
      this.element.scrollTop = this.element.scrollHeight - this.element.offsetHeight;
      etch.update(this);
    })
  }

  pageUp() {
    const pathDetailsElement = this.element.querySelector('.path-details');
    const matchElement = this.element.querySelector('.path:not(.collapsed) .search-result');
    const pathDetailsHeight = pathDetailsElement ? pathDetailsElement.offsetHeight : 0;
    const matchHeight = matchElement ? matchElement.offsetHeight : 0;

    const position = this.positionOfSelectedResult(pathDetailsHeight, matchHeight);
    this.element.scrollTop -= this.element.offsetHeight;
    this.selectResultAtPosition(
      position - this.element.offsetHeight,
      pathDetailsHeight,
      matchHeight
    );
  }

  pageDown() {
    const pathDetailsElement = this.element.querySelector('.path-details');
    const matchElement = this.element.querySelector('.path:not(.collapsed) .search-result');
    const pathDetailsHeight = pathDetailsElement ? pathDetailsElement.offsetHeight : 0;
    const matchHeight = matchElement ? matchElement.offsetHeight : 0;

    const position = this.positionOfSelectedResult(pathDetailsHeight, matchHeight);
    const newScrollTop = this.element.scrollTop + this.element.offsetHeight;
    return this.renderResults(newScrollTop).then(() => {
      this.element.scrollTop = newScrollTop;
      this.selectResultAtPosition(
        position + this.element.offsetHeight,
        pathDetailsHeight,
        matchHeight
      );
    });
  }

  positionOfSelectedResult(pathDetailsHeight, matchHeight) {
    let result = 0;
    for (let i = 0; i < this.selectedResultIndex; i++) {
      result += pathDetailsHeight;
      if (!this.collapsedResultIndices[i]) {
        result += this.searchResults[i].matches.length * matchHeight
      }
    }

    if (this.selectedMatchIndex !== -1) {
      result += pathDetailsHeight + this.selectedMatchIndex * matchHeight;
    }

    return result;
  }

  selectResultAtPosition(position, pathDetailsHeight, matchHeight) {
    this.selectedResultIndex = this.searchResults.length - 1;
    this.selectedMatchIndex = this.collapsedResultIndices[this.selectedResultIndex] ?
      -1 : this.searchResults[this.selectedResultIndex].matches.length - 1;

    let top = 0, bottom = 0;
    for (let i = 0; i < this.searchResults.length; i++) {
      bottom = top + pathDetailsHeight;
      if (bottom > position) {
        this.selectedResultIndex = i;
        this.selectedMatchIndex = -1;
        break;
      }

      top = bottom;

      if (!this.collapsedResultIndices[i]) {
        const matchesBottom = top + this.searchResults[i].matches.length * matchHeight;
        if (matchesBottom > position) {
          this.selectedResultIndex = i;
          this.selectedMatchIndex = Math.round((position - top) / matchHeight);
          top += this.selectedMatchIndex * matchHeight;
          bottom = top + matchHeight;
          break;
        }

        top = matchesBottom;
      }
    }

    if (this.element.scrollTop > top) {
      this.element.scrollTop = top;
    }

    if (this.element.scrollTop < bottom - this.element.offsetHeight) {
      this.element.scrollTop = bottom - this.element.offsetHeight;
    }

    etch.update(this);
  }

  moveDown() {
    if (this.selectedResultIndex === -1) {
      this.selectFirstResult();
      return;
    }

    this.userMovedSelection = true;
    const selectedResult = this.searchResults[this.selectedResultIndex];
    if (this.selectedMatchIndex < selectedResult.matches.length - 1 &&
        !this.collapsedResultIndices[this.selectedResultIndex]) {
      this.selectedMatchIndex++;
    } else if (this.selectedResultIndex < this.searchResults.length - 1) {
      this.selectedResultIndex++;
      this.selectedMatchIndex = -1;
    }

    etch.update(this).then(this.scrollToSelectedMatch.bind(this));
  }

  moveUp() {
    if (this.selectedResultIndex === -1) {
      this.selectFirstResult();
      return;
    }

    this.userMovedSelection = true;
    if (this.selectedMatchIndex >= 0) {
      this.selectedMatchIndex--;
    } else if (this.selectedResultIndex > 0) {
      this.selectedResultIndex--;
      const selectedResult = this.searchResults[this.selectedResultIndex];
      if (this.collapsedResultIndices[this.selectedResultIndex]) {
        this.selectedMatchIndex = -1;
      } else {
        this.selectedMatchIndex = selectedResult.matches.length - 1;
      }
    }

    etch.update(this).then(this.scrollToSelectedMatch.bind(this));
  }

  expandResult() {
    if (this.selectedResultIndex !== -1) {
      this.collapsedResultIndices[this.selectedResultIndex] = false;
      this.renderResults();
    }
  }

  collapseResult() {
    if (this.selectedResultIndex !== -1) {
      this.collapsedResultIndices[this.selectedResultIndex] = true;
      this.selectedMatchIndex = -1;
      this.renderResults();
    }
  }

  confirmResult({pending} = {}) {
    if (this.selectedResultIndex !== -1) {
      if (this.selectedMatchIndex !== -1) {
        const result = this.searchResults[this.selectedResultIndex];
        const match = result.matches[this.selectedMatchIndex];
        atom.workspace
          .open(result.filePath, {
            pending,
            split: reverseDirections[atom.config.get('find-and-replace.projectSearchResultsPaneSplitDirection')]
          })
          .then(editor => {
            editor.setSelectedBufferRange(match.range, {autoscroll: true})
          });
      } else {
        this.collapsedResultIndices[this.selectedResultIndex] = !this.collapsedResultIndices[this.selectedResultIndex];
        this.renderResults();
      }
    }
  }

  copyResult() {
    if (this.selectedResultIndex !== -1) {
      if (this.selectedMatchIndex !== -1) {
        const result = this.searchResults[this.selectedResultIndex];
        const match = result.matches[this.selectedMatchIndex];
        atom.clipboard.write(match.lineText);
      }
    }
  }

  copyPath(event) {
    const pathElement = event.target.closest('.path');
    if (!pathElement) return;

    const filePath = event.target.dataset.path;
    let [rootPath, relativePath] = atom.project.relativizePath(filePath);
    if (rootPath && atom.project.getDirectories().length > 1) {
      relativePath = path.join(path.basename(rootPath), relativePath);
    }
    atom.clipboard.write(relativePath);
  }

  expandAllResults() {
    this.collapsedResultIndices = new Array(this.searchResults.length);
    this.collapsedResultIndices.fill(false);
    this.renderResults(Infinity);
  }

  collapseAllResults() {
    this.collapsedResultIndices = new Array(this.model.getPaths().length);
    this.collapsedResultIndices.fill(true);
    this.renderResults(Infinity);
  }

  scrollToSelectedMatch() {
    const resultElement = this.element.children[this.selectedResultIndex];

    let top = resultElement.offsetTop;
    let bottom = top + resultElement.offsetHeight;

    if (this.selectedMatchIndex !== -1) {
      const matchElement = resultElement.querySelectorAll('.search-result');
      top += matchElement.offsetTop;
      bottom = top + matchElement.offsetHeight;
    }

    if (bottom > this.element.scrollTop + this.element.scrollHeight) {
      this.element.scrollTop = bottom - this.element.scrollHeight;
    }

    if (top < this.scrollTop) {
      this.element.scrollTop = top;
    }
  }

  scrollToBottom() {
    this.renderResults(Infinity);
    this.element.scrollTop = this.element.scrollHeight;
  }

  scrollToTop() {
    this.element.scrollTop = 0;
  }

  selectedResultView() {
    const element = this.selectedElement()
    if (element) return this.resultViewsByElement.get(element)
  }
};
<commit_msg>Select first match when expanding collapsed path<commit_after>const _ = require('underscore-plus');
const {Range, CompositeDisposable} = require('atom');
const ResultView = require('./result-view');
const etch = require('etch')
const $ = require('../dom-helpers')

const reverseDirections = {
  left: 'right',
  right: 'left',
  up: 'down',
  down: 'up'
};

module.exports =
class ResultsView {
  constructor({model}) {
    this.model = model;
    this.pixelOverdraw = 100;
    this.searchResults = [];
    this.selectedResultIndex = 0;
    this.selectedMatchIndex = -1;
    this.collapsedResultIndices = [];

    etch.initialize(this);

    this.element.addEventListener('mousedown', this.handleClick.bind(this));
    this.element.addEventListener('scroll', () => this.renderResults())
    this.element.addEventListener('resize', () => this.renderResults())

    this.subscriptions = new CompositeDisposable(
      this.model.onDidAddResult(this.addResult.bind(this)),
      this.model.onDidRemoveResult(this.removeResult.bind(this)),
      this.model.onDidClearSearchState(this.clear.bind(this)),
      this.model.getFindOptions().onDidChangeReplacePattern(() => etch.update(this)),

      atom.commands.add(this.element, {
        'core:move-up': this.moveUp.bind(this),
        'core:move-down': this.moveDown.bind(this),
        'core:move-left': this.collapseResult.bind(this),
        'core:move-right': this.expandResult.bind(this),
        'core:page-up': this.pageUp.bind(this),
        'core:page-down': this.pageDown.bind(this),
        'core:move-to-top': this.moveToTop.bind(this),
        'core:move-to-bottom': this.moveToBottom.bind(this),
        'core:confirm': this.confirmResult.bind(this),
        'core:copy': this.copyResult.bind(this),
        'find-and-replace:copy-path': this.copyPath.bind(this)
      })
    );

    this.renderResults();
  }

  update() {}

  destroy() {
    this.subscriptions.dispose();
  }

  clear() {
    this.searchResults = [];
    this.selectedResultIndex = -1;
    this.selectedMatchIndex = -1;
    etch.update(this);
  }

  render () {
    let regex = null, replacePattern = null;
    if (this.model.replacedPathCount == null) {
      regex = this.model.regex;
      replacePattern = this.model.getFindOptions().replacePattern;
    }

    return (
      $.ol(
        {
          className: 'results-view list-tree focusable-panel has-collapsable-children',
          tabIndex: -1
        },

        ...this.searchResults.map(({filePath, matches}, i) => {
          const isSelected = (i === this.selectedResultIndex);
          const isExpanded = !this.collapsedResultIndices[i];
          const selectedMatchIndex = isSelected && this.selectedMatchIndex;

          return $(ResultView, {
            filePath, matches, isSelected, isExpanded, selectedMatchIndex,
            regex, replacePattern
          });
        })
      )
    );
  }

  addResult({filePath, result, filePathInsertedIndex}) {
    result = Object.assign({filePath}, result);

    const existingIndex = this.searchResults.findIndex(existingResult =>
      existingResult.filePath === filePath
    );
    if (existingIndex !== -1) {
      this.searchResults[existingIndex] = result;
      return;
    }

    if (filePathInsertedIndex < this.searchResults.length || this.shouldRenderMoreResults()) {
      this.searchResults.splice(filePathInsertedIndex, 0, result);
    }

    if (!this.userMovedSelection || this.model.getPathCount() === 1) {
      this.selectFirstResult();
    }

    etch.update(this);
  }

  removeResult({filePath}) {
    const index = this.results.findIndex(result => result.filePath === filePath);
    if (index !== -1) {
      this.results.splice(index, 1);
      etch.update(this);
    }
  }

  renderResults(scrollTop) {
    for (const filePath of this.model.getPaths().slice(this.searchResults.length)) {
      if (!this.shouldRenderMoreResults(scrollTop)) break;
      this.searchResults.push(this.model.getResult(filePath));
    }

    return etch.update(this);
  }

  shouldRenderMoreResults(scrollTop) {
    if (scrollTop == null) scrollTop = this.element.scrollTop;
    const pathDetailsElement = this.element.querySelector('.path-details');
    const matchElement = this.element.querySelector('.path:not(.collapsed) .search-result');
    const pathDetailsHeight = pathDetailsElement ? pathDetailsElement.offsetHeight : 0;
    const matchHeight = matchElement ? matchElement.offsetHeight : 0;

    let renderedHeight = 0;
    for (let i = 0; i < this.searchResults.length; i++) {
      renderedHeight += pathDetailsHeight;
      if (!this.collapsedResultIndices[i]) {
        renderedHeight += this.searchResults[i].matches.length * matchHeight;
      }
    }

    return renderedHeight < scrollTop + this.element.offsetHeight + this.pixelOverdraw;
  }

  handleClick(event) {
    const clickedResultElement = event.target.closest('.path');
    const clickedMatchElement = event.target.closest('.search-result');
    if (event.ctrlKey || !clickedResultElement) return;

    const clickedFilePath = clickedResultElement.dataset.path;
    this.selectedResultIndex = this.searchResults.findIndex(searchResult =>
      searchResult.filePath === clickedFilePath
    );
    const clickedResult = this.searchResults[this.selectedResultIndex];

    if (clickedMatchElement) {
      const clickedRange = clickedMatchElement.dataset.range;
      this.selectedMatchIndex = clickedResult.matches.findIndex(match =>
        Range.fromObject(match.range).toString() === clickedRange
      );
      this.confirmResult({pending: event.detail === 1});
    } else {
      this.selectedMatchIndex = -1;
      this.confirmResult();
    }

    this.renderResults();
  }

  selectFirstResult() {
    this.selectedResultIndex = 0;
    if (this.collapsedResultIndices[0]) {
      this.selectedMatchIndex = -1;
    } else {
      this.selectedMatchIndex = 0;
    }
    etch.update(this);
  }

  moveToTop() {
    this.element.scrollTop = 0;
    this.selectFirstResult();
  }

  moveToBottom() {
    return this.renderResults(Infinity).then(() => {
      this.selectedResultIndex = this.searchResults.length - 1;
      if (this.collapsedResultIndices[this.selectedResultIndex]) {
        this.selectedMatchIndex = -1;
      } else {
        this.selectedMatchIndex = this.searchResults[this.selectedResultIndex].matches.length - 1;
      }
      this.element.scrollTop = this.element.scrollHeight - this.element.offsetHeight;
      etch.update(this);
    })
  }

  pageUp() {
    const pathDetailsElement = this.element.querySelector('.path-details');
    const matchElement = this.element.querySelector('.path:not(.collapsed) .search-result');
    const pathDetailsHeight = pathDetailsElement ? pathDetailsElement.offsetHeight : 0;
    const matchHeight = matchElement ? matchElement.offsetHeight : 0;

    const position = this.positionOfSelectedResult(pathDetailsHeight, matchHeight);
    this.element.scrollTop -= this.element.offsetHeight;
    this.selectResultAtPosition(
      position - this.element.offsetHeight,
      pathDetailsHeight,
      matchHeight
    );
  }

  pageDown() {
    const pathDetailsElement = this.element.querySelector('.path-details');
    const matchElement = this.element.querySelector('.path:not(.collapsed) .search-result');
    const pathDetailsHeight = pathDetailsElement ? pathDetailsElement.offsetHeight : 0;
    const matchHeight = matchElement ? matchElement.offsetHeight : 0;

    const position = this.positionOfSelectedResult(pathDetailsHeight, matchHeight);
    const newScrollTop = this.element.scrollTop + this.element.offsetHeight;
    return this.renderResults(newScrollTop).then(() => {
      this.element.scrollTop = newScrollTop;
      this.selectResultAtPosition(
        position + this.element.offsetHeight,
        pathDetailsHeight,
        matchHeight
      );
    });
  }

  positionOfSelectedResult(pathDetailsHeight, matchHeight) {
    let result = 0;
    for (let i = 0; i < this.selectedResultIndex; i++) {
      result += pathDetailsHeight;
      if (!this.collapsedResultIndices[i]) {
        result += this.searchResults[i].matches.length * matchHeight
      }
    }

    if (this.selectedMatchIndex !== -1) {
      result += pathDetailsHeight + this.selectedMatchIndex * matchHeight;
    }

    return result;
  }

  selectResultAtPosition(position, pathDetailsHeight, matchHeight) {
    this.selectedResultIndex = this.searchResults.length - 1;
    this.selectedMatchIndex = this.collapsedResultIndices[this.selectedResultIndex] ?
      -1 : this.searchResults[this.selectedResultIndex].matches.length - 1;

    let top = 0, bottom = 0;
    for (let i = 0; i < this.searchResults.length; i++) {
      bottom = top + pathDetailsHeight;
      if (bottom > position) {
        this.selectedResultIndex = i;
        this.selectedMatchIndex = -1;
        break;
      }

      top = bottom;

      if (!this.collapsedResultIndices[i]) {
        const matchesBottom = top + this.searchResults[i].matches.length * matchHeight;
        if (matchesBottom > position) {
          this.selectedResultIndex = i;
          this.selectedMatchIndex = Math.round((position - top) / matchHeight);
          top += this.selectedMatchIndex * matchHeight;
          bottom = top + matchHeight;
          break;
        }

        top = matchesBottom;
      }
    }

    if (this.element.scrollTop > top) {
      this.element.scrollTop = top;
    }

    if (this.element.scrollTop < bottom - this.element.offsetHeight) {
      this.element.scrollTop = bottom - this.element.offsetHeight;
    }

    etch.update(this);
  }

  moveDown() {
    if (this.selectedResultIndex === -1) {
      this.selectFirstResult();
      return;
    }

    this.userMovedSelection = true;
    const selectedResult = this.searchResults[this.selectedResultIndex];
    if (this.selectedMatchIndex < selectedResult.matches.length - 1 &&
        !this.collapsedResultIndices[this.selectedResultIndex]) {
      this.selectedMatchIndex++;
    } else if (this.selectedResultIndex < this.searchResults.length - 1) {
      this.selectedResultIndex++;
      this.selectedMatchIndex = -1;
    }

    etch.update(this).then(this.scrollToSelectedMatch.bind(this));
  }

  moveUp() {
    if (this.selectedResultIndex === -1) {
      this.selectFirstResult();
      return;
    }

    this.userMovedSelection = true;
    if (this.selectedMatchIndex >= 0) {
      this.selectedMatchIndex--;
    } else if (this.selectedResultIndex > 0) {
      this.selectedResultIndex--;
      const selectedResult = this.searchResults[this.selectedResultIndex];
      if (this.collapsedResultIndices[this.selectedResultIndex]) {
        this.selectedMatchIndex = -1;
      } else {
        this.selectedMatchIndex = selectedResult.matches.length - 1;
      }
    }

    etch.update(this).then(this.scrollToSelectedMatch.bind(this));
  }

  expandResult() {
    if (this.selectedResultIndex !== -1 && this.selectedMatchIndex == -1) {
      this.collapsedResultIndices[this.selectedResultIndex] = false;
      this.selectedMatchIndex = 0;
      this.renderResults();
    }
  }

  collapseResult() {
    if (this.selectedResultIndex !== -1) {
      this.collapsedResultIndices[this.selectedResultIndex] = true;
      this.selectedMatchIndex = -1;
      this.renderResults();
    }
  }

  confirmResult({pending} = {}) {
    if (this.selectedResultIndex !== -1) {
      if (this.selectedMatchIndex !== -1) {
        const result = this.searchResults[this.selectedResultIndex];
        const match = result.matches[this.selectedMatchIndex];
        atom.workspace
          .open(result.filePath, {
            pending,
            split: reverseDirections[atom.config.get('find-and-replace.projectSearchResultsPaneSplitDirection')]
          })
          .then(editor => {
            editor.setSelectedBufferRange(match.range, {autoscroll: true})
          });
      } else {
        this.collapsedResultIndices[this.selectedResultIndex] = !this.collapsedResultIndices[this.selectedResultIndex];
        this.renderResults();
      }
    }
  }

  copyResult() {
    if (this.selectedResultIndex !== -1) {
      if (this.selectedMatchIndex !== -1) {
        const result = this.searchResults[this.selectedResultIndex];
        const match = result.matches[this.selectedMatchIndex];
        atom.clipboard.write(match.lineText);
      }
    }
  }

  copyPath(event) {
    const pathElement = event.target.closest('.path');
    if (!pathElement) return;

    const filePath = event.target.dataset.path;
    let [rootPath, relativePath] = atom.project.relativizePath(filePath);
    if (rootPath && atom.project.getDirectories().length > 1) {
      relativePath = path.join(path.basename(rootPath), relativePath);
    }
    atom.clipboard.write(relativePath);
  }

  expandAllResults() {
    this.collapsedResultIndices = new Array(this.searchResults.length);
    this.collapsedResultIndices.fill(false);
    this.renderResults(Infinity);
  }

  collapseAllResults() {
    this.collapsedResultIndices = new Array(this.model.getPaths().length);
    this.collapsedResultIndices.fill(true);
    this.renderResults(Infinity);
  }

  scrollToSelectedMatch() {
    const resultElement = this.element.children[this.selectedResultIndex];

    let top = resultElement.offsetTop;
    let bottom = top + resultElement.offsetHeight;

    if (this.selectedMatchIndex !== -1) {
      const matchElement = resultElement.querySelectorAll('.search-result');
      top += matchElement.offsetTop;
      bottom = top + matchElement.offsetHeight;
    }

    if (bottom > this.element.scrollTop + this.element.scrollHeight) {
      this.element.scrollTop = bottom - this.element.scrollHeight;
    }

    if (top < this.scrollTop) {
      this.element.scrollTop = top;
    }
  }

  scrollToBottom() {
    this.renderResults(Infinity);
    this.element.scrollTop = this.element.scrollHeight;
  }

  scrollToTop() {
    this.element.scrollTop = 0;
  }

  selectedResultView() {
    const element = this.selectedElement()
    if (element) return this.resultViewsByElement.get(element)
  }
};
<|endoftext|>


<commit_before>module.exports = {
  extends: [
    "plugin:flowtype/recommended",
    "airbnb",
    "prettier",
    "prettier/react"
  ],
  rules: {
    "react/jsx-filename-extension": [1, { extensions: [".js"] }],
    "react/jsx-sort-props": [
      2,
      {
        ignoreCase: true,
        reservedFirst: false
      }
    ],
    "sort-keys": ["error", "asc", { caseSensitive: false, natural: true }],
    "import/extensions": "off",
    "import/no-extraneous-dependencies": [
      "error",
      {
        devDependencies: [
          "**/mock-*/**",
          "**/__tests__/**",
          "**/*.test.*",
          "**/fixtures/**",
          "**/*.stories*",
          "**/*.showcase*",
          "**/showcase-helper*",
          "**/scripts/**",
          "webpack.config*.js"
        ],
        optionalDependencies: false
      }
    ],
    "jsx-a11y/anchor-is-valid": [
      "error",
      {
        components: ["Link"],
        specialLink: ["url"],
        aspects: ["noHref", "invalidHref", "preferButton"]
      }
    ],
    "no-restricted-properties": [
      2,
      {
        object: "React",
        property: "Component",
        message: "Please destruct Component from React."
      },
      {
        object: "React",
        property: "PureComponent",
        message: "Please destruct PureComponent from React."
      }
    ]
  },
  settings: {
    "import/resolver": {
      node: {
        extensions: [".js", ".android.js", ".ios.js", ".web.js"]
      }
    }
  },
  root: true
};
<commit_msg>chore: remove eslint alphabetical ordering (#1909)<commit_after>module.exports = {
  extends: [
    "plugin:flowtype/recommended",
    "airbnb",
    "prettier",
    "prettier/react"
  ],
  rules: {
    "react/jsx-filename-extension": [1, { extensions: [".js"] }],
    "react/jsx-sort-props": [
      2,
      {
        ignoreCase: true,
        reservedFirst: false
      }
    ],
    "import/extensions": "off",
    "import/no-extraneous-dependencies": [
      "error",
      {
        devDependencies: [
          "**/mock-*/**",
          "**/__tests__/**",
          "**/*.test.*",
          "**/fixtures/**",
          "**/*.stories*",
          "**/*.showcase*",
          "**/showcase-helper*",
          "**/scripts/**",
          "webpack.config*.js"
        ],
        optionalDependencies: false
      }
    ],
    "jsx-a11y/anchor-is-valid": [
      "error",
      {
        components: ["Link"],
        specialLink: ["url"],
        aspects: ["noHref", "invalidHref", "preferButton"]
      }
    ],
    "no-restricted-properties": [
      2,
      {
        object: "React",
        property: "Component",
        message: "Please destruct Component from React."
      },
      {
        object: "React",
        property: "PureComponent",
        message: "Please destruct PureComponent from React."
      }
    ]
  },
  settings: {
    "import/resolver": {
      node: {
        extensions: [".js", ".android.js", ".ios.js", ".web.js"]
      }
    }
  },
  root: true
};
<|endoftext|>


<commit_before>define([
	'./createSyncStore',
	'./stateData',
	'dojo/_base/array'
], function (createSyncStore, stateData, arrayUtil) {

	var nextId = 0;
	var topHeavyData = arrayUtil.map(stateData.items, function (state) {
		return {
			id: nextId++,
			abbreviation: state.abbreviation,
			name: state.name,
			children: [{
				id: nextId++,
				abbreviation: 'US',
				name: 'United States of America'
			}]
		};
	});

	// Store with few children and many parents to exhibit any
	// issues due to bugs related to total disregarding level
	return createSyncStore({
		data: topHeavyData,
		getChildren: function (parent) {
			return createSyncStore({
				data: parent.children
			});
		},
		mayHaveChildren: function (parent) {
			return !!parent.children;
		}
	});
});
<commit_msg>testTopHeavyHierarchicalStore: use dstore/Tree<commit_after>define([
	'dstore/Tree',
	'./createSyncStore',
	'./stateData',
	'dojo/_base/array'
], function (Tree, createSyncStore, stateData, arrayUtil) {

	var nextId = 0;
	var topHeavyData = arrayUtil.map(stateData.items, function (state) {
		return {
			id: nextId++,
			abbreviation: state.abbreviation,
			name: state.name,
			hasChildren: true,
			parent: null
		};
	});

	// Store with few children and many parents to exhibit any
	// issues due to bugs related to total disregarding level
	arrayUtil.forEach(topHeavyData, function (state) {
		topHeavyData.push({
			id: nextId++,
			abbreviation: 'US',
			name: 'United States of America',
			hasChildren: false,
			parent: state.id
		});
	});

	return createSyncStore({ data: topHeavyData }, Tree).getRootCollection();
});
<|endoftext|>


<commit_before>/**
 * Analytics Module Component Stories.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import { generateReportBasedWidgetStories } from './utils/generate-widget-stories';
import DashboardAllTrafficWidget from '../assets/js/modules/analytics/components/dashboard/DashboardAllTrafficWidget';
import DashboardPopularPagesWidget from '../assets/js/modules/analytics/components/dashboard/DashboardPopularPagesWidget';
import DashboardBounceRateWidget from '../assets/js/modules/analytics/components/dashboard/DashboardBounceRateWidget';
import DashboardGoalsWidget from '../assets/js/modules/analytics/components/dashboard/DashboardGoalsWidget';
import DashboardUniqueVisitorsWidget from '../assets/js/modules/analytics/components/dashboard/DashboardUniqueVisitorsWidget';
import { STORE_NAME } from '../assets/js/modules/analytics/datastore/constants';
import {
	accountsPropertiesProfiles,
	goals,
	dashboardAllTrafficArgs,
	dashboardAllTrafficData,
	pageDashboardAllTrafficArgs,
	pageDashboardAllTrafficData,
	dashboardPopularPagesArgs,
	dashboardPopularPagesData,
	pageDashboardBounceRateWidgetArgs,
	pageDashboardBounceRateWidgetData,
	pageDashboardUniqueVisitorsSparkArgs,
	pageDashboardUniqueVisitorsSparkData,
	pageDashboardUniqueVisitorsVisitorArgs,
	pageDashboardUniqueVisitorsVisitorData,
	dashboardBounceRateWidgetArgs,
	dashboardBounceRateWidgetData,
	dashboardGoalsWidgetArgs,
	dashboardGoalsWidgetData,
	dashboardUniqueVisitorsSparkArgs,
	dashboardUniqueVisitorsVisitorArgs,
	dashboardUniqueVisitorsSparkData,
	dashboardUniqueVisitorsVisitorData,
} from '../assets/js/modules/analytics/datastore/__fixtures__';
import DashboardAllTrafficWidgetV2 from '../assets/js/modules/analytics/components/dashboard/DashboardAllTrafficWidgetV2';

/**
 * Defines some additional setup for all stories.
 *
 * @since 1.19.0
 *
 * @param {wp.data.registry} registry Registry with all available stores registered.
 */
const setup = ( registry ) => {
	const [ property ] = accountsPropertiesProfiles.properties;
	registry.dispatch( STORE_NAME ).receiveGetSettings( {
		// eslint-disable-next-line sitekit/camelcase-acronyms
		accountID: property.accountId,
		// eslint-disable-next-line sitekit/camelcase-acronyms
		internalWebPropertyID: property.internalWebPropertyId,
		// eslint-disable-next-line sitekit/camelcase-acronyms
		profileID: property.defaultProfileId,
	} );
};

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/All Traffic Widget',
	data: dashboardAllTrafficData,
	options: dashboardAllTrafficArgs,
	Component: DashboardAllTrafficWidget,
	wrapWidget: false,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/All Traffic Widget V2',
	data: dashboardAllTrafficData,
	options: dashboardAllTrafficArgs,
	Component: DashboardAllTrafficWidgetV2,
	wrapWidget: false,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Page Dashboard/All Traffic Widget',
	data: pageDashboardAllTrafficData,
	options: pageDashboardAllTrafficArgs,
	Component: DashboardAllTrafficWidget,
	wrapWidget: false,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/Bounce Rate Widget',
	data: dashboardBounceRateWidgetData,
	options: dashboardBounceRateWidgetArgs,
	Component: DashboardBounceRateWidget,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Page Dashboard/Bounce Rate Widget',
	data: pageDashboardBounceRateWidgetData,
	options: pageDashboardBounceRateWidgetArgs,
	Component: DashboardBounceRateWidget,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/Goals Widget',
	data: dashboardGoalsWidgetData,
	options: dashboardGoalsWidgetArgs,
	Component: DashboardGoalsWidget,
	additionalVariants: {
		'No Goals': { data: dashboardGoalsWidgetData, options: dashboardGoalsWidgetArgs },
	},
	additionalVariantCallbacks: {
		Loaded: ( dispatch ) => dispatch( STORE_NAME ).receiveGetGoals( goals ),
		'Data Unavailable': ( dispatch ) => dispatch( STORE_NAME ).receiveGetGoals( goals ),
	},
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/Unique Visitors Widget',
	data: [
		dashboardUniqueVisitorsVisitorData,
		dashboardUniqueVisitorsSparkData,
	],
	options: [
		dashboardUniqueVisitorsVisitorArgs,
		dashboardUniqueVisitorsSparkArgs,
	],
	Component: DashboardUniqueVisitorsWidget,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Page Dashboard/Unique Visitors Widget',
	data: [
		pageDashboardUniqueVisitorsVisitorData,
		pageDashboardUniqueVisitorsSparkData,
	],
	options: [
		pageDashboardUniqueVisitorsVisitorArgs,
		pageDashboardUniqueVisitorsSparkArgs,
	],
	Component: DashboardUniqueVisitorsWidget,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/Popular Pages Widget',
	data: dashboardPopularPagesData,
	options: dashboardPopularPagesArgs,
	Component: DashboardPopularPagesWidget,
	wrapWidget: false,
	setup,
} );
<commit_msg>Use preliminary Storybook data for new All Traffic widget and add TODO comments.<commit_after>/**
 * Analytics Module Component Stories.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import { generateReportBasedWidgetStories } from './utils/generate-widget-stories';
import DashboardAllTrafficWidget from '../assets/js/modules/analytics/components/dashboard/DashboardAllTrafficWidget';
import DashboardPopularPagesWidget from '../assets/js/modules/analytics/components/dashboard/DashboardPopularPagesWidget';
import DashboardBounceRateWidget from '../assets/js/modules/analytics/components/dashboard/DashboardBounceRateWidget';
import DashboardGoalsWidget from '../assets/js/modules/analytics/components/dashboard/DashboardGoalsWidget';
import DashboardUniqueVisitorsWidget from '../assets/js/modules/analytics/components/dashboard/DashboardUniqueVisitorsWidget';
import { STORE_NAME } from '../assets/js/modules/analytics/datastore/constants';
import {
	accountsPropertiesProfiles,
	goals,
	dashboardAllTrafficArgs,
	dashboardAllTrafficData,
	pageDashboardAllTrafficArgs,
	pageDashboardAllTrafficData,
	dashboardPopularPagesArgs,
	dashboardPopularPagesData,
	pageDashboardBounceRateWidgetArgs,
	pageDashboardBounceRateWidgetData,
	pageDashboardUniqueVisitorsSparkArgs,
	pageDashboardUniqueVisitorsSparkData,
	pageDashboardUniqueVisitorsVisitorArgs,
	pageDashboardUniqueVisitorsVisitorData,
	dashboardBounceRateWidgetArgs,
	dashboardBounceRateWidgetData,
	dashboardGoalsWidgetArgs,
	dashboardGoalsWidgetData,
	dashboardUniqueVisitorsSparkArgs,
	dashboardUniqueVisitorsVisitorArgs,
	dashboardUniqueVisitorsSparkData,
	dashboardUniqueVisitorsVisitorData,
} from '../assets/js/modules/analytics/datastore/__fixtures__';
import DashboardAllTrafficWidgetV2 from '../assets/js/modules/analytics/components/dashboard/DashboardAllTrafficWidgetV2';

/**
 * Defines some additional setup for all stories.
 *
 * @since 1.19.0
 *
 * @param {wp.data.registry} registry Registry with all available stores registered.
 */
const setup = ( registry ) => {
	const [ property ] = accountsPropertiesProfiles.properties;
	registry.dispatch( STORE_NAME ).receiveGetSettings( {
		// eslint-disable-next-line sitekit/camelcase-acronyms
		accountID: property.accountId,
		// eslint-disable-next-line sitekit/camelcase-acronyms
		internalWebPropertyID: property.internalWebPropertyId,
		// eslint-disable-next-line sitekit/camelcase-acronyms
		profileID: property.defaultProfileId,
	} );
};

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/All Traffic Widget',
	data: dashboardAllTrafficData,
	options: dashboardAllTrafficArgs,
	Component: DashboardAllTrafficWidget,
	wrapWidget: false,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/All Traffic Widget V2',
	data: [], // TODO: Provide fixtures/mocks for all necessary responses.
	options: { // TODO: Provide fixtures/mocks for all necessary requests.
		startDate: '2020-11-01',
		endDate: '2020-11-28',
		metrics: [
			{
				expression: 'ga:users',
				alias: 'Users',
			},
		],
		dimensions: [
			'ga:channelGrouping',
		],
	},
	Component: DashboardAllTrafficWidgetV2,
	wrapWidget: false,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Page Dashboard/All Traffic Widget',
	data: pageDashboardAllTrafficData,
	options: pageDashboardAllTrafficArgs,
	Component: DashboardAllTrafficWidget,
	wrapWidget: false,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/Bounce Rate Widget',
	data: dashboardBounceRateWidgetData,
	options: dashboardBounceRateWidgetArgs,
	Component: DashboardBounceRateWidget,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Page Dashboard/Bounce Rate Widget',
	data: pageDashboardBounceRateWidgetData,
	options: pageDashboardBounceRateWidgetArgs,
	Component: DashboardBounceRateWidget,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/Goals Widget',
	data: dashboardGoalsWidgetData,
	options: dashboardGoalsWidgetArgs,
	Component: DashboardGoalsWidget,
	additionalVariants: {
		'No Goals': { data: dashboardGoalsWidgetData, options: dashboardGoalsWidgetArgs },
	},
	additionalVariantCallbacks: {
		Loaded: ( dispatch ) => dispatch( STORE_NAME ).receiveGetGoals( goals ),
		'Data Unavailable': ( dispatch ) => dispatch( STORE_NAME ).receiveGetGoals( goals ),
	},
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/Unique Visitors Widget',
	data: [
		dashboardUniqueVisitorsVisitorData,
		dashboardUniqueVisitorsSparkData,
	],
	options: [
		dashboardUniqueVisitorsVisitorArgs,
		dashboardUniqueVisitorsSparkArgs,
	],
	Component: DashboardUniqueVisitorsWidget,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Page Dashboard/Unique Visitors Widget',
	data: [
		pageDashboardUniqueVisitorsVisitorData,
		pageDashboardUniqueVisitorsSparkData,
	],
	options: [
		pageDashboardUniqueVisitorsVisitorArgs,
		pageDashboardUniqueVisitorsSparkArgs,
	],
	Component: DashboardUniqueVisitorsWidget,
	setup,
} );

generateReportBasedWidgetStories( {
	moduleSlugs: [ 'analytics' ],
	datastore: STORE_NAME,
	group: 'Analytics Module/Components/Dashboard/Popular Pages Widget',
	data: dashboardPopularPagesData,
	options: dashboardPopularPagesArgs,
	Component: DashboardPopularPagesWidget,
	wrapWidget: false,
	setup,
} );
<|endoftext|>


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

  var mozjpeg = require('imagemin-mozjpeg');

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

    clean: ['dist', '.tmp'],

    copy: {
      dist: {
        files: [
          { expand: true, src: ['src/index.html'], dest: 'dist/', filter: 'isFile', flatten: true },
          { expand: true, src: ['src/sitemap.xml'], dest: 'dist/', filter: 'isFile', flatten: true },
          { expand: true, src: ['src/favicon*'], dest: 'dist/', filter: 'isFile', flatten: true },
          { expand: true, src: ['src/preview.jpg'], dest: 'dist/', filter: 'isFile', flatten: true },
          { expand: true, src: ['src/font/*'], dest: 'dist/font/', flatten: true },
          { expand: true, src: ['src/data/*'], dest: 'dist/data/', flatten: true },
          { expand: true, src: ['src/template/*'], dest: 'dist/template/', flatten: true },
          { expand: true, src: ['src/img/*'], dest: 'dist/img/', flatten: true }
        ]
      }
    },

    useminPrepare: {
      html: ['src/index.html']
    },

    usemin: {
      options: {
        blockReplacements: {
          js: function (block) {

            return '<script async src="' + block.dest + '"><\/script>';
          }
        }
      },
      html: ['dist/index.html']
    },

    compass: {
      dist: {
        options: {
          sassDir: 'src/style',
          cssDir: 'src/style'
        }
      }
    },

    cssmin: {
      combine: {
        files: {
          'dist/css/style.min.css': ['src/style/main.css']
        }
      }
    },

    ngAnnotate: {
      options: {
        singleQuotes: true
      },

      dist: {
        files: {
          '.tmp/ngAnnotate/app.js': [
            'src/script/app.js',
            'src/script/routes.js',
            'src/script/services/jsonLoader.js',
            'src/script/services/metaTags.js',
            'src/script/controllers/navCtrl.js',
            'src/script/controllers/metaCtrl.js',
            'src/script/controllers/projectCtrl.js',
            'src/script/controllers/projectMetaCtrl.js',
            'src/script/components/dashcaseFilter.js',
            'src/script/components/feedReader.js'
          ]
        }
      }
    },

    uglify: {
      dist: {
        files: {
          '.tmp/uglify/app.min.js': ['.tmp/ngAnnotate/app.js']
        }
      }
    },

    concat: {
      options: {
        separator: ';',
        sourceMap: true
      },
      dist: {
        src: [
          'vendor/angular/angular.min.js',
          'vendor/angular/angular-route.min.js',
          '.tmp/uglify/app.min.js'
        ],
        dest: 'dist/src/main.min.js'
      }
    },

    'json-minify': {
      dist: {
        files: 'dist/data/*.json'
      }
    },

    imagemin: {
      jpg: {
        options: {
          progressive: true,
          use: [mozjpeg()]
        },
        files: [{
          expand: true,
          cwd: 'src/img/project/',
          src: ['*.jpg'],
          dest: 'dist/img/project/',
          ext: '.jpg'
        }]
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-compass');
  grunt.loadNpmTasks('grunt-usemin');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-ng-annotate');
  grunt.loadNpmTasks('grunt-json-minify');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('dist', [
    'clean', 'copy', 'compass', 'useminPrepare', 'cssmin', 'ngAnnotate', 'uglify', 'concat', 'usemin', 'json-minify', 'imagemin'
  ]);
};
<commit_msg>Update Gruntfile to match new favicon path<commit_after>module.exports = function (grunt) {

  var mozjpeg = require('imagemin-mozjpeg');

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

    clean: ['dist', '.tmp'],

    copy: {
      dist: {
        files: [
          { expand: true, src: ['src/index.html'], dest: 'dist/', filter: 'isFile', flatten: true },
          { expand: true, src: ['src/sitemap.xml'], dest: 'dist/', filter: 'isFile', flatten: true },
          { expand: true, src: ['src/favicon.ico'], dest: 'dist/', filter: 'isFile', flatten: true },
          { expand: true, src: ['src/font/*'], dest: 'dist/font/', flatten: true },
          { expand: true, src: ['src/data/*'], dest: 'dist/data/', flatten: true },
          { expand: true, src: ['src/template/*'], dest: 'dist/template/', flatten: true },
          { expand: true, src: ['src/img/*'], dest: 'dist/img/', flatten: true }
        ]
      }
    },

    useminPrepare: {
      html: ['src/index.html']
    },

    usemin: {
      options: {
        blockReplacements: {
          js: function (block) {

            return '<script async src="' + block.dest + '"><\/script>';
          }
        }
      },
      html: ['dist/index.html']
    },

    compass: {
      dist: {
        options: {
          sassDir: 'src/style',
          cssDir: 'src/style'
        }
      }
    },

    cssmin: {
      combine: {
        files: {
          'dist/css/style.min.css': ['src/style/main.css']
        }
      }
    },

    ngAnnotate: {
      options: {
        singleQuotes: true
      },

      dist: {
        files: {
          '.tmp/ngAnnotate/app.js': [
            'src/script/app.js',
            'src/script/routes.js',
            'src/script/services/jsonLoader.js',
            'src/script/services/metaTags.js',
            'src/script/controllers/navCtrl.js',
            'src/script/controllers/metaCtrl.js',
            'src/script/controllers/projectCtrl.js',
            'src/script/controllers/projectMetaCtrl.js',
            'src/script/components/dashcaseFilter.js',
            'src/script/components/feedReader.js'
          ]
        }
      }
    },

    uglify: {
      dist: {
        files: {
          '.tmp/uglify/app.min.js': ['.tmp/ngAnnotate/app.js']
        }
      }
    },

    concat: {
      options: {
        separator: ';',
        sourceMap: true
      },
      dist: {
        src: [
          'vendor/angular/angular.min.js',
          'vendor/angular/angular-route.min.js',
          '.tmp/uglify/app.min.js'
        ],
        dest: 'dist/src/main.min.js'
      }
    },

    'json-minify': {
      dist: {
        files: 'dist/data/*.json'
      }
    },

    imagemin: {
      jpg: {
        options: {
          progressive: true,
          use: [mozjpeg()]
        },
        files: [{
          expand: true,
          cwd: 'src/img/project/',
          src: ['*.jpg'],
          dest: 'dist/img/project/',
          ext: '.jpg'
        }]
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-compass');
  grunt.loadNpmTasks('grunt-usemin');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-ng-annotate');
  grunt.loadNpmTasks('grunt-json-minify');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('dist', [
    'clean', 'copy', 'compass', 'useminPrepare', 'cssmin', 'ngAnnotate', 'uglify', 'concat', 'usemin', 'json-minify', 'imagemin'
  ]);
};
<|endoftext|>