<commit_before>(function() {
    var Ext = window.Ext4 || window.Ext;

    /**
     * Iteration Tracking Board App
     * The Iteration Tracking Board can be used to visualize and manage your User Stories and Defects within an Iteration.
     */
    Ext.define('Rally.apps.iterationtrackingboard.IterationTrackingBoardApp', {
        extend: 'Rally.app.TimeboxScopedApp',
        requires: [
            'Rally.data.ModelFactory',
            'Rally.ui.gridboard.GridBoard',
            'Rally.ui.grid.TreeGrid',
            'Rally.ui.gridboard.plugin.GridBoardAddNew',
            'Rally.ui.gridboard.plugin.GridBoardOwnerFilter',
            'Rally.ui.gridboard.plugin.GridBoardFilterInfo',
            'Rally.ui.gridboard.plugin.GridBoardArtifactTypeChooser',
            'Rally.ui.gridboard.plugin.GridBoardFieldPicker',
            'Rally.ui.cardboard.plugin.ColumnPolicy',
            'Rally.ui.gridboard.plugin.GridBoardFilterInfo',
            'Rally.ui.gridboard.plugin.GridBoardFilterControl',
            'Rally.ui.filter.view.ModelFilter'
        ],
        mixins: ['Rally.app.CardFieldSelectable'],
        componentCls: 'iterationtrackingboard',
        alias: 'widget.rallyiterationtrackingboard',

        settingsScope: 'project',
        scopeType: 'iteration',

        config: {
            defaultSettings: {
                showCardAge: true,
                cardAgeThreshold: 3,
                cardFields: 'Parent,Tasks,Defects,Discussion,PlanEstimate'
            }
        },

        onScopeChange: function(scope) {
            this.remove('gridBoard');
            this._loadModels();
        },

        getSettingsFields: function () {
            var fields = this.callParent(arguments);

            if (!this.isShowingBlankSlate()) {
                this.appendCardFieldPickerSetting(fields);
                if (this.showGridSettings) {
                    fields.push({settingsType: 'grid', html: 'no grid settings'});
                }
            }

            fields.push({
                type: 'cardage',
                settingsType: 'board',
                config: {
                    margin: '0 0 0 80',
                    width: 300
                }
            });

            return fields;
        },

        launch: function() {
            this.showGridSettings = this.getContext().isFeatureEnabled('ITERATION_TRACKING_BOARD_GRID_TOGGLE');
            this.callParent(arguments);
        },

        _addGridBoard: function(compositeModel, treeGridModel) {
            var plugins = ['rallygridboardaddnew'],
                context = this.getContext();

            if (context.isFeatureEnabled('F4359_FILTER')) {
                plugins.push({
                    ptype: 'rallygridboardfiltercontrol',
                    filterControlConfig: {
                        cls: 'secondary small button picto gridboard-filter-control',
                        stateful: true,
                        stateId: context.getScopedStateId('iteration-tracking-filter-button'),
                        items: [
                            {
                                xtype: 'rallymodelfilter',
                                models: compositeModel.getArtifactComponentModels()
                            }
                        ]
                    }
                });
            }

            plugins = plugins.concat([{
                    ptype: 'rallygridboardfilterinfo',
                    isGloballyScoped: Ext.isEmpty(this.getSetting('project')) ? true : false,
                    stateId: 'iteration-tracking-owner-filter-' + this.getAppId()
                },
                'rallygridboardownerfilter',
                'rallygridboardfieldpicker'
            ]);

            if (context.isFeatureEnabled('SHOW_ARTIFACT_CHOOSER_ON_ITERATION_BOARDS')) {
                plugins.push({
                    ptype: 'rallygridboardartifacttypechooser',
                    artifactTypePreferenceKey: 'artifact-types',
                    showAgreements: true
                });
            }
            this.plugins = plugins;
            this._addGrid(this._getGridConfig(treeGridModel));
        },

        _addGrid: function(gridConfig){
            var context = this.getContext();

            this.gridboard = this.add({
                itemId: 'gridBoard',
                xtype: 'rallygridboard',
                stateId: 'iterationtracking-gridboard',
                context: context,
                enableToggle: context.isFeatureEnabled('ITERATION_TRACKING_BOARD_GRID_TOGGLE'),
                plugins: this.plugins,
                modelNames: this.modelNames,
                allModelNames: context.isFeatureEnabled('F2903_USE_ITERATION_TREE_GRID') ? this.allModelNames : null,
                cardBoardConfig: {
                    columnConfig: {
                        additionalFetchFields: ['PortfolioItem'],
                        plugins: [{
                            ptype: 'rallycolumnpolicy',
                            app: this
                        }]
                    },
                    cardConfig: {
                        fields: this.getCardFieldNames(),
                        showAge: this.getSetting('showCardAge') ? this.getSetting('cardAgeThreshold') : -1,
                        showBlockedReason: true
                    },
                    listeners: {
                        filter: this._onBoardFilter,
                        filtercomplete: this._onBoardFilterComplete
                    }
                },
                gridConfig: gridConfig,
                addNewPluginConfig: {
                    style: {
                        'float': 'left'
                    }
                },
                listeners: {
                    load: this._onLoad,
                    toggle: this._publishContentUpdated,
                    recordupdate: this._publishContentUpdatedNoDashboardLayout,
                    recordcreate: this._publishContentUpdatedNoDashboardLayout,
                    scope: this
                }
            });
        },

        _getGridConfig: function(treeGridModel, columns) {
            var context = this.getContext();

            var gridConfig = {
                storeConfig: {
                    autoLoad: context.isFeatureEnabled('F4359_FILTER') ? false : true
                },
                columnCfgs: this._getGridColumns(),
                enableBulkEdit: context.isFeatureEnabled('EXT4_GRID_BULK_EDIT'),
                stateful: context.isFeatureEnabled('ITERATION_TRACKING_PERSISTENT_PREFERENCES')
            };

            if (context.isFeatureEnabled('F2903_USE_ITERATION_TREE_GRID')) {
                Ext.apply(gridConfig, {
                    xtype: 'rallytreegrid',
                    model: treeGridModel,
                    storeConfig: {
                        nodeParam: 'Parent',
                        parentFieldNames: ['Requirement', 'WorkProduct'],
                        parentTypes: ['HierarchicalRequirement', 'Defect', 'DefectSuite', 'TestSet'],
                        childTypes: ['Defect', 'Task', 'TestCase'],
                        topLevelQuery: this.context.getTimeboxScope().getQueryFilter(),
                        sorters: ['Rank DESC'],
                        fetch: ['FormattedID', 'Tasks', 'Defects', 'TestCases']
                    },
                    rootVisible: false,
                    stateful: true,
                    columnCfgs: columns ? this._getGridColumns(columns) : null,
                    defaultColumnCfgs: this._getGridColumns(),
                    isLeaf: function(record) {
                        return  (!record.raw.Tasks || record.raw.Tasks.Count === 0) &&
                                (!record.raw.Defects || record.raw.Defects.Count === 0) &&
                                (!record.raw.TestCases || record.raw.TestCases.Count === 0);
                    },
                    getIcon: function(record) {
                        return '';
                    },
                    listeners:{
                        reconfigure: function(columns) {
                            this._onReconfigure(columns, treeGridModel);
                        },
                        scope: this
                    }
                });
            }
            return gridConfig;
        },

        _onReconfigure: function(columns, treeGridModel) {
            this.remove(this.gridboard, true);
            this._addGrid(this._getGridConfig(treeGridModel, columns));
        },

        _getGridColumns: function(columns) {
            var context = this.getContext(),
                result = ['FormattedID', 'Name', 'ScheduleState', 'Blocked', 'PlanEstimate', 'TaskStatus', 'TaskEstimateTotal', 'TaskRemainingTotal', 'Owner', 'DefectStatus', 'Discussion'];

            if (context.isFeatureEnabled('F2903_USE_ITERATION_TREE_GRID')) {
                if (columns) {
                    result = columns;
                }
                _.pull(result, 'FormattedID');
            }

            return result;
        },

        _loadModels: function() {
            var topLevelTypes = ['User Story', 'Defect', 'Defect Suite', 'Test Set'],
                allTypes = topLevelTypes.concat(['Task', 'Test Case']);
            Rally.data.ModelFactory.getModels({
                types: allTypes,
                context: this.getContext().getDataContext(),
                success: function(models) {
                    var topLevelModels = _.filter(models, function(model, key) {
                            return _.contains(topLevelTypes, key);
                        }),
                        compositeModel = Rally.domain.WsapiModelBuilder.buildCompositeArtifact(topLevelModels, this.getContext()),
                        treeGridModel;
                    this.modelNames = topLevelTypes;
                    this.allModelNames = allTypes;
                    if (this.getContext().isFeatureEnabled('F2903_USE_ITERATION_TREE_GRID')) {
                        treeGridModel = Rally.domain.WsapiModelBuilder.buildCompositeArtifact(_.values(models), this.getContext());
                    }
                    this._addGridBoard(compositeModel, treeGridModel);
                },
                scope: this
            });
        },

        _onLoad: function() {
            this._publishContentUpdated();
            if (Rally.BrowserTest) {
                Rally.BrowserTest.publishComponentReady(this);
            }
        },

        _onBoardFilter: function() {
            this.setLoading(true);
        },

        _onBoardFilterComplete: function() {
            this.setLoading(false);
        },

        _publishContentUpdated: function() {
            this.fireEvent('contentupdated');
        },

        _publishContentUpdatedNoDashboardLayout: function() {
            this.fireEvent('contentupdated', {dashboardLayout: false});
        }
    });
})();
<commit_msg>S56018 added owner filter to grid pop over filter on the iteration tracking board app<commit_after>(function() {
    var Ext = window.Ext4 || window.Ext;

    /**
     * Iteration Tracking Board App
     * The Iteration Tracking Board can be used to visualize and manage your User Stories and Defects within an Iteration.
     */
    Ext.define('Rally.apps.iterationtrackingboard.IterationTrackingBoardApp', {
        extend: 'Rally.app.TimeboxScopedApp',
        requires: [
            'Rally.data.ModelFactory',
            'Rally.ui.gridboard.GridBoard',
            'Rally.ui.grid.TreeGrid',
            'Rally.ui.gridboard.plugin.GridBoardAddNew',
            'Rally.ui.gridboard.plugin.GridBoardOwnerFilter',
            'Rally.ui.gridboard.plugin.GridBoardFilterInfo',
            'Rally.ui.gridboard.plugin.GridBoardArtifactTypeChooser',
            'Rally.ui.gridboard.plugin.GridBoardFieldPicker',
            'Rally.ui.cardboard.plugin.ColumnPolicy',
            'Rally.ui.gridboard.plugin.GridBoardFilterInfo',
            'Rally.ui.gridboard.plugin.GridBoardFilterControl',
            'Rally.ui.filter.view.ModelFilter',
            'Rally.ui.filter.view.OwnerFilter'
        ],
        mixins: ['Rally.app.CardFieldSelectable'],
        componentCls: 'iterationtrackingboard',
        alias: 'widget.rallyiterationtrackingboard',

        settingsScope: 'project',
        scopeType: 'iteration',

        config: {
            defaultSettings: {
                showCardAge: true,
                cardAgeThreshold: 3,
                cardFields: 'Parent,Tasks,Defects,Discussion,PlanEstimate'
            }
        },

        onScopeChange: function(scope) {
            this.remove('gridBoard');
            this._loadModels();
        },

        getSettingsFields: function () {
            var fields = this.callParent(arguments);

            if (!this.isShowingBlankSlate()) {
                this.appendCardFieldPickerSetting(fields);
                if (this.showGridSettings) {
                    fields.push({settingsType: 'grid', html: 'no grid settings'});
                }
            }

            fields.push({
                type: 'cardage',
                settingsType: 'board',
                config: {
                    margin: '0 0 0 80',
                    width: 300
                }
            });

            return fields;
        },

        launch: function() {
            this.showGridSettings = this.getContext().isFeatureEnabled('ITERATION_TRACKING_BOARD_GRID_TOGGLE');
            this.callParent(arguments);
        },

        _addGridBoard: function(compositeModel, treeGridModel) {
            var plugins = ['rallygridboardaddnew'],
                context = this.getContext();

            if (context.isFeatureEnabled('F4359_FILTER')) {
                plugins.push({
                    ptype: 'rallygridboardfiltercontrol',
                    filterControlConfig: {
                        cls: 'secondary small button picto gridboard-filter-control',
                        stateful: true,
                        stateId: context.getScopedStateId('iteration-tracking-filter-button'),
                        items: [
                            {
                                xtype: 'rallyownerfilter',
                                margin: '0 5',
                                project: this.getContext().getProjectRef()
                            },
                            {
                                xtype: 'rallymodelfilter',
                                models: compositeModel.getArtifactComponentModels()
                            }
                        ]
                    }
                });
            }

            plugins = plugins.concat([{
                    ptype: 'rallygridboardfilterinfo',
                    isGloballyScoped: Ext.isEmpty(this.getSetting('project')) ? true : false,
                    stateId: 'iteration-tracking-owner-filter-' + this.getAppId()
                },
                'rallygridboardownerfilter',
                'rallygridboardfieldpicker'
            ]);

            if (context.isFeatureEnabled('SHOW_ARTIFACT_CHOOSER_ON_ITERATION_BOARDS')) {
                plugins.push({
                    ptype: 'rallygridboardartifacttypechooser',
                    artifactTypePreferenceKey: 'artifact-types',
                    showAgreements: true
                });
            }
            this.plugins = plugins;
            this._addGrid(this._getGridConfig(treeGridModel));
        },

        _addGrid: function(gridConfig){
            var context = this.getContext();

            this.gridboard = this.add({
                itemId: 'gridBoard',
                xtype: 'rallygridboard',
                stateId: 'iterationtracking-gridboard',
                context: context,
                enableToggle: context.isFeatureEnabled('ITERATION_TRACKING_BOARD_GRID_TOGGLE'),
                plugins: this.plugins,
                modelNames: this.modelNames,
                allModelNames: context.isFeatureEnabled('F2903_USE_ITERATION_TREE_GRID') ? this.allModelNames : null,
                cardBoardConfig: {
                    columnConfig: {
                        additionalFetchFields: ['PortfolioItem'],
                        plugins: [{
                            ptype: 'rallycolumnpolicy',
                            app: this
                        }]
                    },
                    cardConfig: {
                        fields: this.getCardFieldNames(),
                        showAge: this.getSetting('showCardAge') ? this.getSetting('cardAgeThreshold') : -1,
                        showBlockedReason: true
                    },
                    listeners: {
                        filter: this._onBoardFilter,
                        filtercomplete: this._onBoardFilterComplete
                    }
                },
                gridConfig: gridConfig,
                addNewPluginConfig: {
                    style: {
                        'float': 'left'
                    }
                },
                listeners: {
                    load: this._onLoad,
                    toggle: this._publishContentUpdated,
                    recordupdate: this._publishContentUpdatedNoDashboardLayout,
                    recordcreate: this._publishContentUpdatedNoDashboardLayout,
                    scope: this
                }
            });
        },

        _getGridConfig: function(treeGridModel, columns) {
            var context = this.getContext();

            var gridConfig = {
                storeConfig: {
                    autoLoad: context.isFeatureEnabled('F4359_FILTER') ? false : true
                },
                columnCfgs: this._getGridColumns(),
                enableBulkEdit: context.isFeatureEnabled('EXT4_GRID_BULK_EDIT'),
                stateful: context.isFeatureEnabled('ITERATION_TRACKING_PERSISTENT_PREFERENCES')
            };

            if (context.isFeatureEnabled('F2903_USE_ITERATION_TREE_GRID')) {
                Ext.apply(gridConfig, {
                    xtype: 'rallytreegrid',
                    model: treeGridModel,
                    storeConfig: {
                        nodeParam: 'Parent',
                        parentFieldNames: ['Requirement', 'WorkProduct'],
                        parentTypes: ['HierarchicalRequirement', 'Defect', 'DefectSuite', 'TestSet'],
                        childTypes: ['Defect', 'Task', 'TestCase'],
                        topLevelQuery: this.context.getTimeboxScope().getQueryFilter(),
                        sorters: ['Rank DESC'],
                        fetch: ['FormattedID', 'Tasks', 'Defects', 'TestCases']
                    },
                    rootVisible: false,
                    stateful: true,
                    columnCfgs: columns ? this._getGridColumns(columns) : null,
                    defaultColumnCfgs: this._getGridColumns(),
                    isLeaf: function(record) {
                        return  (!record.raw.Tasks || record.raw.Tasks.Count === 0) &&
                                (!record.raw.Defects || record.raw.Defects.Count === 0) &&
                                (!record.raw.TestCases || record.raw.TestCases.Count === 0);
                    },
                    getIcon: function(record) {
                        return '';
                    },
                    listeners:{
                        reconfigure: function(columns) {
                            this._onReconfigure(columns, treeGridModel);
                        },
                        scope: this
                    }
                });
            }
            return gridConfig;
        },

        _onReconfigure: function(columns, treeGridModel) {
            this.remove(this.gridboard, true);
            this._addGrid(this._getGridConfig(treeGridModel, columns));
        },

        _getGridColumns: function(columns) {
            var context = this.getContext(),
                result = ['FormattedID', 'Name', 'ScheduleState', 'Blocked', 'PlanEstimate', 'TaskStatus', 'TaskEstimateTotal', 'TaskRemainingTotal', 'Owner', 'DefectStatus', 'Discussion'];

            if (context.isFeatureEnabled('F2903_USE_ITERATION_TREE_GRID')) {
                if (columns) {
                    result = columns;
                }
                _.pull(result, 'FormattedID');
            }

            return result;
        },

        _loadModels: function() {
            var topLevelTypes = ['User Story', 'Defect', 'Defect Suite', 'Test Set'],
                allTypes = topLevelTypes.concat(['Task', 'Test Case']);
            Rally.data.ModelFactory.getModels({
                types: allTypes,
                context: this.getContext().getDataContext(),
                success: function(models) {
                    var topLevelModels = _.filter(models, function(model, key) {
                            return _.contains(topLevelTypes, key);
                        }),
                        compositeModel = Rally.domain.WsapiModelBuilder.buildCompositeArtifact(topLevelModels, this.getContext()),
                        treeGridModel;
                    this.modelNames = topLevelTypes;
                    this.allModelNames = allTypes;
                    if (this.getContext().isFeatureEnabled('F2903_USE_ITERATION_TREE_GRID')) {
                        treeGridModel = Rally.domain.WsapiModelBuilder.buildCompositeArtifact(_.values(models), this.getContext());
                    }
                    this._addGridBoard(compositeModel, treeGridModel);
                },
                scope: this
            });
        },

        _onLoad: function() {
            this._publishContentUpdated();
            if (Rally.BrowserTest) {
                Rally.BrowserTest.publishComponentReady(this);
            }
        },

        _onBoardFilter: function() {
            this.setLoading(true);
        },

        _onBoardFilterComplete: function() {
            this.setLoading(false);
        },

        _publishContentUpdated: function() {
            this.fireEvent('contentupdated');
        },

        _publishContentUpdatedNoDashboardLayout: function() {
            this.fireEvent('contentupdated', {dashboardLayout: false});
        }
    });
})();
<|endoftext|>


