<commit_before>/**
 * Shopware 4.0
 * Copyright © 2012 shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * 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.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 *
 * @category   Shopware
 * @package    Migration
 * @subpackage Form
 * @copyright  Copyright (c) 2012, shopware AG (http://www.shopware.de)
 * @version    $Id$
 * @author shopware AG
 */

/**
 * Shopware UI - Migration import form
 * Lets the user select data to be imported and starts the actual import
 */
//{namespace name=backend/swag_migration/main}
//{block name="backend/swag_migration/view/form/import"}
Ext.define('Shopware.apps.SwagMigration.view.form.Import', {
    /**
     * Define that the billing field set is an extension of the Ext.form.FieldSet
     * @string
     */
    extend: 'Ext.form.Panel',
    bodyStyle: 'padding:10px',
    /**
     * The Ext.container.Container.layout for the fieldset's immediate child items.
     * @object
     */
    layout: 'anchor',

    autoScroll: true,

    /**
     * List of short aliases for class names. Most useful for defining xtypes for widgets.
     * @string
     */
    alias: 'widget.migration-form-import',
    /**
     * Set css class for this component
     * @string
     */
    cls: 'shopware-form',

    /**
     * will be set to true if the current profile needs an additional salt to be entered by the user
     */
    saltInputNeeded: false,

    /**
     * Will be set to true, if the migration plugin provides password encoder for the selected profile
     */
    showPasswordInfo: false,

    /**
     * Will be set to true, if migration plugin provides importing of downloads
     */
    importAllowed: false,

    importImages: true,

    /**
	 * The initComponent template method is an important initialization step for a Component.
     * It is intended to be implemented by each subclass of Ext.Component to provide any needed constructor logic.
     * The initComponent method of the class being created is called first,
     * with each initComponent method up the hierarchy to Ext.Component being called thereafter.
     * This makes it easy to implement and, if needed, override the constructor logic of the Component at any step in the hierarchy.
     * The initComponent method must contain a call to callParent in order to ensure that the parent class' initComponent method is also called.
	 *
	 * @return void
	 */
    initComponent:function () {
        var me = this;

        me.addEvents(
            /**
             * Fired when the supplier combo changes in order to trigger form validation
             */
            'validate'
        );

        me.items = me.createItems();
        me.callParent(arguments);
    },

    /**
     * Returns an array with the fieldsets available in this view
     * @return Array
     */
    createItems: function() {
        var me = this;

        me.passwordInfo = Shopware.Notification.createBlockMessage('{s name=passwordInfo}Attention: If you want the customer to be able to login with his old password, you should not uninstall the migration tool, as it provides the password encoder for migrated customers. Once a customer has logged in, his password will be converted to a shopware-password, so in most cases it should be safe to uninstall the migration tool after a year.{/s}', 'notice');
        me.passwordInfo .margin = '10 5';

        me.fieldSet = {
            xtype:'fieldset',
            layout: 'column',
            title: '{s name=importSettings}Import settings{/s}',
            autoHeight: true,
            defaults: {
                anchor: '100%',
                labelWidth: 500,
                buttonAlign: 'left'
            },
            defaultType: 'textfield',
            items : me.getContainers()
        };

        me.advancedOptionsFieldset = {
            xtype:'fieldset',
            title: '{s name=importSettingsAdvanced}Advanced import settings{/s}',
            autoHeight: true,
            defaults: {
                anchor: '100%',
                labelWidth: 500
            },
            items : me.getAdvancedInputItems()
        };

        var clearShopFieldSet = {
            xtype:'migration-fieldset-clearshop',
            collapsible: true,
            collapsed: true
        };

        return  [ me.passwordInfo,  me.fieldSet, me.advancedOptionsFieldset, clearShopFieldSet ];
    },

    getContainers:function () {
        var leftContainer, rightContainer, me = this;

        leftContainer = Ext.create('Ext.container.Container', {
            columnWidth:0.33,
            defaults: {
                labelWidth: 250,
                anchor: '100%',
                buttonAlign: 'left',
                checked: true
            },
            padding: '0 5 0 0',
            layout: 'anchor',
            border:false,
            items:me.getLeftItems()
        });

        rightContainer = Ext.create('Ext.container.Container', {
            columnWidth:0.67,
            layout: 'anchor',
            defaults: {
                labelWidth: 250,
                anchor: '100%',
                buttonAlign: 'left',
                checked: true
            },
            margin: '0 0 0 80',
            border:false,
            items:me.getRightItems()
        });

        return [ leftContainer, rightContainer ] ;
    },

    getLeftItems: function() {
        var me = this,
            items = [];

        items = [{
            fieldLabel: '{s name=importProducts}Import products{/s}',
            name: 'import_products',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=importTranslations}Import translations{/s}',
            name: 'import_translations',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=importProperties}Import product properties{/s}',
            name: 'import_properties',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=importCategories}Import categories{/s}',
            name: 'import_categories',
            xtype: 'checkbox'
        }, {
            fieldLabel: '',
            name: 'import_article_categories',
            xtype: 'checkbox',
            checked: false,
            hidden: true
        }, {
            fieldLabel: '{s name=importPrices}Import customer group prices{/s}',
            name: 'import_prices',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=generateVariants}Generate variants from attributes{/s}',
            name: 'import_generate_variants',
            xtype: 'checkbox'
        }, {
            fieldLabel: '',
            name: 'import_create_configurator_variants',
            xtype: 'checkbox',
            checked: false,
            hidden: true
        }];

        me.importInput = Ext.create('Ext.form.field.Checkbox', {
            labelWidth: 250,
            fieldLabel: '{s name=importDownloads}Import article downloads{/s}',
            helpText: '{s name=importDownloadsHelptext}Imports article attached downloads (e.g. a pdf-manual){/s}',
            name: 'import_downloads',
            checked: false,
            hidden: !me.importAllowed,
            listeners: {
                change: function(checkBox, newValue, oldValue, eOpts) {
                    me.importAllowed = newValue;

                    me.basePath.allowBlank = (!newValue && !me.importImages);
                    if(newValue || me.importImages) {
                        me.basePath.show();
                    }else{
                        me.basePath.hide();
                    }
                    me.fireEvent('validate');
                }
            }
        });
        items.push(me.importInput);

        me.importEsdInput = Ext.create('Ext.form.field.Checkbox', {
            labelWidth: 250,

            fieldLabel: '{s name=importDownloadsEsd}Import ESD Downloads{/s}',
            helpText: '{s name=importDownloadsEsdHelptext}There is no guarantee that esd downloads can be imported. Main restriction: the particular file must be available for download in the customer area of the base shop. Reasons for a file not to be downloadable may include: max number of downloads reached or download link expired.{/s}',
            name: 'import_downloads_esd',
            checked: false,
            hidden: !me.importAllowed,
            listeners: {
                change: function (checkBox, newValue, oldValue, eOpts) {
                    me.importAllowed = newValue;

                    me.basePath.allowBlank = (!newValue && !me.importImages);
                    if (newValue || me.importImages) {
                        me.basePath.show();
                    } else {
                        me.basePath.hide();
                    }
                    me.fireEvent('validate');
                }
            }
        });
        items.push(me.importEsdInput);

        me.importEsdOrderInput = Ext.create('Ext.form.field.Checkbox', {
            labelWidth: 250,
            fieldLabel: '{s name=importEsdOrders}Import ESD Orders{/s}',
            helpText: '{s name="importEsdOrdersHelptext"}Makes ESD articles available for download by customers in the frontend.{/s}',
            name: 'import_orders_esd',
            checked: false,
            hidden: !me.importAllowed,
            listeners: {
                change: function (checkBox, newValue, oldValue, eOpts) {
                    me.importAllowed = newValue;

                    me.basePath.allowBlank = (!newValue && !me.importImages);
                    if (newValue || me.importImages) {
                        me.basePath.show();
                    } else {
                        me.basePath.hide();
                    }
                    me.fireEvent('validate');
                }
            }
        });
        items.push(me.importEsdOrderInput);

        return items;
    },

    getRightItems: function() {
        var me = this;

        me.basePath = Ext.create('Ext.form.field.Text', {
            fieldLabel: '{s name=articleImagesPath}Shop path (e.g. http://www.example.org/old_shop or /var/www/old_shop){/s}',
            name: 'basepath',
            helpText: '{s name=helpTextBasePathTrailingSlash}Please append trailing slash to base path.{/s}',
            value: '',
            labelWidth: 250,
            allowBlank: false,
            listeners: {
                change: function() {
                    me.fireEvent('validate');
                }
            }
        });

        me.saltInput = Ext.create('Ext.form.field.Text', {
            fieldLabel: '{s name=saltInput}Password Salt{/s}',
            name: 'salt',
            value: '',
            labelWidth: 250,
            allowBlank: true,
            helpText: "{s name=saltInputHelp}The destination shop uses a salt to make its password more secure. In this special case the salt cannot be read automatically. Please copy the salt from /destination_shop/config/settings.inc.php to this field. It is defined as 'COOKIE KEY' there.{/s}",
            hidden: !me.saltInputNeeded,
            listeners: {
                change: function() {
                    me.fireEvent('validate');
                }
            }
        });

        me.imageInput = Ext.create('Ext.form.field.Checkbox', {
            fieldLabel: '{s name=importArticleImages}Import product images{/s}',
            name: 'import_images',
            xtype: 'checkbox',
            labelWidth: 250,
            helpText: '{s name=thumbnailGenerationNeeded}After image import you need to generate the image thumbnails in the media manager for the article album.{/s}',
            checked: me.importImages,
            listeners: {
                change: function(checkBox, newValue) {
                    me.importImages = newValue;

                    // if the product images are going to be imported, the basePath field is mandatory
                    me.basePath.allowBlank = (!newValue && !me.importAllowed);
                    if(newValue || me.importAllowed) {
                        me.basePath.show();
                    }else{
                        me.basePath.hide();
                    }
                    me.fireEvent('validate');
                }
            }
        });

        return [
            me.imageInput,
        {
            fieldLabel: '{s name=importCustomers}Import customers{/s}',
            name: 'import_customers',
            xtype: 'checkbox',
            listeners: {
                change: function(checkBox, newValue, oldValue, eOpts) {
                    if(newValue && me.saltInputNeeded) {
                        me.saltInput.show();
                        me.saltInput.allowBlank = false;
                    }else{
                        me.saltInput.hide();
                        me.saltInput.allowBlank = true;
                    }
                    me.fireEvent('validate');
                }
            }
        }, {
            fieldLabel: '{s name=importRatings}Import ratings{/s}',
            name: 'import_ratings',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=importOrders}Import orders{/s}',
            name: 'import_orders',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=finish}Finish import{/s}',
            name: 'finish_import',
            xtype: 'checkbox',
            checked: false
        }, {
            fieldLabel: '{s name=defaultSupplier}Default supplier{/s}',
            name: 'supplier',
            hiddenName: 'supplier',
            valueField: 'name',
            displayField: 'name',
            triggerAction: 'all',
            xtype: 'combo',
            allowBlank: false,
            mode: 'remote',
            selectOnFocus: true,
            store: Ext.create('Shopware.apps.Base.store.Supplier'),
            listeners: {
                change: function() {
                    me.fireEvent('validate');
                }
            }
        },
            me.basePath,
            me.saltInput
        ];

    },

    getAdvancedInputItems: function() {
        var me = this;

        var radioGroup = Ext.create('Ext.form.RadioGroup', {
                fieldLabel: '{s name=handleInvalidProductNumbers}How to handle invalid product numbers{/s}',
                labelWidth: 500,
                columns: 1,
                items: [
                    {
                        xtype: 'radiofield',
                        boxLabel: '{s name=handleProductNumber/complain}Complain about invalid product numbers{/s}',
                        name: 'number_validation_mode',
                        checked: true,
                        inputValue: 'complain'
                    },
                    {
                        xtype: 'radiofield',
                        boxLabel: '{s name=handleProductNumber/convert}Generate new valid numbers{/s}',
                        name: 'number_validation_mode',
                        inputValue: 'make_valid'
                    },
                    {
                        xtype: 'radiofield',
                        boxLabel: '{s name=handleProductNumber/ignore}Ignore invalid product numbers (not recommended){/s}',
                        name: 'number_validation_mode',
                        inputValue: 'ignore'
                    }
                ]
            });

        return [radioGroup];

    },

    setShowPasswordInfo: function(value) {
        var me = this;

        me.showPasswordInfo = value;

        if (value) {
            me.passwordInfo.show();
        } else {
            me.passwordInfo.reset();
            me.passwordInfo.hide();
        }
    },

    setSaltInputNeeded: function(value) {
        var me = this;

        me.saltInputNeeded = value;

        if (value) {
            me.saltInput.show();
            me.saltInput.allowBlank = false;
        } else {
            me.saltInput.reset();
            me.saltInput.hide();
            me.saltInput.allowBlank = true;
        }
    },

    setImportAllowed: function(value) {
        var me = this;

        me.importAllowed = value;

        if (value) {
            me.importInput.show();
            me.importInput.allowBlank = false;
            me.importEsdInput.show();
            me.importEsdInput.allowBlank = false;
            me.importEsdOrderInput.show();
            me.importEsdOrderInput.allowBlank = false;
        } else {
            me.importInput.reset();
            me.importInput.hide();
            me.importInput.allowBlank = true;
            me.importEsdInput.reset();
            me.importEsdInput.hide();
            me.importEsdInput.allowBlank = true;
            me.importEsdOrderInput.reset();
            me.importEsdOrderInput.hide();
            me.importEsdOrderInput.allowBlank = true;
        }
    }

});
//{/block}
<commit_msg>PT-3111 hide esd orders when import orders not selected<commit_after>/**
 * Shopware 4.0
 * Copyright © 2012 shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * 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.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 *
 * @category   Shopware
 * @package    Migration
 * @subpackage Form
 * @copyright  Copyright (c) 2012, shopware AG (http://www.shopware.de)
 * @version    $Id$
 * @author shopware AG
 */

/**
 * Shopware UI - Migration import form
 * Lets the user select data to be imported and starts the actual import
 */
//{namespace name=backend/swag_migration/main}
//{block name="backend/swag_migration/view/form/import"}
Ext.define('Shopware.apps.SwagMigration.view.form.Import', {
    /**
     * Define that the billing field set is an extension of the Ext.form.FieldSet
     * @string
     */
    extend: 'Ext.form.Panel',
    bodyStyle: 'padding:10px',
    /**
     * The Ext.container.Container.layout for the fieldset's immediate child items.
     * @object
     */
    layout: 'anchor',

    autoScroll: true,

    /**
     * List of short aliases for class names. Most useful for defining xtypes for widgets.
     * @string
     */
    alias: 'widget.migration-form-import',
    /**
     * Set css class for this component
     * @string
     */
    cls: 'shopware-form',

    /**
     * will be set to true if the current profile needs an additional salt to be entered by the user
     */
    saltInputNeeded: false,

    /**
     * Will be set to true, if the migration plugin provides password encoder for the selected profile
     */
    showPasswordInfo: false,

    basePathAllow: true,

    /**
	 * The initComponent template method is an important initialization step for a Component.
     * It is intended to be implemented by each subclass of Ext.Component to provide any needed constructor logic.
     * The initComponent method of the class being created is called first,
     * with each initComponent method up the hierarchy to Ext.Component being called thereafter.
     * This makes it easy to implement and, if needed, override the constructor logic of the Component at any step in the hierarchy.
     * The initComponent method must contain a call to callParent in order to ensure that the parent class' initComponent method is also called.
	 *
	 * @return void
	 */
    initComponent:function () {
        var me = this;

        me.addEvents(
            /**
             * Fired when the supplier combo changes in order to trigger form validation
             */
            'validate'
        );

        me.items = me.createItems();
        me.callParent(arguments);
    },

    /**
     * Returns an array with the fieldsets available in this view
     * @return Array
     */
    createItems: function() {
        var me = this;

        me.passwordInfo = Shopware.Notification.createBlockMessage('{s name=passwordInfo}Attention: If you want the customer to be able to login with his old password, you should not uninstall the migration tool, as it provides the password encoder for migrated customers. Once a customer has logged in, his password will be converted to a shopware-password, so in most cases it should be safe to uninstall the migration tool after a year.{/s}', 'notice');
        me.passwordInfo .margin = '10 5';

        me.fieldSet = {
            xtype:'fieldset',
            layout: 'column',
            title: '{s name=importSettings}Import settings{/s}',
            autoHeight: true,
            defaults: {
                anchor: '100%',
                labelWidth: 500,
                buttonAlign: 'left'
            },
            defaultType: 'textfield',
            items : me.getContainers()
        };

        me.advancedOptionsFieldset = {
            xtype:'fieldset',
            title: '{s name=importSettingsAdvanced}Advanced import settings{/s}',
            autoHeight: true,
            defaults: {
                anchor: '100%',
                labelWidth: 500
            },
            items : me.getAdvancedInputItems()
        };

        var clearShopFieldSet = {
            xtype:'migration-fieldset-clearshop',
            collapsible: true,
            collapsed: true
        };

        return  [ me.passwordInfo,  me.fieldSet, me.advancedOptionsFieldset, clearShopFieldSet ];
    },

    getContainers:function () {
        var leftContainer, rightContainer, me = this;

        leftContainer = Ext.create('Ext.container.Container', {
            columnWidth:0.33,
            defaults: {
                labelWidth: 250,
                anchor: '100%',
                buttonAlign: 'left',
                checked: true
            },
            padding: '0 5 0 0',
            layout: 'anchor',
            border:false,
            items:me.getLeftItems()
        });

        rightContainer = Ext.create('Ext.container.Container', {
            columnWidth:0.67,
            layout: 'anchor',
            defaults: {
                labelWidth: 250,
                anchor: '100%',
                buttonAlign: 'left',
                checked: true
            },
            margin: '0 0 0 80',
            border:false,
            items:me.getRightItems()
        });

        return [ leftContainer, rightContainer ] ;
    },

    getLeftItems: function() {
        var me = this,
            items = [];

        items = [{
            fieldLabel: '{s name=importProducts}Import products{/s}',
            name: 'import_products',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=importTranslations}Import translations{/s}',
            name: 'import_translations',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=importProperties}Import product properties{/s}',
            name: 'import_properties',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=importCategories}Import categories{/s}',
            name: 'import_categories',
            xtype: 'checkbox'
        }, {
            fieldLabel: '',
            name: 'import_article_categories',
            xtype: 'checkbox',
            checked: false,
            hidden: true
        }, {
            fieldLabel: '{s name=importPrices}Import customer group prices{/s}',
            name: 'import_prices',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=generateVariants}Generate variants from attributes{/s}',
            name: 'import_generate_variants',
            xtype: 'checkbox'
        }, {
            fieldLabel: '',
            name: 'import_create_configurator_variants',
            xtype: 'checkbox',
            checked: false,
            hidden: true
        }];

        me.importInput = Ext.create('Ext.form.field.Checkbox', {
            labelWidth: 250,
            fieldLabel: '{s name=importDownloads}Import article downloads{/s}',
            helpText: '{s name=importDownloadsHelptext}Imports article attached downloads (e.g. a pdf-manual){/s}',
            name: 'import_downloads',
            checked: false,
            listeners: {
                change: function(checkBox, newValue) {
                    me.basePath.allowBlank = (!newValue && !me.imageInput.getValue());
                    if(newValue || me.imageInput.getValue()) {
                        me.basePath.show();
                    } else {
                        me.basePath.hide();
                    }

                    if(newValue) {
                        me.importEsdInput.show();
                    } else {
                        me.importEsdInput.hide();
                        me.importEsdInput.reset();
                    }

                    me.fireEvent('validate');
                }
            }
        });
        items.push(me.importInput);

        me.importEsdInput = Ext.create('Ext.form.field.Checkbox', {
            labelWidth: 250,
            fieldLabel: '{s name=importDownloadsEsd}Import ESD Downloads{/s}',
            helpText: '{s name=importDownloadsEsdHelptext}There is no guarantee that esd downloads can be imported. Main restriction: the particular file must be available for download in the customer area of the base shop. Reasons for a file not to be downloadable may include: max number of downloads reached or download link expired.{/s}',
            name: 'import_downloads_esd',
            checked: false,
            hidden: true,
            listeners: {
                change: function () {
                    me.fireEvent('validate');
                }
            }
        });
        items.push(me.importEsdInput);

        me.importEsdOrderInput = Ext.create('Ext.form.field.Checkbox', {
            labelWidth: 250,
            fieldLabel: '{s name=importEsdOrders}Import ESD Orders{/s}',
            helpText: '{s name="importEsdOrdersHelptext"}Makes ESD articles available for download by customers in the frontend.{/s}',
            name: 'import_orders_esd',
            checked: false,
            listeners: {
                change: function () {
                    me.fireEvent('validate');
                }
            }
        });
        items.push(me.importEsdOrderInput);

        return items;
    },

    getRightItems: function() {
        var me = this;

        me.basePath = Ext.create('Ext.form.field.Text', {
            fieldLabel: '{s name=articleImagesPath}Shop path (e.g. http://www.example.org/old_shop or /var/www/old_shop){/s}',
            name: 'basepath',
            helpText: '{s name=helpTextBasePathTrailingSlash}Please append trailing slash to base path.{/s}',
            value: '',
            labelWidth: 250,
            allowBlank: false,
            listeners: {
                change: function() {
                    me.fireEvent('validate');
                }
            }
        });

        me.saltInput = Ext.create('Ext.form.field.Text', {
            fieldLabel: '{s name=saltInput}Password Salt{/s}',
            name: 'salt',
            value: '',
            labelWidth: 250,
            allowBlank: true,
            helpText: "{s name=saltInputHelp}The destination shop uses a salt to make its password more secure. In this special case the salt cannot be read automatically. Please copy the salt from /destination_shop/config/settings.inc.php to this field. It is defined as 'COOKIE KEY' there.{/s}",
            hidden: !me.saltInputNeeded,
            listeners: {
                change: function() {
                    me.fireEvent('validate');
                }
            }
        });

        me.imageInput = Ext.create('Ext.form.field.Checkbox', {
            fieldLabel: '{s name=importArticleImages}Import product images{/s}',
            name: 'import_images',
            xtype: 'checkbox',
            labelWidth: 250,
            helpText: '{s name=thumbnailGenerationNeeded}After image import you need to generate the image thumbnails in the media manager for the article album.{/s}',
            checked: me.basePathAllow,
            listeners: {
                change: function(checkBox, newValue) {
                    // if the product images are going to be imported, the basePath field is mandatory
                    me.basePath.allowBlank = (!newValue && !me.importInput.getValue());
                    if(newValue || me.importInput.getValue()) {
                        me.basePath.show();
                    } else {
                        me.basePath.hide();
                    }
                    me.fireEvent('validate');
                }
            }
        });

        return [
            me.imageInput,
        {
            fieldLabel: '{s name=importCustomers}Import customers{/s}',
            name: 'import_customers',
            xtype: 'checkbox',
            listeners: {
                change: function(checkBox, newValue, oldValue, eOpts) {
                    if(newValue && me.saltInputNeeded) {
                        me.saltInput.show();
                        me.saltInput.allowBlank = false;
                    }else{
                        me.saltInput.hide();
                        me.saltInput.allowBlank = true;
                    }
                    me.fireEvent('validate');
                }
            }
        }, {
            fieldLabel: '{s name=importRatings}Import ratings{/s}',
            name: 'import_ratings',
            xtype: 'checkbox'
        }, {
            fieldLabel: '{s name=importOrders}Import orders{/s}',
            name: 'import_orders',
            xtype: 'checkbox',
            listeners: {
                change: function(checkBox, newValue) {
                    if(newValue) {
                        me.importEsdOrderInput.show();
                    } else {
                        me.importEsdOrderInput.hide();
                        me.importEsdOrderInput.reset();
                    }
                }
            }
        }, {
            fieldLabel: '{s name=finish}Finish import{/s}',
            name: 'finish_import',
            xtype: 'checkbox',
            checked: false
        }, {
            fieldLabel: '{s name=defaultSupplier}Default supplier{/s}',
            name: 'supplier',
            hiddenName: 'supplier',
            valueField: 'name',
            displayField: 'name',
            triggerAction: 'all',
            xtype: 'combo',
            allowBlank: false,
            mode: 'remote',
            selectOnFocus: true,
            store: Ext.create('Shopware.apps.Base.store.Supplier'),
            listeners: {
                change: function() {
                    me.fireEvent('validate');
                }
            }
        },
            me.basePath,
            me.saltInput
        ];

    },

    getAdvancedInputItems: function() {
        var me = this;

        var radioGroup = Ext.create('Ext.form.RadioGroup', {
                fieldLabel: '{s name=handleInvalidProductNumbers}How to handle invalid product numbers{/s}',
                labelWidth: 500,
                columns: 1,
                items: [
                    {
                        xtype: 'radiofield',
                        boxLabel: '{s name=handleProductNumber/complain}Complain about invalid product numbers{/s}',
                        name: 'number_validation_mode',
                        checked: true,
                        inputValue: 'complain'
                    },
                    {
                        xtype: 'radiofield',
                        boxLabel: '{s name=handleProductNumber/convert}Generate new valid numbers{/s}',
                        name: 'number_validation_mode',
                        inputValue: 'make_valid'
                    },
                    {
                        xtype: 'radiofield',
                        boxLabel: '{s name=handleProductNumber/ignore}Ignore invalid product numbers (not recommended){/s}',
                        name: 'number_validation_mode',
                        inputValue: 'ignore'
                    }
                ]
            });

        return [radioGroup];

    },

    setShowPasswordInfo: function(value) {
        var me = this;

        me.showPasswordInfo = value;

        if (value) {
            me.passwordInfo.show();
        } else {
            me.passwordInfo.reset();
            me.passwordInfo.hide();
        }
    },

    setSaltInputNeeded: function(value) {
        var me = this;

        me.saltInputNeeded = value;

        if (value) {
            me.saltInput.show();
            me.saltInput.allowBlank = false;
        } else {
            me.saltInput.reset();
            me.saltInput.hide();
            me.saltInput.allowBlank = true;
        }
    },

    setImportAllowed: function(value) {
        var me = this;

        if (value) {
            me.importInput.show();
            me.importInput.allowBlank = false;
            me.importEsdOrderInput.show();
            me.importEsdOrderInput.allowBlank = false;
        } else {
            me.importInput.reset();
            me.importInput.hide();
            me.importInput.allowBlank = true;
            me.importEsdInput.reset();
            me.importEsdInput.hide();
            me.importEsdInput.allowBlank = true;
            me.importEsdOrderInput.reset();
            me.importEsdOrderInput.hide();
            me.importEsdOrderInput.allowBlank = true;
        }
    }

});
//{/block}
<|endoftext|>