<commit_before>/**
 *  \details © 2011  Open Ximdex Evolution SL [http://www.ximdex.org]
 *
 *  Ximdex a Semantic Content Management System (CMS)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published
 *  by the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  See the Affero GNU General Public License for more details.
 *  You should have received a copy of the Affero GNU General Public License
 *  version 3 along with Ximdex (see LICENSE file).
 *
 *  If not, visit http://gnu.org/licenses/agpl-3.0.html.
 *
 *  @author Ximdex DevTeam <dev@ximdex.com>
 *  @version $Revision$
 */

/**
 * Control the forms submission logic.
 */

X.FormsManager = Object.xo_create({

	buttons: null,

	_init: function(options) {

		this.options = Object.extend({
			actionView: null,
			iframeId: '',
			actionContainer: null,
			form: null,
			searches: [
				'(not_empty)', '(is_url)', '(is_email)', '(js_val_min)__([^\d]+)',
				'(field_equals)__([^\\s]+)', '(check_group)__([^\\s]+)', '(js_val_alphanumeric)',
				'(js_val_unique_name)', '(js_val_unique_url)'
			]
		}, options);

		// Don't want the jQuery object, want the DOMElement
		this.options.form = $(this.options.form).get(0);

		this.options.form.getFormMgr = function() {
			return this;
		}.bind(this);

		this._checkInputFields();
		this._registerButtons();
	},

	/**
	 * Checks and corrects inputs behaviours.
	 */
	_checkInputFields: function() {

		var $fields = $('input[type=text]', this.options.form);

		// Don't send a form when enter key pressed
		$fields.keydown(function(event) {
			if (event.keyCode == 13) {
				return false;
			}
		});
	},

	/**
	 * Register click events on all form buttons with the class "validate"
	 */
	_registerButtons: function() {

		this.buttons = [];

		// Register buttons that will send the form
		$('.validate', this.options.form).each(function(index, button) {
			this.registerButton(button);
		}.bind(this));

		// Register buttons for reseting the form
		$('.reset-button', this.options.form).each(function(index, button) {
			button.click(function() {
				this.options.form.reset();
				return false;
			});
		}.bind(this));
	},

	/**
	 * Extends a button with methods for retrieve the form and the FormManager object.
	 * Creates a collection that stores "beforeSubmit" callbacks.
	 * If one callback return TRUE the form submission will be aborted.
	 *
	 * button: the DOMElement that will act as a submit button when clicked.
	 * confirm: When TRUE a confirmation message will be shown.
	 * message: The confirmation message. When NULL, the value attribute of the button will be used.
	 * file: ???
	 */
	registerButton: function(button, options) {

		button = $(button).get(0);

		options = $.extend({
			confirm: true,
			message: null,
			file: 0,
			jsonResponse: true
		}, options);

		button = $.extend(button, {
			getForm: function() {
				return this.options.form;
			}.bind(this),
			getFormMgr: function() {
				return this;
			}.bind(this),
			beforeSubmit: new X.Collection({unique: true})
		});

		$(button).click(function(event) {

			// Call the callbacks, if one of them returns TRUE the form will not be submitted
			var submit = true;
			var i = 0, l = this.beforeSubmit.size();
			while (submit && i<l) {
				var cb = this.beforeSubmit.get(i);
				if (Object.isFunction(cb)) {
					var abort = cb(event, this);
					submit = abort === true ? false : true;
				}
				i++;
			}

			if (!submit) {
				//console.log('[formsManager]: Aborting sendForm.');
				return;
			}

			return this.getFormMgr().sendForm($.extend({
				button: this
			}, options));
		});

		this.buttons.push(button);
		return button;
	},

	getButtons: function() {
		return this.buttons;
	},

	getActionContainer: function() {
		return this.options.actionContainer;
	},

	setActionContainer: function(container) {
		this.options.actionContainer = container;
		return this;
	},

	/**
	 * button: the DOMElement that will act as a submit button when clicked.
	 * confirm: When TRUE a confirmation message will be shown.
	 * message: The confirmation message. When NULL the value attribute of the button will be used.
	 * file: ???
	 */
	sendForm: function(options) {

		options = $.extend({
			button: null,
			confirm: true,
			message: null,
			file: 0,
			jsonResponse: false
		}, options);

		// Ensure the form and iframe IDs are unique
		var formId = $(this.options.form).attr('id');
		if (Object.isEmpty(formId)) {
			formId = 'form_' + X.getUID();
			$(this.options.form).attr('id', formId);
		}
		this.options.iframeId = 'form_sender_' + formId;

		// Validate the form
		if (!Object.isEmpty($(this.options.form).data('validator')) || $(this.options.form).data('validator') == null) {
			$(this.options.form).validate(
				{
					rules: this._getConstraints(this.options.form),
					messages: this._getMessages(this.options.form),
					errorElement: "span",
					errorPlacement: function(error, element) {

						$span = $("").addClass("error_block");
						if (element[0].tagName.toLowerCase()=="select" && element.parent().hasClass("input-select"))
							$span.addClass("select_block");
						element.wrap($span);
						element.before(error);
					}
				});
		}

		// Submit button
		var submitButton = options.button || $('.validate', this.options.form);
		var message = options.message || $('~ .submit_message', submitButton).attr('value');
		var dialog = this._getDialog(this.options.form, message);
		if (message == '' || message == undefined) {
			options.confirm = false;
		}

		// Send the form
		if (!options.confirm) {
			this._doSubmit(this.options.form, options.files, submitButton, options.jsonResponse);
		} else {
			_this = this;
			var dialogButtons = {};
			dialogButtons[_('Cancel')] = function() {
				_this._cancelSubmit(_this.options.form);
				$(dialog).dialog('destroy');
				$(dialog).remove();
			};
			dialogButtons[_('Accept')] = function() {
				_this._doSubmit(_this.options.form, options.files, submitButton, options.jsonResponse);
				$(dialog).dialog('destroy');
				$(dialog).remove();
			};
			$(dialog).dialog({
				title: 'Ximdex Notifications',
				modal: true,
				buttons: dialogButtons
			});
		}

		return false;
	},

	_doSubmit: function(form, files, button, jsonResponse) {

		// Obtains the iframe
		var iframe = this._getIFrame(form);
		$form = $(form);
		// Form attributes
		$form.addClass('ready_to_send');

		if (!isNaN(files) && files > 0) {
			$form.attr('action', $form.attr('action') + '&files=' + files);
		}

		// jQuery Bug: $(elem).attr('target') returns a node with name=target o id=target, not the target attribute of $(elem)
		$form.attr('target', this.options.iframeId);
		$(iframe).load(this._reloadFrame.bind(this, iframe));

		if (Object.isObject(this.options.actionView)) {
			this.options.actionView.history.push($form.attr('action'));
		}

		if (jsonResponse && X.ActionTypes.reload.indexOf(this.options.actionView.action.command) == -1) {
			if ($(form).valid()) {
				button = button[0] || button;
				if (button) var loader = Ladda.create(button).start();//Start button loading animation
				var _this = this;
				$.ajax({
			        url: $form.attr('action'),
			        type: 'post',
			        dataType: 'json',
			        contentType: "application/x-www-form-urlencoded",
			        data: $form.serialize(),
			        success: function(data) {
			        	if(loader) loader.stop();//Stop loading animation
			        	if (data && data.messages) {
			        		_this.options.actionView.actionDoneCallback(data, form);
			        	}
			        },
			        error: function(error) {
			        	_this.options.actionView.actionNotify([_('Internal server error')], $form, true);
			        	loader.stop();
			        }
			    });
			}
		} else {
			button = button[0] || button;
			if (button) var loader = Ladda.create(button).start();//Start button loading animation
			form.submit();
		}
	},

	_cancelSubmit: function(form) {
		var iframe = this._getIFrame(form);
		$(iframe).unbind().remove();
	},

	_getIFrame: function(form) {

		var iframe = $('iframe#' + this.options.iframeId);

		if (iframe.length == 0) {

			iframe = $('')
				.attr({
					id: this.options.iframeId,
					src: 'about:blank',
					name: this.options.iframeId
				})
				.addClass('form_sender ui-helper-hidden');
			$(iframe).appendTo('body');
		}

		return iframe;
	},

	_getDialog: function(form, message) {

		var dialog = $(form).next('div.form_send_dialog');

		if (dialog.length == 0) {

			dialog = $('

').html(message);
			$(form).after(dialog);
		}

		return dialog;
	},

	_getConstraints: function(form) {
		var elements = {};

		$('.validable', form).each(function(id, validable) {

			var elementClass = $(validable).attr('class');
			var constraints = {};

			for (var i=0, l=this.options.searches.length; i<l; i++) {
				var search = this.options.searches[i];
				var result = elementClass.match(search);

				if (result !== null) {

					switch (result[1]) {
						case 'not_empty':
							constraints.required = true;
							break;

						case 'is_url':
							constraints.url = true;
							break;

						case 'is_email':
							constraints.email = true;
							break;

						case 'field_equals':
							constraints.equalTo = '#' + result[2];
							break;
						case 'js_val_min':
							constraints.minlength = result[2];
							break;
						case 'js_val_alphanumeric':
							constraints.alphanumeric = true;
							break;
						case 'js_val_unique_name':
							var idnode = $(validable).attr("data-idnode");
							constraints["remote"] = {
							    url: X.restUrl+"?action=browser3",
                                data: {
									inputName:$(validable).attr("name"),
									nodeid: idnode,
									method:"validation",
									validationMethod:"isUniqueName"
								},
                      			type: "post",
                      		};

							break;
						case 'js_val_unique_url':
							var idnode = $(validable).attr("data-idnode");
							constraints["remote"] = {
							    url: X.restUrl+"?action=browser3",
                                data: {
                                    nodeid: idnode,
									inputName:$(validable).attr("name"),
									method:"validation",
									validationMethod:"isUniqueUrl"
								},
                      			type: "post",
                      		};

							break;

						case 'check_group':
							var allclass = $(validable).attr('class');
							var regex = new RegExp('check_group__([^\\s]+)');
							var matchs = regex.exec(allclass);
							var group = matchs[0];
							constraints.checks = matchs[0];
							break;
					}
				}
			}

			var name = $(validable).attr('name');
			elements[name] = constraints;
		}.bind(this));
		return elements;
	},

	_getMessages: function(form) {
		var elements = {};

		$('.validable', form).each(function(id, validable) {

			var elementClass = $(validable).attr('class');
			var messages = {};

			for (var i=0, l=this.options.searches.length; i<l; i++) {
				var search = this.options.searches[i];
				var result = elementClass.match(search);

				if (result !== null) {

					switch (result[1]) {
						case 'js_val_unique_name':
							messages["remote"] = _("A node with this name already exists for current parent node.");
							break;
						case 'js_val_unique_url':
							messages["remote"] = _("A link with this url already exists.");
							break;
					}
				}
			}

			var name = $(validable).attr('name');
			elements[name] = messages;
		}.bind(this));

		return elements;
	},

	/**
	 * Loads the content of a panel after sending the form
	 * @return NULL
	 */
	_reloadFrame: function(event, iframe) {

		if( null != iframe.target ) {
		  var iframe = iframe.target;
		}

		var content = $(iframe).contents().find('body').html();
		var sessionInfo = content.match(/<xim:meta name="X-XIMDEX" content="([^"]*)"/);

		if (!Object.isEmpty(sessionInfo)) {
			if (X.checkSession(sessionInfo[1] || '')) {
				return;
			}
		}

		if (!this.options.actionContainer || !Object.isString(content) || content.length == 0) {
			return false;
		}

		$(this.options.actionContainer).html(content);

		// Remove the iframe from de DOM preventing the infinite page load
		$(iframe)
			.unbind()
			.attr('src', 'about:blank')
			.remove();

		$(this).trigger('form-loaded', []);
	}

});
<commit_msg>Actions can now be submitted with "enter" key<commit_after>/**
 *  \details © 2011  Open Ximdex Evolution SL [http://www.ximdex.org]
 *
 *  Ximdex a Semantic Content Management System (CMS)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published
 *  by the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  See the Affero GNU General Public License for more details.
 *  You should have received a copy of the Affero GNU General Public License
 *  version 3 along with Ximdex (see LICENSE file).
 *
 *  If not, visit http://gnu.org/licenses/agpl-3.0.html.
 *
 *  @author Ximdex DevTeam <dev@ximdex.com>
 *  @version $Revision$
 */