<commit_before>var request = require('request').defaults({json: true});
var HttpStatus = require('http-status-codes');
var async = require('async');
var auth = require('../helper/auth');
var api = require('../helper/api').skvsApiUrl;
var hubApi = require('../helper/api').dockerHubApiUrl;
var error_helper = require('../helper/error').errorHelper;
var request_handler = require('../helper/error').requestHandler;

module.exports = function (router) {
  // TODO: return system data: IP, hostname, hardware revision, software revision, etc.
  router.get('/system', auth, function (req, res, next) {
    res.json({status: "okay"});
  });

  router.get('/system/update', auth, function (req, res, next) {
    /*
     ┌────────────────────────────┐
     │      Frontend Request      │
     │GET /admin/api/system/update│
     └────────────────────────────┘
     │
     ▼
     ┌──────────────────────────┐
     │ skvs GET /system/channel │
     └──────────────────────────┘
     │ eg. 'development'
     ▼
     ┌──────────────────────────┐
     │ skvs GET /system/images  │
     └──────────────────────────┘
     │     Keys: key1...keyN
     ┌──────────────────────────────┐    │    ┌──────────────────────────────┐
     ┌──│skvs GET /system/images/<key1>│◀───┼───▶│hub GET /<key1>/tag/<channel> │──┐
     │  └──────────────────────────────┘    │    └──────────────────────────────┘  │
     │                   .                  │                     .                │
     │                   .          Parallel Requests             .                │
     │                   .                  │                     .                │
     │  ┌──────────────────────────────┐    │    ┌──────────────────────────────┐  │
     ├──│skvs GET /system/images/<keyN>│◀───┴───▶│hub GET /<keyN>/tag/<channel> │──┤
     │  └──────────────────────────────┘         └──────────────────────────────┘  │
     │                                                                             │
     │   Local image1...imageN           ┌─────┐          Remote image1...imageN   │
     └──────────────────────────────────▶│MERGE│◀──────────────────────────────────┘
     └─────┘
     │
     ▼
     ┌──────────────────┐
     │Frontend Response │
     └──────────────────┘
     */
    request(api('/system/channel'), request_handler(function (response, result) {
      if (response.statusCode == HttpStatus.OK) {
        var channel = result.value.trim();
        request(api('/system/images'), request_handler(function (response, result) {
          if (response.statusCode == HttpStatus.OK && result.namespace) {
            var get_image_id_for_key = result.keys.reduce(function (obj, key) {
              obj[key] = function (callback) {
                // Get all Image Ids via skvs/dockerhub
                async.parallel({
                  local: function (c) {
                    request(api('/system/images/' + key), request_handler(function (response, result) {
                      if (result.value == undefined || result.value == null) {
                        result.value = ""; // always return empty string.
                      }
                      c(null, result.value.trim());
                    }), function () {
                      c(null, ""); // empty string if something went wrong
                    });
                  },
                  remote: function (c) {
                    var key_splitted = key.split(":");
                    var name = key_splitted[0];
                    var tag = key_splitted[1];
                    request(hubApi(name + '/tags/' + tag), request_handler(function (response, result) {
                      var latest_layer = result[0] || {id: ""};
                      c(null, latest_layer.id);
                    }), function () {
                      c(null, ""); // empty string if something went wrong
                    });
                  }
                }, function (err, results) {
                  results = results || {}; // no error handling here, if something went wrong, handle it outside.
                  callback(null, results);
                });
              };
              return obj;
            }, {});
            async.parallel(get_image_id_for_key, function (err, images) {
              images = images || {};
              var result = {};
              result['images'] = images;
              result['channel'] = channel;
              var image_keys = Object.keys(images);
              if (image_keys.length == 0) {
                result.up_to_date = false; // No Images => update needed!
              } else {
                result.up_to_date = image_keys.every(function (currentKey, i, arr) {
                  var currentImage = images[currentKey];
                  return currentImage.local.indexOf(currentImage.remote) === 0;
                });
              }
              res.json(result);
            });
          } else {
            next(error_helper(HttpStatus.INTERNAL_SERVER_ERROR, "No image states found."));
          }
        }, next));
      } else {
        next(error_helper(HttpStatus.INTERNAL_SERVER_ERROR, "No channel found!"));
      }
    }, next));
  });

  router.post('/system/update', auth, function (req, res, next) {
    var channel = req.body['channel'];
    if (channel == undefined || channel == null || channel == "") {
      next(error_helper(HttpStatus.BAD_REQUEST, "No channel given!"));
    } else {
      var options = {
        url: api('/system/channel'),
        method: 'PUT',
        form: {
          value: channel
        }
      };
      request(options, request_handler(function (response, result) {
        if (response.statusCode == HttpStatus.OK) {
          res.json({status: "okay", channel: channel});
        } else {
          next(error_helper(HttpStatus.INTERNAL_SERVER_ERROR));
        }
      }), next);
    }
  });
};
<commit_msg>Comment opn bugs.<commit_after>var request = require('request').defaults({json: true});
var HttpStatus = require('http-status-codes');
var async = require('async');
var auth = require('../helper/auth');
var api = require('../helper/api').skvsApiUrl;
var hubApi = require('../helper/api').dockerHubApiUrl;
var error_helper = require('../helper/error').errorHelper;
var request_handler = require('../helper/error').requestHandler;

module.exports = function (router) {
  // TODO: return system data: IP, hostname, hardware revision, software revision, etc.
  router.get('/system', auth, function (req, res, next) {
    res.json({status: "okay"});
  });

  router.get('/system/update', auth, function (req, res, next) {
    /*
     ┌────────────────────────────┐
     │      Frontend Request      │
     │GET /admin/api/system/update│
     └────────────────────────────┘
     │
     ▼
     ┌──────────────────────────┐
     │ skvs GET /system/channel │
     └──────────────────────────┘
     │ eg. 'development'
     ▼
     ┌──────────────────────────┐
     │ skvs GET /system/images  │
     └──────────────────────────┘
     │     Keys: key1...keyN
     ┌──────────────────────────────┐    │    ┌──────────────────────────────┐
     ┌──│skvs GET /system/images/<key1>│◀───┼───▶│hub GET /<key1>/tag/<channel> │──┐
     │  └──────────────────────────────┘    │    └──────────────────────────────┘  │
     │                   .                  │                     .                │
     │                   .          Parallel Requests             .                │
     │                   .                  │                     .                │
     │  ┌──────────────────────────────┐    │    ┌──────────────────────────────┐  │
     ├──│skvs GET /system/images/<keyN>│◀───┴───▶│hub GET /<keyN>/tag/<channel> │──┤
     │  └──────────────────────────────┘         └──────────────────────────────┘  │
     │                                                                             │
     │   Local image1...imageN           ┌─────┐          Remote image1...imageN   │
     └──────────────────────────────────▶│MERGE│◀──────────────────────────────────┘
     └─────┘
     │
     ▼
     ┌──────────────────┐
     │Frontend Response │
     └──────────────────┘
     */
    request(api('/system/channel'), request_handler(function (response, result) {
      if (response.statusCode == HttpStatus.OK) {
        var channel = result.value.trim();
        request(api('/system/images'), request_handler(function (response, result) {
          if (response.statusCode == HttpStatus.OK && result.namespace) {
            var get_image_id_for_key = result.keys.reduce(function (obj, key) {
              obj[key] = function (callback) {
                // Get all Image Ids via skvs/dockerhub
                async.parallel({
                  local: function (c) {
                    request(api('/system/images/' + key), request_handler(function (response, result) {
                      if (result.value == undefined || result.value == null) {
                        result.value = ""; // always return empty string.
                      }
                      c(null, result.value.trim());
                    }), function () {
                      c(null, ""); // empty string if something went wrong
                    });
                  },
                  remote: function (c) {
                    var key_splitted = key.split(":");
                    var name = key_splitted[0];
                    var tag = key_splitted[1];
                    request(hubApi(name + '/tags/' + tag), request_handler(function (response, result) {
                      var latest_layer = result[0] || {id: ""};
                      c(null, latest_layer.id);
                    }), function () {
                      c(null, ""); // empty string if something went wrong
                    });
                  }
                }, function (err, results) {
                  results = results || {}; // no error handling here, if something went wrong, handle it outside.
                  callback(null, results);
                });
              };
              return obj;
            }, {});
            async.parallel(get_image_id_for_key, function (err, images) {
              images = images || {};
              var result = {};
              result['images'] = images;
              result['channel'] = channel;
              // TODO: filter images for the correct channel only
              // TODO: # TODO: handle images w/ slashes like ibuildthecloud/systemd-docker:latest
              // TODO: race condition in trigger-update-protonet.{service, path}
              var image_keys = Object.keys(images);
              if (image_keys.length == 0) {
                result.up_to_date = false; // No Images => update needed!
                console.log('Found no images, update required.');
              } else {
                result.up_to_date = image_keys.every(function (currentKey, i, arr) {
                  var currentImage = images[currentKey];
                  var result = currentImage.local.indexOf(currentImage.remote) === 0;
                  if (! result) {
                    console.log('Remote "' + currentImage.remote + '" differs from local and will trigger an update.');
                  }
                  return result;
                });
              }
              res.json(result);
            });
          } else {
            next(error_helper(HttpStatus.INTERNAL_SERVER_ERROR, "No image states found."));
          }
        }, next));
      } else {
        next(error_helper(HttpStatus.INTERNAL_SERVER_ERROR, "No channel found!"));
      }
    }, next));
  });

  router.post('/system/update', auth, function (req, res, next) {
    var channel = req.body['channel'];
    if (channel == undefined || channel == null || channel == "") {
      next(error_helper(HttpStatus.BAD_REQUEST, "No channel given!"));
    } else {
      var options = {
        url: api('/system/channel'),
        method: 'PUT',
        form: {
          value: channel
        }
      };
      request(options, request_handler(function (response, result) {
        if (response.statusCode == HttpStatus.OK) {
          res.json({status: "okay", channel: channel});
        } else {
          next(error_helper(HttpStatus.INTERNAL_SERVER_ERROR));
        }
      }), next);
    }
  });
};
<|endoftext|>