/**
 * Control the forms submission logic.
 */

X.FormsManager = Object.xo_create({

	buttons: null,

	_init: function(options) {

		this.options = Object.extend({
			actionView: null,
			iframeId: '',
			actionContainer: null,
			form: null,
			searches: [
				'(not_empty)', '(is_url)', '(is_email)', '(js_val_min)__([^\d]+)',
				'(field_equals)__([^\\s]+)', '(check_group)__([^\\s]+)', '(js_val_alphanumeric)',
				'(js_val_unique_name)', '(js_val_unique_url)'
			]
		}, options);

		// Don't want the jQuery object, want the DOMElement
		this.options.form = $(this.options.form).get(0);

		this.options.form.getFormMgr = function() {
			return this;
		}.bind(this);

		this._checkInputFields();
		this._registerButtons();
	},

	/**
	 * Checks and corrects inputs behaviours.
	 */
	_checkInputFields: function() {

		// var $fields = $('input[type=text]', this.options.form);

		// // // Don't send a form when enter key pressed
		// // $fields.keydown(function(event) {
		// // 	if (event.keyCode == 13) {
		// // 		return false;
		// // 	}
		// // });
	},

	/**
	 * Register click events on all form buttons with the class "validate"
	 */
	_registerButtons: function() {

		this.buttons = [];

		// Register buttons that will send the form
		$('.validate', this.options.form).each(function(index, button) {
			this.registerButton(button);
		}.bind(this));

		// Register buttons for reseting the form
		$('.reset-button', this.options.form).each(function(index, button) {
			button.click(function() {
				this.options.form.reset();
				return false;
			});
		}.bind(this));
	},

	/**
	 * Extends a button with methods for retrieve the form and the FormManager object.
	 * Creates a collection that stores "beforeSubmit" callbacks.
	 * If one callback return TRUE the form submission will be aborted.
	 *
	 * button: the DOMElement that will act as a submit button when clicked.
	 * confirm: When TRUE a confirmation message will be shown.
	 * message: The confirmation message. When NULL, the value attribute of the button will be used.
	 * file: ???
	 */
	registerButton: function(button, options) {

		button = $(button).get(0);

		options = $.extend({
			confirm: true,
			message: null,
			file: 0,
			jsonResponse: true
		}, options);

		button = $.extend(button, {
			getForm: function() {
				return this.options.form;
			}.bind(this),
			getFormMgr: function() {
				return this;
			}.bind(this),
			beforeSubmit: new X.Collection({unique: true})
		});

		$(button).click(trySubmit);
		$(this.options.form).keydown(function(event){
			if (event.target.nodeName !== 'TEXTAREA') {
				if (event.keyCode == 13) {
					return trySubmit(event);
					// return false;
				}
			}
		});
		this.buttons.push(button);

		function trySubmit(event) {
			if (!this.blockSubmit) {
				// Call the callbacks, if one of them returns TRUE the form will not be submitted
				var submit = true;
				var i = 0, l = button.beforeSubmit.size();
				while (submit && i<l) {
					var cb = button.beforeSubmit.get(i);
					if (Object.isFunction(cb)) {
						var abort = cb(event, button);
						submit = abort === true ? false : true;
					}
					i++;
				}

				if (!submit) return false;

				button.getFormMgr().sendForm($.extend({
					button: button
				}, options));

				return false;
			}
		}

		return button;
	},

	getButtons: function() {
		return this.buttons;
	},

	getActionContainer: function() {
		return this.options.actionContainer;
	},

	setActionContainer: function(container) {
		this.options.actionContainer = container;
		return this;
	},

	/**
	 * button: the DOMElement that will act as a submit button when clicked.
	 * confirm: When TRUE a confirmation message will be shown.
	 * message: The confirmation message. When NULL the value attribute of the button will be used.
	 * file: ???
	 */
	sendForm: function(options) {

		options = $.extend({
			button: null,
			confirm: true,
			message: null,
			file: 0,
			jsonResponse: false
		}, options);

		// Ensure the form and iframe IDs are unique
		var formId = $(this.options.form).attr('id');
		if (Object.isEmpty(formId)) {
			formId = 'form_' + X.getUID();
			$(this.options.form).attr('id', formId);
		}
		this.options.iframeId = 'form_sender_' + formId;

		// Validate the form
		if (!Object.isEmpty($(this.options.form).data('validator')) || $(this.options.form).data('validator') == null) {
			$(this.options.form).validate(
				{
					rules: this._getConstraints(this.options.form),
					messages: this._getMessages(this.options.form),
					errorElement: "span",
					errorPlacement: function(error, element) {

						$span = $("").addClass("error_block");
						if (element[0].tagName.toLowerCase()=="select" && element.parent().hasClass("input-select"))
							$span.addClass("select_block");
						element.wrap($span);
						element.before(error);
					}
				});
		}

		// Submit button
		var submitButton = options.button || $('.validate', this.options.form);
		var message = options.message || $('~ .submit_message', submitButton).attr('value');
		var dialog = this._getDialog(this.options.form, message);
		if (message == '' || message == undefined) {
			options.confirm = false;
		}

		// Send the form
		if (!options.confirm) {
			this._doSubmit(this.options.form, options.files, submitButton, options.jsonResponse);
		} else {
			_this = this;
			var dialogButtons = {};
			dialogButtons[_('Cancel')] = function() {
				_this._cancelSubmit(_this.options.form);
				$(dialog).dialog('destroy');
				$(dialog).remove();
			};
			dialogButtons[_('Accept')] = function() {
				_this._doSubmit(_this.options.form, options.files, submitButton, options.jsonResponse);
				$(dialog).dialog('destroy');
				$(dialog).remove();
			};
			$(dialog).dialog({
				title: 'Ximdex Notifications',
				modal: true,
				buttons: dialogButtons
			});
		}

		return false;
	},

	_doSubmit: function(form, files, button, jsonResponse) {

		// Obtains the iframe
		var iframe = this._getIFrame(form);
		$form = $(form);
		// Form attributes
		$form.addClass('ready_to_send');

		if (!isNaN(files) && files > 0) {
			$form.attr('action', $form.attr('action') + '&files=' + files);
		}

		// jQuery Bug: $(elem).attr('target') returns a node with name=target o id=target, not the target attribute of $(elem)
		$form.attr('target', this.options.iframeId);
		$(iframe).load(this._reloadFrame.bind(this, iframe));

		if (Object.isObject(this.options.actionView)) {
			this.options.actionView.history.push($form.attr('action'));
		}

		if (jsonResponse && X.ActionTypes.reload.indexOf(this.options.actionView.action.command) == -1) {
			if ($(form).valid()) {
				button = button[0] || button;
				if (button) var loader = Ladda.create(button).start();//Start button loading animation
				this.blockSubmit = true;
				var _this = this;
				$.ajax({
			        url: $form.attr('action'),
			        type: 'post',
			        dataType: 'json',
			        contentType: "application/x-www-form-urlencoded",
			        data: $form.serialize(),
			        success: function(data) {
			        	if(loader) loader.stop();//Stop loading animation
			        	if (data && data.messages) {
			        		_this.options.actionView.actionDoneCallback(data, form);
			        	}
			        	this.blockSubmit = false;
			        },
			        error: function(error) {
			        	_this.options.actionView.actionNotify([_('Internal server error')], $form, true);
			        	loader.stop();
			        	this.blockSubmit = false;
			        }
			    });
			}
		} else {
			button = button[0] || button;
			if (button) var loader = Ladda.create(button).start();//Start button loading animation
			form.submit();
		}
	},

	_cancelSubmit: function(form) {
		var iframe = this._getIFrame(form);
		$(iframe).unbind().remove();
	},

	_getIFrame: function(form) {

		var iframe = $('iframe#' + this.options.iframeId);

		if (iframe.length == 0) {

			iframe = $('')
				.attr({
					id: this.options.iframeId,
					src: 'about:blank',
					name: this.options.iframeId
				})
				.addClass('form_sender ui-helper-hidden');
			$(iframe).appendTo('body');
		}

		return iframe;
	},

	_getDialog: function(form, message) {

		var dialog = $(form).next('div.form_send_dialog');

		if (dialog.length == 0) {

			dialog = $('

').html(message);
			$(form).after(dialog);
		}

		return dialog;
	},

	_getConstraints: function(form) {
		var elements = {};

		$('.validable', form).each(function(id, validable) {

			var elementClass = $(validable).attr('class');
			var constraints = {};

			for (var i=0, l=this.options.searches.length; i<l; i++) {
				var search = this.options.searches[i];
				var result = elementClass.match(search);

				if (result !== null) {

					switch (result[1]) {
						case 'not_empty':
							constraints.required = true;
							break;

						case 'is_url':
							constraints.url = true;
							break;

						case 'is_email':
							constraints.email = true;
							break;

						case 'field_equals':
							constraints.equalTo = '#' + result[2];
							break;
						case 'js_val_min':
							constraints.minlength = result[2];
							break;
						case 'js_val_alphanumeric':
							constraints.alphanumeric = true;
							break;
						case 'js_val_unique_name':
							var idnode = $(validable).attr("data-idnode");
							constraints["remote"] = {
							    url: X.restUrl+"?action=browser3",
                                data: {
									inputName:$(validable).attr("name"),
									nodeid: idnode,
									method:"validation",
									validationMethod:"isUniqueName"
								},
                      			type: "post",
                      		};

							break;
						case 'js_val_unique_url':
							var idnode = $(validable).attr("data-idnode");
							constraints["remote"] = {
							    url: X.restUrl+"?action=browser3",
                                data: {
                                    nodeid: idnode,
									inputName:$(validable).attr("name"),
									method:"validation",
									validationMethod:"isUniqueUrl"
								},
                      			type: "post",
                      		};

							break;

						case 'check_group':
							var allclass = $(validable).attr('class');
							var regex = new RegExp('check_group__([^\\s]+)');
							var matchs = regex.exec(allclass);
							var group = matchs[0];
							constraints.checks = matchs[0];
							break;
					}
				}
			}

			var name = $(validable).attr('name');
			elements[name] = constraints;
		}.bind(this));
		return elements;
	},

	_getMessages: function(form) {
		var elements = {};

		$('.validable', form).each(function(id, validable) {

			var elementClass = $(validable).attr('class');
			var messages = {};

			for (var i=0, l=this.options.searches.length; i<l; i++) {
				var search = this.options.searches[i];
				var result = elementClass.match(search);

				if (result !== null) {

					switch (result[1]) {
						case 'js_val_unique_name':
							messages["remote"] = _("A node with this name already exists for current parent node.");
							break;
						case 'js_val_unique_url':
							messages["remote"] = _("A link with this url already exists.");
							break;
					}
				}
			}

			var name = $(validable).attr('name');
			elements[name] = messages;
		}.bind(this));

		return elements;
	},

	/**
	 * Loads the content of a panel after sending the form
	 * @return NULL
	 */
	_reloadFrame: function(event, iframe) {

		if( null != iframe.target ) {
		  var iframe = iframe.target;
		}

		var content = $(iframe).contents().find('body').html();
		var sessionInfo = content.match(/<xim:meta name="X-XIMDEX" content="([^"]*)"/);

		if (!Object.isEmpty(sessionInfo)) {
			if (X.checkSession(sessionInfo[1] || '')) {
				return;
			}
		}

		if (!this.options.actionContainer || !Object.isString(content) || content.length == 0) {
			return false;
		}

		$(this.options.actionContainer).html(content);

		// Remove the iframe from de DOM preventing the infinite page load
		$(iframe)
			.unbind()
			.attr('src', 'about:blank')
			.remove();

		$(this).trigger('form-loaded', []);
	}

});
<|endoftext|>