<commit_before>//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Creates "back" button, if applicable
//------------------------------------------------------------------------------
d3plus.ui.history = function(vars) {

  if (!vars.small && vars.history.states.length > 0) {

    var button = vars.parent.selectAll("div#d3plus_back_button")
      .data(["d3plus_back_button"])

    var size = vars.title.value
      ? vars.style.title.font.size : vars.style.title.sub.font.size

    var color = vars.title.sub.value
      ? vars.style.title.sub.font.color : vars.style.title.font.color

    var family = vars.title.sub.value
      ? vars.style.title.sub.font.family : vars.style.title.font.family

    var weight = vars.title.sub.value
      ? vars.style.title.sub.font.weight : vars.style.title.font.weight

    var padding = vars.title.sub.value
      ? vars.style.title.sub["padding"] : vars.style.title["padding"]

    function style(elem) {

        elem
          .style("position","absolute")
          .style("left",padding*2+"px")
          .style("top",vars.margin.top/2-size/2+"px")
          .style("color", color)
          .style("font-family", family)
          .style("font-weight", weight)
          .style("font-size",size+"px")
          .style("z-index",2000)

    }

    var min_height = size + padding*2
    if (vars.margin.top < min_height) {
      vars.margin.top = min_height
    }

    var enter = button.enter().append("div")
      .attr("id","d3plus_back_button")
      .style("opacity",0)
      .call(style)
      .html(function(){

        if (d3plus.fonts.awesome) {
          var arrow = "&#xf104"
        }
        else {
          var arrow = "« "
        }

        return arrow+vars.format("Back")

      })

    button
      .on(d3plus.evt.over,function(){

        if (!vars.small && vars.history.states.length > 0) {

          d3.select(this)
            .style("cursor","pointer")
            .transition().duration(vars.style.timing.mouseevents)
              .style("color",d3plus.color.lighter(color))

        }

      })
      .on(d3plus.evt.out,function(){

        if (!vars.small && vars.history.states.length > 0) {

          d3.select(this)
            .style("cursor","auto")
            .transition().duration(vars.style.timing.mouseevents)
              .style("color",color)

        }

      })
      .on(d3plus.evt.click,function(){

        vars.back()

      })
      .transition().duration(vars.style.timing.transitions)
        .style("opacity",1)
        .call(style)

  }
  else {
    vars.parent.selectAll("div#d3plus_back_button")
      .transition().duration(vars.style.timing.transitions)
      .style("opacity",0)
      .remove()
  }

}
<commit_msg>moved back button a little bit more to the right<commit_after>//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Creates "back" button, if applicable
//------------------------------------------------------------------------------
d3plus.ui.history = function(vars) {

  if (!vars.small && vars.history.states.length > 0) {

    var button = vars.parent.selectAll("div#d3plus_back_button")
      .data(["d3plus_back_button"])

    var size = vars.title.value
      ? vars.style.title.font.size : vars.style.title.sub.font.size

    var color = vars.title.sub.value
      ? vars.style.title.sub.font.color : vars.style.title.font.color

    var family = vars.title.sub.value
      ? vars.style.title.sub.font.family : vars.style.title.font.family

    var weight = vars.title.sub.value
      ? vars.style.title.sub.font.weight : vars.style.title.font.weight

    var padding = vars.title.sub.value
      ? vars.style.title.sub["padding"] : vars.style.title["padding"]

    function style(elem) {

        elem
          .style("position","absolute")
          .style("left",padding*4+"px")
          .style("top",vars.margin.top/2-size/2+"px")
          .style("color", color)
          .style("font-family", family)
          .style("font-weight", weight)
          .style("font-size",size+"px")
          .style("z-index",2000)

    }

    var min_height = size + padding*2
    if (vars.margin.top < min_height) {
      vars.margin.top = min_height
    }

    var enter = button.enter().append("div")
      .attr("id","d3plus_back_button")
      .style("opacity",0)
      .call(style)
      .html(function(){

        if (d3plus.fonts.awesome) {
          var arrow = "&#xf104"
        }
        else {
          var arrow = "« "
        }

        return arrow+vars.format("Back")

      })

    button
      .on(d3plus.evt.over,function(){

        if (!vars.small && vars.history.states.length > 0) {

          d3.select(this)
            .style("cursor","pointer")
            .transition().duration(vars.style.timing.mouseevents)
              .style("color",d3plus.color.lighter(color))

        }

      })
      .on(d3plus.evt.out,function(){

        if (!vars.small && vars.history.states.length > 0) {

          d3.select(this)
            .style("cursor","auto")
            .transition().duration(vars.style.timing.mouseevents)
              .style("color",color)

        }

      })
      .on(d3plus.evt.click,function(){

        vars.back()

      })
      .transition().duration(vars.style.timing.transitions)
        .style("opacity",1)
        .call(style)

  }
  else {
    vars.parent.selectAll("div#d3plus_back_button")
      .transition().duration(vars.style.timing.transitions)
      .style("opacity",0)
      .remove()
  }

}
<|endoftext|>


<commit_before>import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
// import resourcesToBackend from 'i18next-resources-to-backend';
import { format as formatDate, isDate } from 'date-fns';
import { enUS as en, es } from 'date-fns/locale';
import enTranslation from '../../locales/en/translation.json';

/**
 * Helper function to set language on main element for DS component detection.
 *
 * @param {string} language
 */
const setPageLanguage = language => {
  document.getElementById('main')?.setAttribute('lang', language);
};

const locales = { en, es };

i18n
  /*
  .use(
    resourcesToBackend((language, namespace, callback) => {
      import(`../../locales/${language}/${namespace}.json`)
        .then(resources => {
          callback(null, resources);
        })
        .catch(error => {
          callback(error, null);
        });
    }),
  )
  */
  .use(initReactI18next)
  .use(LanguageDetector)
  .init({
    detection: {
      order: ['localStorage', 'sessionStorage', 'navigator'],
      lookupLocalStorage: 'checkin-i18nextLng',
      lookupSessionStorage: 'checkin-i18nextLng',
    },
    fallbackLng: 'en',
    debug: false,
    interpolation: {
      escapeValue: false,
      format: (value, format, lng) => {
        if (isDate(value)) {
          const locale = locales[lng];

          if (format === 'long') {
            return formatDate(value, 'MMMM dd, yyyy', { locale });
          }
          if (format === 'longAtTime') {
            let dateString = formatDate(value, 'PPPppp', { locale });

            // Remove date suffixes. (1st/2nd/etc.)
            dateString = dateString.replace(
              /([0-9]{1,2})([a-z]{2})(, )/,
              '$1$3',
            );

            // Adjust am/pm formatting.
            dateString = dateString.replace(/:[0-9]{2} AM .*$/, ' a.m.');
            dateString = dateString.replace(/:[0-9]{2} PM .*$/, ' p.m.');

            return dateString;
          }
          if (format === 'mdY') {
            return formatDate(value, 'MM/dd/Y');
          }
          if (format === 'time') {
            return formatDate(value, 'h:mm aaaa', { locale });
          }

          return formatDate(value, format, { locale });
        }
        return value;
      },
    },
    // Load only the english translation.
    // TODO: use resourcesToBackend to dynamically load all translations
    // once translations have been rolled out in production.
    resources: {
      en: { translation: enTranslation },
    },
  });

// This is necessary for DS components to use our language preference on initial load.
setPageLanguage(i18n.language);

i18n.on('languageChanged', language => {
  setPageLanguage(language);
});