<commit_before>import macro from 'vtk.js/Sources/macro';
import vtkSVGRepresentation from 'vtk.js/Sources/Widgets/SVG/SVGRepresentation';

const { createSvgElement } = vtkSVGRepresentation;

// ----------------------------------------------------------------------------
// vtkSVGLandmarkRepresentation
// ----------------------------------------------------------------------------

function vtkSVGLandmarkRepresentation(publicAPI, model) {
  // Set our className
  model.classHierarchy.push('vtkSVGLandmarkRepresentation');

  publicAPI.render = () => {
    const list = publicAPI.getRepresentationStates();

    const coords = list.map((state) => state.getOrigin());
    const texts = list.map((state, index) =>
      state.getText ? state.getText() : `L${index}`
    );

    return publicAPI.worldPointsToPixelSpace(coords).then((pixelSpace) => {
      const points2d = pixelSpace.coords;
      const winHeight = pixelSpace.windowSize[1];

      const root = createSvgElement('g');
      for (let i = 0; i < points2d.length; i++) {
        const xy = points2d[i];
        if (Number.isNaN(xy[0]) || Number.isNaN(xy[1])) {
          continue; // eslint-disable-line
        }
        const x = xy[0];
        const y = winHeight - xy[1];

        let circle = {};
        if (model.showCircle === true) {
          circle = createSvgElement('circle');
          Object.keys(model.circleProps || {}).forEach((prop) =>
            circle.setAttribute(prop, model.circleProps[prop])
          );
          circle.setAttribute('cx', x);
          circle.setAttribute('cy', y);
          root.appendChild(circle);
        }
        if (!texts[i]) {
          texts[i] = '';
        }
        const splitText = texts[i].split('\n');
        const newlineOffset =
          model.fontProperties != null && model.fontProperties.fontSize
            ? model.fontProperties.fontSize
            : 15;
        splitText.forEach((subText, j) => {
          const text = createSvgElement('text');
          Object.keys(model.textProps || {}).forEach((prop) => {
            let propValue = model.textProps[prop];
            if (model.offsetText === true && prop === 'dy') {
              propValue = model.textProps.dy + newlineOffset * j;
            }
            text.setAttribute(prop, propValue);
          });
          text.setAttribute('x', x);
          text.setAttribute('y', y);
          if (model.fontProperties != null) {
            text.setAttribute('font-size', model.fontProperties.fontSize);
            text.setAttribute('font-family', model.fontProperties.fontFamily);
            text.setAttribute('font-weight', model.fontProperties.fontStyle);
            text.setAttribute('fill', model.fontProperties.fontColor);
          }
          text.textContent = subText;
          root.appendChild(text);
        });
      }

      return root;
    });
  };
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
  circleProps: {
    r: 5,
    stroke: 'red',
    fill: 'red',
  },
  textProps: {
    fill: 'white',
    dx: 12,
    dy: -12,
  },
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
  Object.assign(model, DEFAULT_VALUES, initialValues);

  vtkSVGRepresentation.extend(publicAPI, model, initialValues);

  macro.setGet(publicAPI, model, ['circleProps', 'textProps', 'name']);

  // Object specific methods
  vtkSVGLandmarkRepresentation(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(
  extend,
  'vtkSVGLandmarkRepresentation'
);

// ----------------------------------------------------------------------------

export default { extend, newInstance };
<commit_msg>fix(SVGLandmarkRepresentation): Do not share SVGLandmarkRepresentation<commit_after>import macro from 'vtk.js/Sources/macro';
import vtkSVGRepresentation from 'vtk.js/Sources/Widgets/SVG/SVGRepresentation';

const { createSvgElement } = vtkSVGRepresentation;

// ----------------------------------------------------------------------------
// vtkSVGLandmarkRepresentation
// ----------------------------------------------------------------------------

function vtkSVGLandmarkRepresentation(publicAPI, model) {
  // Set our className
  model.classHierarchy.push('vtkSVGLandmarkRepresentation');

  publicAPI.render = () => {
    const list = publicAPI.getRepresentationStates();

    const coords = list.map((state) => state.getOrigin());
    const texts = list.map((state, index) =>
      state.getText ? state.getText() : `L${index}`
    );

    return publicAPI.worldPointsToPixelSpace(coords).then((pixelSpace) => {
      const points2d = pixelSpace.coords;
      const winHeight = pixelSpace.windowSize[1];

      const root = createSvgElement('g');
      for (let i = 0; i < points2d.length; i++) {
        const xy = points2d[i];
        if (Number.isNaN(xy[0]) || Number.isNaN(xy[1])) {
          continue; // eslint-disable-line
        }
        const x = xy[0];
        const y = winHeight - xy[1];

        let circle = {};
        if (model.showCircle === true) {
          circle = createSvgElement('circle');
          Object.keys(model.circleProps || {}).forEach((prop) =>
            circle.setAttribute(prop, model.circleProps[prop])
          );
          circle.setAttribute('cx', x);
          circle.setAttribute('cy', y);
          root.appendChild(circle);
        }
        if (!texts[i]) {
          texts[i] = '';
        }
        const splitText = texts[i].split('\n');
        const newlineOffset =
          model.fontProperties != null && model.fontProperties.fontSize
            ? model.fontProperties.fontSize
            : 15;
        splitText.forEach((subText, j) => {
          const text = createSvgElement('text');
          Object.keys(model.textProps || {}).forEach((prop) => {
            let propValue = model.textProps[prop];
            if (model.offsetText === true && prop === 'dy') {
              propValue = model.textProps.dy + newlineOffset * j;
            }
            text.setAttribute(prop, propValue);
          });
          text.setAttribute('x', x);
          text.setAttribute('y', y);
          if (model.fontProperties != null) {
            text.setAttribute('font-size', model.fontProperties.fontSize);
            text.setAttribute('font-family', model.fontProperties.fontFamily);
            text.setAttribute('font-weight', model.fontProperties.fontStyle);
            text.setAttribute('fill', model.fontProperties.fontColor);
          }
          text.textContent = subText;
          root.appendChild(text);
        });
      }

      return root;
    });
  };
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

function defaultValues(initialValues) {
  return {
    circleProps: {
      r: 5,
      stroke: 'red',
      fill: 'red',
    },
    textProps: {
      fill: 'white',
      dx: 12,
      dy: -12,
    },
    ...initialValues,
  };
}

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
  Object.assign(model, defaultValues(initialValues));

  vtkSVGRepresentation.extend(publicAPI, model, initialValues);

  macro.setGet(publicAPI, model, ['circleProps', 'textProps', 'name']);

  // Object specific methods
  vtkSVGLandmarkRepresentation(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(
  extend,
  'vtkSVGLandmarkRepresentation'
);

// ----------------------------------------------------------------------------

export default { extend, newInstance };
<|endoftext|>


<commit_before>/* Load Lively */

var loadCallbacks = []
export function whenLoaded(cb) {
    loadCallbacks.push(cb)
}

if ('serviceWorker' in navigator) {
    console.log("LOAD Lively4: boot lively4 service worker")
    // var root = ("" + window.location).replace(/[^\/]*$/,'../')
    var root = "" + lively4url + "/";
    var serviceworkerReady = false

    var onReady = function() {
        serviceworkerReady = true;
        // Lively has all the dependencies
        if (window.location.host == " livelykernel.github.io") {
          // #Experiment #Jens
          lively4url = "https://lively4/"
        }
        System.import(lively4url + "/src/client/lively.js").then(function(module) {
            lively.initializeHalos();
            lively.components.loadUnresolved();
            console.log("running on load callbacks:");
            loadCallbacks.forEach(function(cb){
                try {
                   cb()
                } catch(e) {
                    console.log("Error running on load callback: "  + cb + " error: " + e)
                }
            });

            if (!window.__karma__) {
              window.onbeforeunload = function(e) {
                return 'Do you really want to leave this page?';
              };
            }
            console.log("lively loaded");
        })
    }

    if (navigator.serviceWorker.controller) {
      console.log("Use existing service worker")
      // we don't have to do anything here... the service worker is already there
      onReady()
    } else {

      navigator.serviceWorker.register(root + 'swx-loader.js', {
          // navigator.serviceWorker.register('../../serviceworker-loader.js', {
          // scope: root + "draft/"
          scope: root
      }).then(function(registration) {
          // Registration was successful
          console.log('ServiceWorker registration successful with scope: ', registration.scope);

          // so now we have to reload!

          console.log("ok... lets WAIT WAIT WAIT!!!!")
          // console.log("Lively4 ServiceWorker installed! Reboot needed! ;-)")
          // window.location = window.location

      }).catch(function(err) {
          // registration failed
          console.log('ServiceWorker registration failed: ', err);
      });
      navigator.serviceWorker.ready.then(onReady)
    }

    var fs = new Promise(function(resolve, reject) {
        navigator.webkitPersistentStorage.requestQuota(1024 * 1024 * 10, function(grantedQuota) {
            self.webkitRequestFileSystem(PERSISTENT, grantedQuota, resolve, reject)
        }, reject)
    })

    navigator.serviceWorker.addEventListener("message", (event) => {
        var reject = function(err) {
            event.ports[0].postMessage({error: err})
        }

        switch(event.data.name) {
            case 'swx:readFile':
                fs.then((fs) => {
                    fs.root.getFile(event.data.file, undefined, function(fileEntry) {
                        fileEntry.file(function(file) {
                            var reader = new FileReader()

                            reader.onloadend = function(e) {
                                console.log('[LFS] read complete', e)
                                event.ports[0].postMessage({content: reader.result})
                            }

                            reader.readAsText(file)
                        })
                    }, reject)
                }).catch(reject)

                break
            case 'swx:writeFile':
                fs.then((fs) => {
                    fs.root.getFile(event.data.file, {create: true, exclusive: false}, function(file) {
                        file.createWriter(function (writer) {
                            writer.onwriteend = function(e) {
                                console.log("[LFS] write complete", e)

                                event.ports[0].postMessage({
                                    content: event.data.content
                                })
                            }

                            writer.onerror = reject
                            writer.write(new Blob([event.data.content], {type: 'text/plain'}))
                        }, reject)
                    }, reject)
                }).catch(reject)

                break
        }
    })
}

document.addEventListener('DOMContentLoaded', function () {
    if (Notification.permission !== "granted")
        Notification.requestPermission();
});

<commit_msg>Update file src/client/load.js with webclient file backend<commit_after>/* Load Lively */

var loadCallbacks = []
export function whenLoaded(cb) {
    loadCallbacks.push(cb)
}

if ('serviceWorker' in navigator) {
    console.log("LOAD Lively4: boot lively4 service worker")
    // var root = ("" + window.location).replace(/[^\/]*$/,'../')
    var root = "" + lively4url + "/";
    var serviceworkerReady = false

    var onReady = function() {
        serviceworkerReady = true;
        // Lively has all the dependencies
        if (window.location.host == "livelykernel.github.io") {
          // #Experiment #Jens
          window.lively4url = "https://lively4/"
        }
        System.import(lively4url + "/src/client/lively.js").then(function(module) {
            lively.initializeHalos();
            lively.components.loadUnresolved();
            console.log("running on load callbacks:");
            loadCallbacks.forEach(function(cb){
                try {
                   cb()
                } catch(e) {
                    console.log("Error running on load callback: "  + cb + " error: " + e)
                }
            });

            if (!window.__karma__) {
              window.onbeforeunload = function(e) {
                return 'Do you really want to leave this page?';
              };
            }
            console.log("lively loaded");
        })
    }

    if (navigator.serviceWorker.controller) {
      console.log("Use existing service worker")
      // we don't have to do anything here... the service worker is already there
      onReady()
    } else {

      navigator.serviceWorker.register(root + 'swx-loader.js', {
          // navigator.serviceWorker.register('../../serviceworker-loader.js', {
          // scope: root + "draft/"
          scope: root
      }).then(function(registration) {
          // Registration was successful
          console.log('ServiceWorker registration successful with scope: ', registration.scope);

          // so now we have to reload!

          console.log("ok... lets WAIT WAIT WAIT!!!!")
          // console.log("Lively4 ServiceWorker installed! Reboot needed! ;-)")
          // window.location = window.location

      }).catch(function(err) {
          // registration failed
          console.log('ServiceWorker registration failed: ', err);
      });
      navigator.serviceWorker.ready.then(onReady)
    }

    var fs = new Promise(function(resolve, reject) {
        navigator.webkitPersistentStorage.requestQuota(1024 * 1024 * 10, function(grantedQuota) {
            self.webkitRequestFileSystem(PERSISTENT, grantedQuota, resolve, reject)
        }, reject)
    })

    navigator.serviceWorker.addEventListener("message", (event) => {
        var reject = function(err) {
            event.ports[0].postMessage({error: err})
        }

        switch(event.data.name) {
            case 'swx:readFile':
                fs.then((fs) => {
                    fs.root.getFile(event.data.file, undefined, function(fileEntry) {
                        fileEntry.file(function(file) {
                            var reader = new FileReader()

                            reader.onloadend = function(e) {
                                console.log('[LFS] read complete', e)
                                event.ports[0].postMessage({content: reader.result})
                            }

                            reader.readAsText(file)
                        })
                    }, reject)
                }).catch(reject)

                break
            case 'swx:writeFile':
                fs.then((fs) => {
                    fs.root.getFile(event.data.file, {create: true, exclusive: false}, function(file) {
                        file.createWriter(function (writer) {
                            writer.onwriteend = function(e) {
                                console.log("[LFS] write complete", e)

                                event.ports[0].postMessage({
                                    content: event.data.content
                                })
                            }

                            writer.onerror = reject
                            writer.write(new Blob([event.data.content], {type: 'text/plain'}))
                        }, reject)
                    }, reject)
                }).catch(reject)

                break
        }
    })
}

document.addEventListener('DOMContentLoaded', function () {
    if (Notification.permission !== "granted")
        Notification.requestPermission();
});

<|endoftext|>


<commit_before>const querystring = require('querystring')

export default class JesqueAdminClient {

  get(target, id, query) {
    let path = this.buildPath(target, id, query);
    return fetch(path, {
      method: 'GET',
      credentials: "same-origin",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      cache: false
    }).then((res)=> {
      return res.json()
    })
  }

  delete(target, id, query) {
    let path = this.buildPath(target, id, query)
    return fetch(path, {
      method: 'DELETE',
      credentials: "same-origin",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      cache: false
    }).then((res)=> {
      return res.json()
    })
  }

  post(target, id, data) {
    let path = this.buildPath(target, id, {});
    return fetch(path, {
      method: 'POST',
      credentials: "same-origin",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      cache: false,
      body: JSON.stringify(data)
    }).then((res)=> {
      return res.json()
    })
  }

  buildPath(target, id, query) {
    let path = window.AppConfig.links[target];
    if (id) {
      path = `${path}/${id}`
    }
    if(query) {
      path = `${path}?${querystring.stringify(query)}`
    }
    return path
  }

}
<commit_msg>fix buildPath to accept 0 as id<commit_after>const querystring = require('querystring')

export default class JesqueAdminClient {

  get(target, id, query) {
    let path = this.buildPath(target, id, query);
    return fetch(path, {
      method: 'GET',
      credentials: "same-origin",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      cache: false
    }).then((res)=> {
      return res.json()
    })
  }

  delete(target, id, query) {
    let path = this.buildPath(target, id, query);
    return fetch(path, {
      method: 'DELETE',
      credentials: "same-origin",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      cache: false
    }).then((res)=> {
      return res.json()
    })
  }

  post(target, id, data) {
    let path = this.buildPath(target, id, {});
    return fetch(path, {
      method: 'POST',
      credentials: "same-origin",
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      cache: false,
      body: JSON.stringify(data)
    }).then((res)=> {
      return res.json()
    })
  }

  buildPath(target, id, query) {
    let path = window.AppConfig.links[target];
    if (id !== undefined && id !== null) {
      path = `${path}/${id}`
    }
    if (query) {
      path = `${path}?${querystring.stringify(query)}`
    }
    return path
  }

}
<|endoftext|>


<commit_before>'use strict';
var QEmitter = require('qemitter'),
    debug = require('debug'),
    util = require('util'),

    _ = require('lodash'),
    chalk = require('chalk'),
    ScreenShooter = require('./screen-shooter'),
    Tester = require('./tester'),
    Config = require('./config'),
    readTests = require('./test-reader'),
    suiteUtils = require('./suite-util'),

    RunnnerStats = require('./stats'),
    RunnerEvents = require('./constants/runner-events'),

    GeminiError = require('./errors/gemini-error'),
    Image = require('./image'),

    DEFAULT_CFG_NAME = '.gemini.yml';

function Gemini(config, allowOverrides) {
    QEmitter.call(this);
    config = config || DEFAULT_CFG_NAME;
    this.config = new Config(config, allowOverrides);
    if (this.config.system.debug) {
        debug.enable('gemini:*');
    }

    var _this = this;

    require('./plugins').load(_this, this.config);

    function executeRunner(runnerInstance, paths, options) {
        if (!options) {
            //if there are only two arguments, they are
            //(runnerInstance, options) and paths are
            //the default.
            options = paths;
            paths = undefined;
        }
        options = options || {};
        options.reporters = options.reporters || [];

        var envBrowsers = process.env.GEMINI_BROWSERS? process.env.GEMINI_BROWSERS.replace(/\s/g, '').split(',') : null;
        options.browsers = options.browsers || envBrowsers;

        if (options.browsers) {
            areAllBrowsersFromConfig(options.browsers, _this.browserIds);
            runnerInstance.setTestBrowsers(options.browsers);
        }

        function notifyEndRunner(data) {
            return _this.emitAndWait(RunnerEvents.END_RUNNER, runnerInstance, data).thenResolve(data);
        }

        return _this.readTests(paths)
            .then(function(rootSuite) {
                return _this.emitAndWait(RunnerEvents.START_RUNNER, runnerInstance)
                    .thenResolve(rootSuite);
            })
            .then(function(rootSuite) {
                var suites = suiteUtils.flattenSuites(rootSuite);

                if (options.grep) {
                    suites = suites.filter(function(suite) {
                        return options.grep.test(suite.fullName);
                    });
                }

                options.reporters.forEach(_.partial(applyReporter, runnerInstance));

                var stats = new RunnnerStats(runnerInstance);

                return runnerInstance.run(suites)
                    .thenResolve(stats.get());
            })
            .then(notifyEndRunner, function(e) {
                return notifyEndRunner().thenReject(e);
            });
    }

    function areAllBrowsersFromConfig(browsers, browsersFromConfig) {
        browsers.forEach(function(name) {
            if (browsersFromConfig.indexOf(name) === -1) {
                throw new GeminiError('Unknown browser id: ' + name,
                    'Use one of the browser ids specified in config file: ' +
                    browsersFromConfig.join(', '));
            }
        });
    }

    this.readTests = function(paths) {
        return readTests(paths, this.config);
    };

    this.gather = function(paths, options) {
        return executeRunner(
            new ScreenShooter(this.config),
            paths,
            options);
    };

    this.test = function(paths, options) {
        return executeRunner(
            new Tester(this.config, {tempDir: options.tempDir}),
            paths,
            options
        );
    };

    this.getScreenshotPath = function(suite, stateName, browserId) {
        return this.config.forBrowser(browserId).getScreenshotPath(suite, stateName);
    };

    this.buildDiff = util.deprecate(function(referencePath, currentPath, diffPath) {
            return Image.buildDiff({
                reference: referencePath,
                current: currentPath,
                diff: diffPath,
                diffColor: this.config.diffColor,
                strictComparison: this.config.strictComparison,
                tolerance: this.config.tolerance
            });
        }, 'gemini.buildDiff' + chalk.red(' is deprecated.\n') +
        'Use ' + chalk.green('testResult.saveDiffTo(path)') +
        ' in ' + chalk.green('endTest') + ' event handler for more accurate diff'
    );

    this.getBrowserCapabilites = function(browserId) {
        return this.config.forBrowser(browserId).desiredCapabilities;
    };

    Object.defineProperty(this, 'browserIds', {
        enumerable: true,
        get: function() {
            return this.config.getBrowserIds();
        }
    });
}

// Gemini needs to inherit from QEmitter rather then
// EventEmmiter because it needs to allow `startRunner`
// event handler delay the execution of tests
util.inherits(Gemini, QEmitter);

function applyReporter(runner, reporter) {
    if (typeof reporter === 'string') {
        try {
            reporter = require('./reporters/' + reporter);
        } catch (e) {
            if (e.code === 'MODULE_NOT_FOUND') {
                throw new GeminiError('No such reporter: ' + reporter);
            }
            throw e;
        }
    }
    if (typeof reporter !== 'function') {
        throw new TypeError('Reporter must be a string or a function');
    }

    reporter(runner);
}

module.exports = Gemini;
<commit_msg>Do not fail tests if browser specified from env does not exist in config<commit_after>'use strict';
var QEmitter = require('qemitter'),
    debug = require('debug'),
    util = require('util'),

    _ = require('lodash'),
    chalk = require('chalk'),
    ScreenShooter = require('./screen-shooter'),
    Tester = require('./tester'),
    Config = require('./config'),
    readTests = require('./test-reader'),
    suiteUtils = require('./suite-util'),

    RunnnerStats = require('./stats'),
    RunnerEvents = require('./constants/runner-events'),

    GeminiError = require('./errors/gemini-error'),
    Image = require('./image'),

    DEFAULT_CFG_NAME = '.gemini.yml';

function Gemini(config, allowOverrides) {
    QEmitter.call(this);
    config = config || DEFAULT_CFG_NAME;
    this.config = new Config(config, allowOverrides);
    if (this.config.system.debug) {
        debug.enable('gemini:*');
    }

    var _this = this;

    require('./plugins').load(_this, this.config);

    function executeRunner(runnerInstance, paths, options) {
        if (!options) {
            //if there are only two arguments, they are
            //(runnerInstance, options) and paths are
            //the default.
            options = paths;
            paths = undefined;
        }
        options = options || {};
        options.reporters = options.reporters || [];

        var envBrowsers = process.env.GEMINI_BROWSERS? process.env.GEMINI_BROWSERS.replace(/\s/g, '').split(',') : null;
        options.browsers = options.browsers || envBrowsers;

        if (options.browsers) {
            var browsersFromConfig = _this.browserIds,
                validBrowsers = _.intersection(options.browsers, browsersFromConfig),
                unknownBrowsers = _.difference(options.browsers, browsersFromConfig);

            if (unknownBrowsers.length) {
                console.warn(util.format(
                    '%s Unknown browsers id: %s. Use one of the browser ids specified in config file: %s',
                    chalk.yellow('WARNING:'), unknownBrowsers.join(', '), browsersFromConfig.join(', ')
                ));
            }

            runnerInstance.setTestBrowsers(validBrowsers);
        }

        function notifyEndRunner(data) {
            return _this.emitAndWait(RunnerEvents.END_RUNNER, runnerInstance, data).thenResolve(data);
        }

        return _this.readTests(paths)
            .then(function(rootSuite) {
                return _this.emitAndWait(RunnerEvents.START_RUNNER, runnerInstance)
                    .thenResolve(rootSuite);
            })
            .then(function(rootSuite) {
                var suites = suiteUtils.flattenSuites(rootSuite);

                if (options.grep) {
                    suites = suites.filter(function(suite) {
                        return options.grep.test(suite.fullName);
                    });
                }

                options.reporters.forEach(_.partial(applyReporter, runnerInstance));

                var stats = new RunnnerStats(runnerInstance);

                return runnerInstance.run(suites)
                    .thenResolve(stats.get());
            })
            .then(notifyEndRunner, function(e) {
                return notifyEndRunner().thenReject(e);
            });
    }

    this.readTests = function(paths) {
        return readTests(paths, this.config);
    };

    this.gather = function(paths, options) {
        return executeRunner(
            new ScreenShooter(this.config),
            paths,
            options);
    };

    this.test = function(paths, options) {
        return executeRunner(
            new Tester(this.config, {tempDir: options.tempDir}),
            paths,
            options
        );
    };

    this.getScreenshotPath = function(suite, stateName, browserId) {
        return this.config.forBrowser(browserId).getScreenshotPath(suite, stateName);
    };

    this.buildDiff = util.deprecate(function(referencePath, currentPath, diffPath) {
            return Image.buildDiff({
                reference: referencePath,
                current: currentPath,
                diff: diffPath,
                diffColor: this.config.diffColor,
                strictComparison: this.config.strictComparison,
                tolerance: this.config.tolerance
            });
        }, 'gemini.buildDiff' + chalk.red(' is deprecated.\n') +
        'Use ' + chalk.green('testResult.saveDiffTo(path)') +
        ' in ' + chalk.green('endTest') + ' event handler for more accurate diff'
    );

    this.getBrowserCapabilites = function(browserId) {
        return this.config.forBrowser(browserId).desiredCapabilities;
    };

    Object.defineProperty(this, 'browserIds', {
        enumerable: true,
        get: function() {
            return this.config.getBrowserIds();
        }
    });
}

// Gemini needs to inherit from QEmitter rather then
// EventEmmiter because it needs to allow `startRunner`
// event handler delay the execution of tests
util.inherits(Gemini, QEmitter);

function applyReporter(runner, reporter) {
    if (typeof reporter === 'string') {
        try {
            reporter = require('./reporters/' + reporter);
        } catch (e) {
            if (e.code === 'MODULE_NOT_FOUND') {
                throw new GeminiError('No such reporter: ' + reporter);
            }
            throw e;
        }
    }
    if (typeof reporter !== 'function') {
        throw new TypeError('Reporter must be a string or a function');
    }

    reporter(runner);
}

module.exports = Gemini;
<|endoftext|>


<commit_before>/* eslint-disable no-magic-numbers */
module.exports = {
    'accessor-pairs': 'error',
    'array-bracket-spacing': [
        'error',
        'never'
    ],
    'array-callback-return': 'error',
    'arrow-body-style': [
        'error',
        'always'
    ],
    'arrow-parens': 'error',
    'arrow-spacing': 'error',
    'block-scoped-var': 'error',
    'block-spacing': 'error',
    'brace-style': 'error',
    'callback-return': 'error',
    'camelcase': 'error',
    'class-methods-use-this': 'error',
    'comma-dangle': 'error',
    'comma-spacing': 'error',
    'comma-style': 'error',
    'complexity': [
        'error',
        4
    ],
    'computed-property-spacing': 'error',
    'consistent-return': 'error',
    'consistent-this': [
        'error',
        'self'
    ],
    'constructor-super': 'error',
    'curly': 'error',
    'default-case': 'error',
    'eol-last': 'error',
    'eqeqeq': [
        'error',
        'always'
    ],
    'func-call-spacing': 'error',
    'generator-star-spacing': 'error',
    'global-require': 'error',
    'guard-for-in': 'error',
    'handle-callback-err': 'error',
    'indent': [
        'error',
        4,
        {
            SwitchCase: 1
        }
    ],
    'jsx-quotes': 'error',
    'key-spacing': 'error',
    'keyword-spacing': 'error',
    'linebreak-style': 'error',
    'lines-around-directive': [
        'error',
        {
            after: 'always',
            before: 'never'
        }
    ],
    'max-depth': [
        'error',
        2
    ],
    'max-nested-callbacks': [
        'error',
        {
            max: 3
        }
    ],
    'max-params': [
        'error',
        {
            max: 3
        }
    ],
    'max-statements-per-line': 'error',
    'new-cap': 'error',
    'new-parens': 'error',
    'newline-after-var': 'error',
    'newline-before-return': 'error',
    'no-alert': 'error',
    'no-array-constructor': 'error',
    'no-bitwise': 'error',
    'no-caller': 'error',
    'no-catch-shadow': 'error',
    'no-class-assign': 'error',
    'no-cond-assign': [
        'error',
        'always'
    ],
    'no-confusing-arrow': 'error',
    'no-console': 'error',
    'no-const-assign': 'error',
    'no-constant-condition': [
        'error',
        {
            checkLoops: false
        }
    ],
    'no-continue': 'error',
    'no-control-regex': 'error',
    'no-debugger': 'error',
    'no-delete-var': 'error',
    'no-div-regex': 'error',
    'no-dupe-args': 'error',
    'no-dupe-class-members': 'error',
    'no-dupe-keys': 'error',
    'no-duplicate-case': 'error',
    'no-duplicate-imports': [
        'error',
        {
            includeExports: true
        }
    ],
    'no-else-return': 'error',
    'no-empty-character-class': 'error',
    'no-empty-function': 'error',
    'no-empty-pattern': 'error',
    'no-eq-null': 'error',
    'no-eval': 'error',
    'no-ex-assign': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-extra-boolean-cast': 'error',
    'no-extra-label': 'error',
    'no-extra-parens': [
        'error',
        'all'
    ],
    'no-extra-semi': 'error',
    'no-fallthrough': 'error',
    'no-floating-decimal': 'error',
    'no-global-assign': 'error',
    'no-implicit-coercion': 'error',
    'no-implicit-globals': 'error',
    'no-implied-eval': 'error',
    'no-inner-declarations': [
        'error',
        'both'
    ],
    'no-invalid-regexp': [
        'error',
        {
            allowConstructorFlags: [
                'u',
                'y'
            ]
        }
    ],
    'no-invalid-this': 'error',
    'no-irregular-whitespace': 'error',
    'no-iterator': 'error',
    'no-label-var': 'error',
    'no-labels': 'error',
    'no-lone-blocks': 'error',
    'no-lonely-if': 'error',
    'no-loop-func': 'error',
    'no-magic-numbers': [
        'error',
        {
            enforceConst: true,
            ignore: [1],
            ignoreArrayIndexes: true
        }
    ],
    'no-mixed-spaces-and-tabs': 'error',
    'no-multi-spaces': 'error',
    'no-multi-str': 'error',
    'no-multiple-empty-lines': [
        'error',
        {
            max: 1
        }
    ],
    'no-nested-ternary': 'error',
    'no-new': 'error',
    'no-new-func': 'error',
    'no-new-object': 'error',
    'no-new-require': 'error',
    'no-new-symbol': 'error',
    'no-new-wrappers': 'error',
    'no-obj-calls': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-param-reassign': [
        'error',
        {
            props: true
        }
    ],
    'no-path-concat': 'error',
    'no-process-exit': 'error',
    'no-proto': 'error',
    'no-redeclare': [
        'error',
        {
            builtinGlobals: true
        }
    ],
    'no-restricted-globals': 'error',
    'no-return-assign': [
        'error',
        'always'
    ],
    'no-script-url': 'error',
    'no-self-assign': [
        'error',
        {
            props: true
        }
    ],
    'no-self-compare': 'error',
    'no-sequences': 'error',
    'no-shadow': 'error',
    'no-shadow-restricted-names': 'error',
    'no-sparse-arrays': 'error',
    'no-sync': 'error',
    'no-tabs': 'error',
    'no-template-curly-in-string': 'error',
    'no-this-before-super': 'error',
    'no-throw-literal': 'error',
    'no-trailing-spaces': 'error',
    'no-undef': 'error',
    'no-undef-init': 'error',
    'no-unexpected-multiline': 'error',
    'no-unmodified-loop-condition': 'error',
    'no-unneeded-ternary': 'error',
    'no-unreachable': 'error',
    'no-unsafe-finally': 'error',
    'no-unsafe-negation': 'error',
    'no-unused-expressions': 'error',
    'no-unused-labels': 'error',
    'no-unused-vars': 'error',
    'no-use-before-define': 'error',
    'no-useless-call': 'error',
    'no-useless-computed-key': 'error',
    'no-useless-concat': 'error',
    'no-useless-constructor': 'error',
    'no-useless-escape': 'error',
    'no-useless-rename': 'error',
    'no-var': 'error',
    'no-void': 'error',
    'no-warning-comments': 'error',
    'no-whitespace-before-property': 'error',
    'no-with': 'error',
    'object-curly-spacing': 'error',
    'object-shorthand': 'error',
    'one-var': [
        'error',
        {
            const: 'never',
            let: 'always',
            var: 'always'
        }
    ],
    'one-var-declaration-per-line': [
        'error',
        'always'
    ],
    'padded-blocks': [
        'error',
        'never'
    ],
    'prefer-const': 'error',
    'prefer-numeric-literals': 'error',
    'prefer-reflect': 'error',
    'prefer-rest-params': 'error',
    'prefer-spread': 'error',
    'prefer-template': 'error',
    'quote-props': [
        'error',
        'as-needed',
        {
            numbers: true,
            unnecessary: false
        }
    ],
    'quotes': [
        'error',
        'single',
        {
            avoidEscape: true
        }
    ],
    'radix': [
        'error',
        'as-needed'
    ],
    'require-yield': 'error',
    'rest-spread-spacing': 'error',
    'semi': 'error',
    'semi-spacing': [
        'error',
        {
            after: true,
            before: false
        }
    ],
    'sort-keys': [
        'error',
        'asc',
        {
            caseSensitive: false,
            natural: true
        }
    ],
    'space-before-blocks': 'error',
    'space-before-function-paren': [
        'error',
        {
            anonymous: 'always',
            named: 'never'
        }
    ],
    'space-in-parens': 'error',
    'space-infix-ops': 'error',
    'space-unary-ops': [
        'error',
        {
            nonwords: false,
            words: true
        }
    ],
    'spaced-comment': 'error',
    'strict': [
        'error',
        'never'
    ],
    'symbol-description': 'error',
    'template-curly-spacing': 'error',
    'unicode-bom': 'error',
    'use-isnan': 'error',
    'valid-typeof': 'error',
    'vars-on-top': 'error',
    'wrap-iife': [
        'error',
        'any'
    ],
    'yield-star-spacing': [
        'error',
        'before'
    ],
    'yoda': [
        'error',
        'never'
    ]
};
/* eslint-enable no-magic-numbers */
<commit_msg>Changes `arrow-body-style` rule to still error, but only `as-needed`.<commit_after>/* eslint-disable no-magic-numbers */
module.exports = {
    'accessor-pairs': 'error',
    'array-bracket-spacing': [
        'error',
        'never'
    ],
    'array-callback-return': 'error',
    'arrow-body-style': 'error',
    'arrow-parens': 'error',
    'arrow-spacing': 'error',
    'block-scoped-var': 'error',
    'block-spacing': 'error',
    'brace-style': 'error',
    'callback-return': 'error',
    'camelcase': 'error',
    'class-methods-use-this': 'error',
    'comma-dangle': 'error',
    'comma-spacing': 'error',
    'comma-style': 'error',
    'complexity': [
        'error',
        4
    ],
    'computed-property-spacing': 'error',
    'consistent-return': 'error',
    'consistent-this': [
        'error',
        'self'
    ],
    'constructor-super': 'error',
    'curly': 'error',
    'default-case': 'error',
    'eol-last': 'error',
    'eqeqeq': [
        'error',
        'always'
    ],
    'func-call-spacing': 'error',
    'generator-star-spacing': 'error',
    'global-require': 'error',
    'guard-for-in': 'error',
    'handle-callback-err': 'error',
    'indent': [
        'error',
        4,
        {
            SwitchCase: 1
        }
    ],
    'jsx-quotes': 'error',
    'key-spacing': 'error',
    'keyword-spacing': 'error',
    'linebreak-style': 'error',
    'lines-around-directive': [
        'error',
        {
            after: 'always',
            before: 'never'
        }
    ],
    'max-depth': [
        'error',
        2
    ],
    'max-nested-callbacks': [
        'error',
        {
            max: 3
        }
    ],
    'max-params': [
        'error',
        {
            max: 3
        }
    ],
    'max-statements-per-line': 'error',
    'new-cap': 'error',
    'new-parens': 'error',
    'newline-after-var': 'error',
    'newline-before-return': 'error',
    'no-alert': 'error',
    'no-array-constructor': 'error',
    'no-bitwise': 'error',
    'no-caller': 'error',
    'no-catch-shadow': 'error',
    'no-class-assign': 'error',
    'no-cond-assign': [
        'error',
        'always'
    ],
    'no-confusing-arrow': 'error',
    'no-console': 'error',
    'no-const-assign': 'error',
    'no-constant-condition': [
        'error',
        {
            checkLoops: false
        }
    ],
    'no-continue': 'error',
    'no-control-regex': 'error',
    'no-debugger': 'error',
    'no-delete-var': 'error',
    'no-div-regex': 'error',
    'no-dupe-args': 'error',
    'no-dupe-class-members': 'error',
    'no-dupe-keys': 'error',
    'no-duplicate-case': 'error',
    'no-duplicate-imports': [
        'error',
        {
            includeExports: true
        }
    ],
    'no-else-return': 'error',
    'no-empty-character-class': 'error',
    'no-empty-function': 'error',
    'no-empty-pattern': 'error',
    'no-eq-null': 'error',
    'no-eval': 'error',
    'no-ex-assign': 'error',
    'no-extend-native': 'error',
    'no-extra-bind': 'error',
    'no-extra-boolean-cast': 'error',
    'no-extra-label': 'error',
    'no-extra-parens': [
        'error',
        'all'
    ],
    'no-extra-semi': 'error',
    'no-fallthrough': 'error',
    'no-floating-decimal': 'error',
    'no-global-assign': 'error',
    'no-implicit-coercion': 'error',
    'no-implicit-globals': 'error',
    'no-implied-eval': 'error',
    'no-inner-declarations': [
        'error',
        'both'
    ],
    'no-invalid-regexp': [
        'error',
        {
            allowConstructorFlags: [
                'u',
                'y'
            ]
        }
    ],
    'no-invalid-this': 'error',
    'no-irregular-whitespace': 'error',
    'no-iterator': 'error',
    'no-label-var': 'error',
    'no-labels': 'error',
    'no-lone-blocks': 'error',
    'no-lonely-if': 'error',
    'no-loop-func': 'error',
    'no-magic-numbers': [
        'error',
        {
            enforceConst: true,
            ignore: [1],
            ignoreArrayIndexes: true
        }
    ],
    'no-mixed-spaces-and-tabs': 'error',
    'no-multi-spaces': 'error',
    'no-multi-str': 'error',
    'no-multiple-empty-lines': [
        'error',
        {
            max: 1
        }
    ],
    'no-nested-ternary': 'error',
    'no-new': 'error',
    'no-new-func': 'error',
    'no-new-object': 'error',
    'no-new-require': 'error',
    'no-new-symbol': 'error',
    'no-new-wrappers': 'error',
    'no-obj-calls': 'error',
    'no-octal': 'error',
    'no-octal-escape': 'error',
    'no-param-reassign': [
        'error',
        {
            props: true
        }
    ],
    'no-path-concat': 'error',
    'no-process-exit': 'error',
    'no-proto': 'error',
    'no-redeclare': [
        'error',
        {
            builtinGlobals: true
        }
    ],
    'no-restricted-globals': 'error',
    'no-return-assign': [
        'error',
        'always'
    ],
    'no-script-url': 'error',
    'no-self-assign': [
        'error',
        {
            props: true
        }
    ],
    'no-self-compare': 'error',
    'no-sequences': 'error',
    'no-shadow': 'error',
    'no-shadow-restricted-names': 'error',
    'no-sparse-arrays': 'error',
    'no-sync': 'error',
    'no-tabs': 'error',
    'no-template-curly-in-string': 'error',
    'no-this-before-super': 'error',
    'no-throw-literal': 'error',
    'no-trailing-spaces': 'error',
    'no-undef': 'error',
    'no-undef-init': 'error',
    'no-unexpected-multiline': 'error',
    'no-unmodified-loop-condition': 'error',
    'no-unneeded-ternary': 'error',
    'no-unreachable': 'error',
    'no-unsafe-finally': 'error',
    'no-unsafe-negation': 'error',
    'no-unused-expressions': 'error',
    'no-unused-labels': 'error',
    'no-unused-vars': 'error',
    'no-use-before-define': 'error',
    'no-useless-call': 'error',
    'no-useless-computed-key': 'error',
    'no-useless-concat': 'error',
    'no-useless-constructor': 'error',
    'no-useless-escape': 'error',
    'no-useless-rename': 'error',
    'no-var': 'error',
    'no-void': 'error',
    'no-warning-comments': 'error',
    'no-whitespace-before-property': 'error',
    'no-with': 'error',
    'object-curly-spacing': 'error',
    'object-shorthand': 'error',
    'one-var': [
        'error',
        {
            const: 'never',
            let: 'always',
            var: 'always'
        }
    ],
    'one-var-declaration-per-line': [
        'error',
        'always'
    ],
    'padded-blocks': [
        'error',
        'never'
    ],
    'prefer-const': 'error',
    'prefer-numeric-literals': 'error',
    'prefer-reflect': 'error',
    'prefer-rest-params': 'error',
    'prefer-spread': 'error',
    'prefer-template': 'error',
    'quote-props': [
        'error',
        'as-needed',
        {
            numbers: true,
            unnecessary: false
        }
    ],
    'quotes': [
        'error',
        'single',
        {
            avoidEscape: true
        }
    ],
    'radix': [
        'error',
        'as-needed'
    ],
    'require-yield': 'error',
    'rest-spread-spacing': 'error',
    'semi': 'error',
    'semi-spacing': [
        'error',
        {
            after: true,
            before: false
        }
    ],
    'sort-keys': [
        'error',
        'asc',
        {
            caseSensitive: false,
            natural: true
        }
    ],
    'space-before-blocks': 'error',
    'space-before-function-paren': [
        'error',
        {
            anonymous: 'always',
            named: 'never'
        }
    ],
    'space-in-parens': 'error',
    'space-infix-ops': 'error',
    'space-unary-ops': [
        'error',
        {
            nonwords: false,
            words: true
        }
    ],
    'spaced-comment': 'error',
    'strict': [
        'error',
        'never'
    ],
    'symbol-description': 'error',
    'template-curly-spacing': 'error',
    'unicode-bom': 'error',
    'use-isnan': 'error',
    'valid-typeof': 'error',
    'vars-on-top': 'error',
    'wrap-iife': [
        'error',
        'any'
    ],
    'yield-star-spacing': [
        'error',
        'before'
    ],
    'yoda': [
        'error',
        'never'
    ]
};
/* eslint-enable no-magic-numbers */
<|endoftext|>