export default i18n;
<commit_msg>Add debug statements (#21355)<commit_after>import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
// import resourcesToBackend from 'i18next-resources-to-backend';
import { format as formatDate, isDate } from 'date-fns';
import { enUS as en, es } from 'date-fns/locale';
import enTranslation from '../../locales/en/translation.json';

/**
 * Helper function to set language on main element for DS component detection.
 *
 * @param {string} language
 */
const setPageLanguage = language => {
  document.getElementById('main')?.setAttribute('lang', language);
};

const locales = { en, es };

i18n
  /*
  .use(
    resourcesToBackend((language, namespace, callback) => {
      import(`../../locales/${language}/${namespace}.json`)
        .then(resources => {
          callback(null, resources);
        })
        .catch(error => {
          callback(error, null);
        });
    }),
  )
  */
  .use(initReactI18next)
  .use(LanguageDetector)
  .init({
    detection: {
      order: ['localStorage', 'sessionStorage', 'navigator'],
      lookupLocalStorage: 'checkin-i18nextLng',
      lookupSessionStorage: 'checkin-i18nextLng',
    },
    fallbackLng: 'en',
    debug: false,
    interpolation: {
      escapeValue: false,
      format: (value, format, lng) => {
        if (isDate(value)) {
          const locale = locales[lng];

          if (format === 'long') {
            return formatDate(value, 'MMMM dd, yyyy', { locale });
          }
          if (format === 'longAtTime') {
            let dateString = formatDate(value, 'PPPppp', { locale });

            // Remove date suffixes. (1st/2nd/etc.)
            dateString = dateString.replace(
              /([0-9]{1,2})([a-z]{2})(, )/,
              '$1$3',
            );

            // Adjust am/pm formatting.
            dateString = dateString.replace(/:[0-9]{2} AM .*$/, ' a.m.');
            dateString = dateString.replace(/:[0-9]{2} PM .*$/, ' p.m.');

            return dateString;
          }
          if (format === 'mdY') {
            return formatDate(value, 'MM/dd/Y');
          }
          if (format === 'time') {
            return formatDate(value, 'h:mm aaaa', { locale });
          }

          return formatDate(value, format, { locale });
        }
        return value;
      },
    },
    // Load only the english translation.
    // TODO: use resourcesToBackend to dynamically load all translations
    // once translations have been rolled out in production.
    resources: {
      en: { translation: enTranslation },
    },
  });

// This is necessary for DS components to use our language preference on initial load.
setPageLanguage(i18n.language);

// Ugly hack to trigger DS language detection.
window.addEventListener('load', () => {
  setTimeout(() => {
    setPageLanguage(i18n.language);
  }, 10);
});

i18n.on('languageChanged', language => {
  setPageLanguage(language);
});

export default i18n;
<|endoftext|>


<commit_before>(function ($) {
  function SlickColumnPicker(columns, grid, user_id, options) {
    var $menu;
    var columnCheckboxes;
    var _self = this;   // Ekohe Add

    var defaults = {
      fadeSpeed:250
    };

    // Ekohe Edit: for MD implementation
    //   1. Add menu container div
    //   2. Use MaterializedCSS's card-panel class
    //   3. Use wulin-columnpicker class for customization

    function init() {
      grid.onHeaderContextMenu.subscribe(handleHeaderContextMenu);
      grid.onColumnsReordered.subscribe(updateColumnOrder);
      options = $.extend({}, defaults, options);

      // Ekohe Edit
      // $menu = $("").appendTo(document.body);
      $menu = $("
")
        .attr('id', grid.name + '-columnpicker')
        .appendTo(document.body);

      $menu.on("mouseleave", function (e) {
        $(this).fadeOut(options.fadeSpeed)
      });
      $menu.on("click", updateColumn);

      // Ekohe Add: bind the column pick event
      $menu.bind("click", handleColumnPick);
      bindGrid();
    }

    // Ekohe Add: Assign the picker itself to grid
    function bindGrid() {
      grid.picker = _self;
    }

    // Ekohe Add: Bind the column pick event
    function handleColumnPick(e, args) {
      _self.onColumnsPick.notify({});
    }

    function destroy() {
      grid.onHeaderContextMenu.unsubscribe(handleHeaderContextMenu);
      grid.onColumnsReordered.unsubscribe(updateColumnOrder);
      $menu.remove();
    }

    // Ekohe Edit:
    //  1. Add column-container div for MD implementation
    //  2. Add "Reset to defaults" feature
    //  3. Remove "Force Fit Columns" & "Synchronous Resizing" features

    function handleHeaderContextMenu(e, args) {
      e.preventDefault();
      $menu.empty();
      updateColumnOrder();
      columnCheckboxes = [];

      var $li, $input, $allNoneInput;

      // Ekohe Edit: Add column-container div for MD implementation
      var $columnContainer = $("
").appendTo($menu);

      // Append columns checkbox
      for (var i = 0; i < columns.length; i++) {
        $li = $("
").appendTo($columnContainer);
        // Ekohe Edit: MD implementation
        // $input = $("<input type='checkbox' />").data("column-id", columns[i].id);
        $input = $("<input type='checkbox' />")
                  .attr({id: "columnpicker_" + i, name: columns[i].field})
                  .appendTo($li);
        columnCheckboxes.push($input);

        if (grid.getColumnIndex(columns[i].id) != null) {
          $input.attr("checked", "checked")
                // Ekohe Add: MD implementation
                .addClass("filled-in");
        }

        // Ekohe Edit: MD implementation
        $("")
          .attr("for", "columnpicker_" + i)
          .text(columns[i].name)
          // .prepend($input);
          .appendTo($li);
      }

      // Ekohe Add
      // Addpend "Reset to defaults" checkbox
      $("
").appendTo($menu);
      $a = $("").appendTo($menu);
      $icon = $("replay").appendTo($a);
      $("").html("RESET TO DEFAULTS").appendTo($a);
      $a.on("click", function() {
        if (confirm('Are you sure that you want to reset the default view?')) {
          $.post('/wulin_master/grid_states_manages/reset_default',
                 { _method: 'PUT',
                   grid_name: grid.name,
                   user_id: user_id
                 },
                 function(data) {
                   if (data == 'ok') {
                     load_page(History.getState().url);
                   } else {
                     displayErrorMessage(data);
                   }
                 });
        }
      });

      // Ekohe Delete
      // Addpend "Force Fit Columns" checkbox
      // $("
").appendTo($menu);
      // $li = $("
").appendTo($menu);
      // $input = $("<input type='checkbox' />").data("option", "autoresize");
      // $("")
      //   .text("Force fit columns")
      //   .prepend($input)
      //   .appendTo($li);
      // if (grid.getOptions().forceFitColumns) {
      //   $input.attr("checked", "checked");
      // }

      // Ekohe Delete
      // Addpend "Synchronous Resizing" checkbox
      // $li = $("
").appendTo($menu);
      // $input = $("<input type='checkbox' />").data("option", "syncresize");
      // $("")
      //   .text("Synchronous resize")
      //   .prepend($input)
      //   .appendTo($li);
      // if (grid.getOptions().syncColumnCellResize) {
      //   $input.attr("checked", "checked");
      // }

      // Ekohe Edit: MD implementation
      $menu
        // .css("top", e.pageY - 10)
        .css("top", e.pageY + 10)
        .css("left", e.pageX - 10)
        // .css("max-height", $(window).height() - e.pageY -10)
        .fadeIn(options.fadeSpeed);
    }

    function updateColumnOrder() {
      // Because columns can be reordered, we have to update the `columns`
      // to reflect the new order, however we can't just take `grid.getColumns()`,
      // as it does not include columns currently hidden by the picker.
      // We create a new `columns` structure by leaving currently-hidden
      // columns in their original ordinal position and interleaving the results
      // of the current column sort.
      var current = grid.getColumns().slice(0);
      var ordered = new Array(columns.length);
      for (var i = 0; i < ordered.length; i++) {
        if ( grid.getColumnIndex(columns[i].id) === undefined ) {
          // If the column doesn't return a value from getColumnIndex,
          // it is hidden. Leave it in this position.
          ordered[i] = columns[i];
        } else {
          // Otherwise, grab the next visible column.
          ordered[i] = current.shift();
        }
      }
      columns = ordered;
    }

    // Ekohe Edit:
    //  1. Remove "Force Fit Columns" & "Synchronous Resizing" features

    function updateColumn(e) {
      // Ekohe Delete
      // "Force Fit Columns" checkbox hanlder
      // if ($(e.target).data("option") == "autoresize") {
      //   if (e.target.checked) {
      //     grid.setOptions({forceFitColumns:true});
      //     grid.autosizeColumns();
      //   } else {
      //     grid.setOptions({forceFitColumns:false});
      //   }
      //   return;
      // }

      // Ekohe Delete
      // "Synchronous Resizing" checkbox hanlder
      // if ($(e.target).data("option") == "syncresize") {
      //   if (e.target.checked) {
      //     grid.setOptions({syncColumnCellResize:true});
      //   } else {
      //     grid.setOptions({syncColumnCellResize:false});
      //   }
      //   return;
      // }

      // Ekohe Edit
      //   Use specifc class to identify columnpicker since e.target
      //   is recognized as label (should be input) here.
      //   TODO: Use e.target instead of using columnpicker element

      // // Column checkbox handler
      // if ($(e.target).is(":checkbox")) {
      //   var visibleColumns = [];
      //   $.each(columnCheckboxes, function (i, e) {
      //     if ($(this).is(":checked")) {
      //       visibleColumns.push(columns[i]);
      //     }
      //   });
      //
      //   if (!visibleColumns.length) {
      //     // Ekohe Edit
      //     // $(e.target).attr("checked", "checked");
      //     $(e.target).attr("checked", "checked")
      //                .addClass("filled-in");
      //     return;
      //   }
      //
      //   grid.setColumns(visibleColumns);
      // }

      var visibleColumns = [];
      $.each($('#' + grid.name + '-columnpicker li input'), function(i, e) {
        if ($(this).is(":checked")) {
          visibleColumns.push(columns[i]);
          $(this).addClass("filled-in");
        }
      });
      grid.setColumns(visibleColumns);
    }

    function getAllColumns() {
      return columns;
    }

    ///////////////////////////////////////////////////////////
    // Ekohe Add: New getter/setters

    function getMenu() {
      return $menu;
    }

    function getColumnCheckboxes() {
      return columnCheckboxes;
    }

    init();

    // Ekohe Modify: Use extend instead of return to set APIs to this
    $.extend(this, {
    // return {
      "onColumnsPick": new Slick.Event(),

      "destroy": destroy,
      "getAllColumns": getAllColumns
    });

  }

  // Slick.Controls.ColumnPicker
  $.extend(true, window, { Slick:{ Controls:{ ColumnPicker:SlickColumnPicker }}});
})(jQuery);
<commit_msg>BUG #71007 - MD implementation: reset default grid states dialog<commit_after>(function ($) {
  function SlickColumnPicker(columns, grid, user_id, options) {
    var $menu;
    var columnCheckboxes;
    var _self = this;   // Ekohe Add

    var defaults = {
      fadeSpeed:250
    };

    // Ekohe Edit: for MD implementation
    //   1. Add menu container div
    //   2. Use MaterializedCSS's card-panel class
    //   3. Use wulin-columnpicker class for customization

    function init() {
      grid.onHeaderContextMenu.subscribe(handleHeaderContextMenu);
      grid.onColumnsReordered.subscribe(updateColumnOrder);
      options = $.extend({}, defaults, options);

      // Ekohe Edit
      // $menu = $("").appendTo(document.body);
      $menu = $("
")
        .attr('id', grid.name + '-columnpicker')
        .appendTo(document.body);

      $menu.on("mouseleave", function (e) {
        $(this).fadeOut(options.fadeSpeed)
      });
      $menu.on("click", updateColumn);

      // Ekohe Add: bind the column pick event
      $menu.bind("click", handleColumnPick);
      bindGrid();
    }

    // Ekohe Add: Assign the picker itself to grid
    function bindGrid() {
      grid.picker = _self;
    }

    // Ekohe Add: Bind the column pick event
    function handleColumnPick(e, args) {
      _self.onColumnsPick.notify({});
    }

    function destroy() {
      grid.onHeaderContextMenu.unsubscribe(handleHeaderContextMenu);
      grid.onColumnsReordered.unsubscribe(updateColumnOrder);
      $menu.remove();
    }

    // Ekohe Edit:
    //  1. Add column-container div for MD implementation
    //  2. Add "Reset to defaults" feature
    //  3. Remove "Force Fit Columns" & "Synchronous Resizing" features

    function handleHeaderContextMenu(e, args) {
      e.preventDefault();
      $menu.empty();
      updateColumnOrder();
      columnCheckboxes = [];

      var $li, $input, $allNoneInput;

      // Ekohe Edit: Add column-container div for MD implementation
      var $columnContainer = $("
").appendTo($menu);

      // Append columns checkbox
      for (var i = 0; i < columns.length; i++) {
        $li = $("
").appendTo($columnContainer);
        // Ekohe Edit: MD implementation
        // $input = $("<input type='checkbox' />").data("column-id", columns[i].id);
        $input = $("<input type='checkbox' />")
                  .attr({id: "columnpicker_" + i, name: columns[i].field})
                  .appendTo($li);
        columnCheckboxes.push($input);

        if (grid.getColumnIndex(columns[i].id) != null) {
          $input.attr("checked", "checked")
                // Ekohe Add: MD implementation
                .addClass("filled-in");
        }

        // Ekohe Edit: MD implementation
        $("")
          .attr("for", "columnpicker_" + i)
          .text(columns[i].name)
          // .prepend($input);
          .appendTo($li);
      }

      // Ekohe Add
      // Addpend "Reset to defaults" checkbox
      $("
").appendTo($menu);
      $a = $("").appendTo($menu);
      $icon = $("replay").appendTo($a);
      $("").html("RESET TO DEFAULTS").appendTo($a);
      $a.on("click", function() {
        $('#confirm-modal').modal('open');
        $('#confirmed-btn').on('click', function() {
          $.post('/wulin_master/grid_states_manages/reset_default',
                 { _method: 'PUT',
                   grid_name: grid.name,
                   user_id: user_id
                 },
                 function(data) {
                   if (data == 'ok') {
                     load_page(History.getState().url);
                   } else {
                     displayErrorMessage(data);
                   }
                 });
          $('#confirm-modal').modal('close');
        })
      });

      // Ekohe Delete
      // Addpend "Force Fit Columns" checkbox
      // $("
").appendTo($menu);
      // $li = $("
").appendTo($menu);
      // $input = $("<input type='checkbox' />").data("option", "autoresize");
      // $("")
      //   .text("Force fit columns")
      //   .prepend($input)
      //   .appendTo($li);
      // if (grid.getOptions().forceFitColumns) {
      //   $input.attr("checked", "checked");
      // }

      // Ekohe Delete
      // Addpend "Synchronous Resizing" checkbox
      // $li = $("
").appendTo($menu);
      // $input = $("<input type='checkbox' />").data("option", "syncresize");
      // $("")
      //   .text("Synchronous resize")
      //   .prepend($input)
      //   .appendTo($li);
      // if (grid.getOptions().syncColumnCellResize) {
      //   $input.attr("checked", "checked");
      // }

      // Ekohe Edit: MD implementation
      $menu
        // .css("top", e.pageY - 10)
        .css("top", e.pageY + 10)
        .css("left", e.pageX - 10)
        // .css("max-height", $(window).height() - e.pageY -10)
        .fadeIn(options.fadeSpeed);
    }

    function updateColumnOrder() {
      // Because columns can be reordered, we have to update the `columns`
      // to reflect the new order, however we can't just take `grid.getColumns()`,
      // as it does not include columns currently hidden by the picker.
      // We create a new `columns` structure by leaving currently-hidden
      // columns in their original ordinal position and interleaving the results
      // of the current column sort.
      var current = grid.getColumns().slice(0);
      var ordered = new Array(columns.length);
      for (var i = 0; i < ordered.length; i++) {
        if ( grid.getColumnIndex(columns[i].id) === undefined ) {
          // If the column doesn't return a value from getColumnIndex,
          // it is hidden. Leave it in this position.
          ordered[i] = columns[i];
        } else {
          // Otherwise, grab the next visible column.
          ordered[i] = current.shift();
        }
      }
      columns = ordered;
    }

    // Ekohe Edit:
    //  1. Remove "Force Fit Columns" & "Synchronous Resizing" features

    function updateColumn(e) {
      // Ekohe Delete
      // "Force Fit Columns" checkbox hanlder
      // if ($(e.target).data("option") == "autoresize") {
      //   if (e.target.checked) {
      //     grid.setOptions({forceFitColumns:true});
      //     grid.autosizeColumns();
      //   } else {
      //     grid.setOptions({forceFitColumns:false});
      //   }
      //   return;
      // }

      // Ekohe Delete
      // "Synchronous Resizing" checkbox hanlder
      // if ($(e.target).data("option") == "syncresize") {
      //   if (e.target.checked) {
      //     grid.setOptions({syncColumnCellResize:true});
      //   } else {
      //     grid.setOptions({syncColumnCellResize:false});
      //   }
      //   return;
      // }

      // Ekohe Edit
      //   Use specifc class to identify columnpicker since e.target
      //   is recognized as label (should be input) here.
      //   TODO: Use e.target instead of using columnpicker element

      // // Column checkbox handler
      // if ($(e.target).is(":checkbox")) {
      //   var visibleColumns = [];
      //   $.each(columnCheckboxes, function (i, e) {
      //     if ($(this).is(":checked")) {
      //       visibleColumns.push(columns[i]);
      //     }
      //   });
      //
      //   if (!visibleColumns.length) {
      //     // Ekohe Edit
      //     // $(e.target).attr("checked", "checked");
      //     $(e.target).attr("checked", "checked")
      //                .addClass("filled-in");
      //     return;
      //   }
      //
      //   grid.setColumns(visibleColumns);
      // }

      var visibleColumns = [];
      $.each($('#' + grid.name + '-columnpicker li input'), function(i, e) {
        if ($(this).is(":checked")) {
          visibleColumns.push(columns[i]);
          $(this).addClass("filled-in");
        }
      });
      grid.setColumns(visibleColumns);
    }

    function getAllColumns() {
      return columns;
    }

    ///////////////////////////////////////////////////////////
    // Ekohe Add: New getter/setters

    function getMenu() {
      return $menu;
    }

    function getColumnCheckboxes() {
      return columnCheckboxes;
    }

    init();

    // Ekohe Modify: Use extend instead of return to set APIs to this
    $.extend(this, {
    // return {
      "onColumnsPick": new Slick.Event(),

      "destroy": destroy,
      "getAllColumns": getAllColumns
    });

  }

  // Slick.Controls.ColumnPicker
  $.extend(true, window, { Slick:{ Controls:{ ColumnPicker:SlickColumnPicker }}});
})(jQuery);
<|endoftext|>


<commit_before>// Amara, universalsubtitles.org
//
// Copyright (C) 2013 Participatory Culture Foundation
//
// 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.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

(function() {

    var root = this;

    var VideoController = function($scope, SubtitleStorage) {
        /**
         * Responsible for initializing the video and all video controls.
         * @param $scope
         * @param SubtitleStorage
         * @constructor
         */

        // The Popcorn instance.
        //
        // For now, make sure we force controls.
        $scope.pop = window.Popcorn.smart('#video', SubtitleStorage.getVideoURL() + '&controls=1');

        $scope.playChunk = function(start, duration) {
            // Play a specified amount of time in a video, beginning at 'start',
            // and then pause.

            // Pause the video, first.
            $scope.pop.play();

            // Remove any existing cues that may interfere.
            var trackEvents = $scope.pop.getTrackEvents();
            for (var i = 0; i < trackEvents.length; i++) {
                $scope.pop.removeTrackEvent(trackEvents[i].id);
            }

            // Set the new start time.
            $scope.pop.currentTime(start);

            // Set a new cue to pause the video at the end of the chunk.
            $scope.pop.cue(start + duration, function() {
                $scope.pop.pause();
            });

            // Play the video.
            $scope.pop.play();

        };
    };

    root.VideoController = VideoController;

}).call(this);
<commit_msg>Fix non-positive-integer start times for playChunk()<commit_after>// Amara, universalsubtitles.org
//
// Copyright (C) 2013 Participatory Culture Foundation
//
// 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.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

(function() {

    var root = this;

    var VideoController = function($scope, SubtitleStorage) {
        /**
         * Responsible for initializing the video and all video controls.
         * @param $scope
         * @param SubtitleStorage
         * @constructor
         */

        // The Popcorn instance.
        //
        // For now, make sure we force controls.
        $scope.pop = window.Popcorn.smart('#video', SubtitleStorage.getVideoURL() + '&controls=1');

        $scope.playChunk = function(start, duration) {
            // Play a specified amount of time in a video, beginning at 'start',
            // and then pause.

            // Pause the video, first.
            $scope.pop.play();

            // Remove any existing cues that may interfere.
            var trackEvents = $scope.pop.getTrackEvents();
            for (var i = 0; i < trackEvents.length; i++) {
                $scope.pop.removeTrackEvent(trackEvents[i].id);
            }

            if (start < 0) {
                start = 0;
            }

            // Set the new start time.
            $scope.pop.currentTime(start);

            // Set a new cue to pause the video at the end of the chunk.
            $scope.pop.cue(start + duration, function() {
                $scope.pop.pause();
            });

            // Play the video.
            $scope.pop.play();

        };
    };

    root.VideoController = VideoController;

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