<commit_before>/*!
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://www.osedu.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

define(['jquery', 'underscore', 'oae.core', '//www.google.com/recaptcha/api/js/recaptcha_ajax.js'], function($, _, oae) {

    return function(uid, showSettings) {

        // Check whether or not the register form should show a recaptcha challenge
        var recaptchaEnabled = oae.api.config.getValue('oae-principals', 'recaptcha', 'enabled');

        /**
         * Set up a reCaptcha container that will used to verify
         * that the current user is a real human
         */
        var setUpReCaptcha = function() {
            if (recaptchaEnabled) {
                var captchaContainer = $('#register-captcha-container')[0];
                Recaptcha.create(oae.api.config.getValue('oae-principals', 'recaptcha', 'publicKey'), captchaContainer, {theme: 'clean'});
            }
        };

        /**
         * Show a validation message for reCaptcha
         */
        var hideRecaptchaError = function() {
            // Remove the aria attributes on the main recaptcha input field
            $('#recaptcha-response-field').removeAttr('aria-invalid aria-describedby');
            $('#register-captcha-error').hide();
            $('#register-captcha').removeClass('error');
        };

        /**
         * Show a validation message for reCaptcha
         */
        var showRecaptchaError = function() {
            // Set the aria attributes on the main recaptcha input field
            $('#recaptcha_response_field').attr({
                'aria-invalid': 'true',
                'aria-describedby': 'register-captcha-error'
            });
            $('#register-captcha').addClass('error');
            $('#register-captcha-error').show();
        };

        /**
         * Set up the check that verifies whether or not the entered username is still availble. This will
         * be done every time the user changes the username
         */
        var setUpUsernameCheck = function() {
            // Keep track of the previously entered username, so we don't send
            // unneccesary requests when the username hasn't actually changed
            var previousUsername = '';

            $('#register-username').on('keyup blur', function() {
                var username = $.trim($('#register-username').val());
                if (previousUsername !== username) {
                    previousUsername = username;
                    // Make sure that the username is acceptable
                    if (username.length > 2 && username.indexOf(' ') === -1) {
                        isUserNameAvailable(function(available) {
                            // Show the available icon if the username is available, otherwise show the unavailable icon
                            available ? $('#register-username').addClass('register-username-available') : $('#register-username').removeClass('register-username-available');
                        });
                    } else {
                        $('#register-username').removeClass('register-username-available');
                    }
                }
            });
        };

        /**
         * Verify whether or not the entered username already exists as a login id on the
         * current tenant. This will happen synchronously when it is part of the form
         * validation
         *
         * @param  {Function}   [callback]              Standard callback function.
         * @param  {Boolean}    [callback.available]    Whether or not the username is available
         * @return {Boolean}                            When no callback is provided, this function will be synchronous and will return whether or not the username is available
         */
        var isUserNameAvailable = function(callback) {
            // If we reach this point, we have a username in a valid format.
            var username = $.trim($('#register-username').val());

            // We check if the userid is still available on the current tenant.
            // We expect a 200 if it already exists and a 404 if it doesn't exist yet.
            var available = false;
            $.ajax({
                url: '/api/auth/exists/' + username,
                async: callback ? true : false,
                success: function() {
                    // The username already exists
                    if (callback) {
                        callback(false);
                    }
                },
                error: function(xhr, textStatus, thrownError) {
                    // The username is still available
                    if (callback) {
                        callback(true);
                    } else {
                        available = true;
                    }
                }
            });
            return available;
        };

        /**
         * Set up the validation on the register form, including the error messages
         */
        setUpValidation = function() {
            var validateOpts = {
                'rules': {
                    'username': {
                        'minlength': 3,
                        'nospaces': true,
                        'validchars': true,
                        'validusername': true
                    },
                    'password': {
                        'minlength': 6
                    },
                    'password_repeat': {
                        'equalTo': '#register-password'
                    }
                },
                'messages': {
                    'firstName': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_FIRST_NAME__'),
                    'lastName': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_LAST_NAME__'),
                    'email': {
                        'required': oae.api.i18n.translate('__MSG__PLEASE_ENTER_A_VALID_EMAIL_ADDRESS__'),
                        'email': oae.api.i18n.translate('__MSG__THIS_IS_AN_INVALID_EMAIL_ADDRESS__'),
                    },
                    'username': {
                        'required': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_USERNAME__'),
                        'minlength': oae.api.i18n.translate('__MSG__THE_USERNAME_SHOULD_BE_AT_LEAST_THREE_CHARACTERS_LONG__'),
                        'nospaces': oae.api.i18n.translate('__MSG__THE_USERNAME_SHOULDNT_CONTAIN_SPACES__')
                    },
                    'password': {
                        'required': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_PASSWORD__'),
                        'minlength': oae.api.i18n.translate('__MSG__YOUR_PASSWORD_SHOULD_BE_AT_LEAST_SIX_CHARACTERS_LONG__')
                    },
                    'password_repeat': {
                        'required': oae.api.i18n.translate('__MSG__PLEASE_REPEAT_YOUR_PASSWORD__'),
                        'passwordmatch': oae.api.i18n.translate('__MSG__THIS_PASSWORD_DOES_NOT_MATCH_THE_FIRST_ONE__')
                    }
                },
                'methods': {
                    'validusername': {
                        'method': function(value, element) {
                            return this.optional(element) || isUserNameAvailable();
                        },
                        'text': oae.api.i18n.translate('__MSG__THIS_USERNAME_HAS_ALREADY_BEEN_TAKEN__')
                    },
                    'validchars': {
                        'method': function(value, element) {
                            return this.optional(element) || !(/[\<\>\\\/{}\[\]!@#\$%^&\*,:]+/i.test(value));
                        },
                        'text': oae.api.i18n.translate('__MSG__CREATE_ACCOUNT_INVALIDCHAR__')
                    }
                },
                'submitHandler': createUser
            };
            oae.api.util.validation().validate($('#register-form'), validateOpts);
        };

        /**
         * Create the new user. This will be called after validation has succeeded
         */
        var createUser = function() {
            // Hide the recaptcha validation
            hideRecaptchaError();

            // Get the form values
            var values = $('#register-form').serializeObject();
            // Collect the recaptcha values
            if (recaptchaEnabled) {
                values['recaptchaChallenge'] = Recaptcha.get_challenge();
                values['recaptchaResponse'] = Recaptcha.get_response();
            }

            // Disable the register button during creation, so it can't be clicked multiple times
            $('button, input').attr('disabled', 'disabled');

            // Create the user
            var displayName = values.firstName + ' ' + values.lastName;
            oae.api.user.createUser(values.username, values.password, displayName, null, values.recaptchaChallenge, values.recaptchaResponse, function(err, createdUser) {
                if (!err) {
                    oae.api.authentication.login(values.username, values.password, function() {
                        // Relocate to the user home space
                        document.location = '/me?welcome=true';
                    });
                } else {
                    // Refresh recaptcha
                    if (recaptchaEnabled) {
                        Recaptcha.reload();
                        showRecaptchaError();
                    }
                    // Unlock the register button again
                    $('button, input').removeAttr('disabled');
                }
            });
        };

        /**
         * Initialize the register modal dialog
         */
        var initRegister = function() {
            $(document).on('click', '.oae-trigger-register', function() {
                // Trigger the modal dialog
                $('#register-container').modal();
            });
        };

        initRegister();
        setUpReCaptcha();
        setUpValidation();
        setUpUsernameCheck();

    };
});
<commit_msg>Fixed i18n issues<commit_after>/*!
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://www.osedu.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

define(['jquery', 'underscore', 'oae.core', '//www.google.com/recaptcha/api/js/recaptcha_ajax.js'], function($, _, oae) {

    return function(uid, showSettings) {

        // Check whether or not the register form should show a recaptcha challenge
        var recaptchaEnabled = oae.api.config.getValue('oae-principals', 'recaptcha', 'enabled');

        /**
         * Set up a reCaptcha container that will used to verify
         * that the current user is a real human
         */
        var setUpReCaptcha = function() {
            if (recaptchaEnabled) {
                var captchaContainer = $('#register-captcha-container')[0];
                Recaptcha.create(oae.api.config.getValue('oae-principals', 'recaptcha', 'publicKey'), captchaContainer, {theme: 'clean'});
            }
        };

        /**
         * Show a validation message for reCaptcha
         */
        var hideRecaptchaError = function() {
            // Remove the aria attributes on the main recaptcha input field
            $('#recaptcha-response-field').removeAttr('aria-invalid aria-describedby');
            $('#register-captcha-error').hide();
            $('#register-captcha').removeClass('error');
        };

        /**
         * Show a validation message for reCaptcha
         */
        var showRecaptchaError = function() {
            // Set the aria attributes on the main recaptcha input field
            $('#recaptcha_response_field').attr({
                'aria-invalid': 'true',
                'aria-describedby': 'register-captcha-error'
            });
            $('#register-captcha').addClass('error');
            $('#register-captcha-error').show();
        };

        /**
         * Set up the check that verifies whether or not the entered username is still availble. This will
         * be done every time the user changes the username
         */
        var setUpUsernameCheck = function() {
            // Keep track of the previously entered username, so we don't send
            // unneccesary requests when the username hasn't actually changed
            var previousUsername = '';

            $('#register-username').on('keyup blur', function() {
                var username = $.trim($('#register-username').val());
                if (previousUsername !== username) {
                    previousUsername = username;
                    // Make sure that the username is acceptable
                    if (username.length > 2 && username.indexOf(' ') === -1) {
                        isUserNameAvailable(function(available) {
                            // Show the available icon if the username is available, otherwise show the unavailable icon
                            available ? $('#register-username').addClass('register-username-available') : $('#register-username').removeClass('register-username-available');
                        });
                    } else {
                        $('#register-username').removeClass('register-username-available');
                    }
                }
            });
        };

        /**
         * Verify whether or not the entered username already exists as a login id on the
         * current tenant. This will happen synchronously when it is part of the form
         * validation
         *
         * @param  {Function}   [callback]              Standard callback function.
         * @param  {Boolean}    [callback.available]    Whether or not the username is available
         * @return {Boolean}                            When no callback is provided, this function will be synchronous and will return whether or not the username is available
         */
        var isUserNameAvailable = function(callback) {
            // If we reach this point, we have a username in a valid format.
            var username = $.trim($('#register-username').val());

            // We check if the userid is still available on the current tenant.
            // We expect a 200 if it already exists and a 404 if it doesn't exist yet.
            var available = false;
            $.ajax({
                url: '/api/auth/exists/' + username,
                async: callback ? true : false,
                success: function() {
                    // The username already exists
                    if (callback) {
                        callback(false);
                    }
                },
                error: function(xhr, textStatus, thrownError) {
                    // The username is still available
                    if (callback) {
                        callback(true);
                    } else {
                        available = true;
                    }
                }
            });
            return available;
        };

        /**
         * Set up the validation on the register form, including the error messages
         */
        setUpValidation = function() {
            var validateOpts = {
                'rules': {
                    'username': {
                        'minlength': 3,
                        'nospaces': true,
                        'validchars': true,
                        'validusername': true
                    },
                    'password': {
                        'minlength': 6
                    },
                    'password_repeat': {
                        'equalTo': '#register-password'
                    }
                },
                'messages': {
                    'firstName': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_FIRST_NAME__', 'register'),
                    'lastName': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_LAST_NAME__', 'register'),
                    'email': {
                        'required': oae.api.i18n.translate('__MSG__PLEASE_ENTER_A_VALID_EMAIL_ADDRESS__', 'register'),
                        'email': oae.api.i18n.translate('__MSG__THIS_IS_AN_INVALID_EMAIL_ADDRESS__', 'register'),
                    },
                    'username': {
                        'required': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_USERNAME__'),
                        'minlength': oae.api.i18n.translate('__MSG__THE_USERNAME_SHOULD_BE_AT_LEAST_THREE_CHARACTERS_LONG__', 'register'),
                        'nospaces': oae.api.i18n.translate('__MSG__THE_USERNAME_SHOULDNT_CONTAIN_SPACES__', 'register')
                    },
                    'password': {
                        'required': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_PASSWORD__'),
                        'minlength': oae.api.i18n.translate('__MSG__YOUR_PASSWORD_SHOULD_BE_AT_LEAST_SIX_CHARACTERS_LONG__', 'register')
                    },
                    'password_repeat': {
                        'required': oae.api.i18n.translate('__MSG__PLEASE_REPEAT_YOUR_PASSWORD__', 'register'),
                        'passwordmatch': oae.api.i18n.translate('__MSG__THIS_PASSWORD_DOES_NOT_MATCH_THE_FIRST_ONE__', 'register')
                    }
                },
                'methods': {
                    'validusername': {
                        'method': function(value, element) {
                            return this.optional(element) || isUserNameAvailable();
                        },
                        'text': oae.api.i18n.translate('__MSG__THIS_USERNAME_HAS_ALREADY_BEEN_TAKEN__', 'register')
                    },
                    'validchars': {
                        'method': function(value, element) {
                            return this.optional(element) || !(/[\<\>\\\/{}\[\]!@#\$%^&\*,:]+/i.test(value));
                        },
                        'text': oae.api.i18n.translate('__MSG__CREATE_ACCOUNT_INVALIDCHAR__', 'register')
                    }
                },
                'submitHandler': createUser
            };
            oae.api.util.validation().validate($('#register-form'), validateOpts);
        };

        /**
         * Create the new user. This will be called after validation has succeeded
         */
        var createUser = function() {
            // Hide the recaptcha validation
            hideRecaptchaError();

            // Get the form values
            var values = $('#register-form').serializeObject();
            // Collect the recaptcha values
            if (recaptchaEnabled) {
                values['recaptchaChallenge'] = Recaptcha.get_challenge();
                values['recaptchaResponse'] = Recaptcha.get_response();
            }

            // Disable the register button during creation, so it can't be clicked multiple times
            $('button, input').attr('disabled', 'disabled');

            // Create the user
            var displayName = values.firstName + ' ' + values.lastName;
            oae.api.user.createUser(values.username, values.password, displayName, null, values.recaptchaChallenge, values.recaptchaResponse, function(err, createdUser) {
                if (!err) {
                    oae.api.authentication.login(values.username, values.password, function() {
                        // Relocate to the user home space
                        document.location = '/me?welcome=true';
                    });
                } else {
                    // Refresh recaptcha
                    if (recaptchaEnabled) {
                        Recaptcha.reload();
                        showRecaptchaError();
                    }
                    // Unlock the register button again
                    $('button, input').removeAttr('disabled');
                }
            });
        };

        /**
         * Initialize the register modal dialog
         */
        var initRegister = function() {
            $(document).on('click', '.oae-trigger-register', function() {
                // Trigger the modal dialog
                $('#register-container').modal();
            });
        };

        initRegister();
        setUpReCaptcha();
        setUpValidation();
        setUpUsernameCheck();

    };
});
<|endoftext|>


<commit_before>/**
 * This kind provide a widget to tune project properties (phonegap
 * stuff included).
 *
 * By default, this widget is tuned for project modification.  In case
 * of project *creation*, the method setup_create must be called after
 * construction.
 */
enyo.kind({
	name: "ProjectProperties",
	classes: "enyo-unselectable",
	fit: true,
	events: {
		onCustomConfigProject: "",
		onSaveGeneratedXml: "",
		onCanceled: "",
	},
	createMode: true,

	components: [
		{kind: "onyx.RadioGroup", onActivate: "switchDrawers", name: "thumbnail", components: [
			{content: "Project", active: true, attributes: {title: 'project attributes...'}},
			{content: "PhoneGap", attributes: {title: 'phonegap build parameters...'}}
		]},
		{name: "projectDrawer", kind: "onyx.Drawer", open:true, components: [
			{content: "Project", tag:"h2"},
			{tag: 'table', components: [
				{tag: "tr" , components: [
					 {tag: "td" , content: "Name: "},
					 {tag: 'td', components:[
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", defaultFocus: true, name: "projectName"}
						  ]}
					 ]},
					 {tag: 'td', content: "Title: "},
					 {tag: "td" , components: [
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", defaultFocus: true, name: "projectTitle"}
						   ]}
					  ]}
				]},
				{tag: "tr" , components: [
					 {tag: "td" , content: "Version: "},
					 {tag: 'td', components:[
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", defaultFocus: true, name: "projectVersion"}
						  ]}
					 ]},
					 {tag: 'td', content: "Id: "},
					 {tag: "td" , components: [
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", defaultFocus: true, name: "projectId",
								attributes: {title: "Application ID in reverse domain-name format: com.example.apps.myapp"}}
						   ]}
					  ]}
				]},
				{tag: "tr" , name:'directoryEntry', canGenerate:false, components: [
					 {tag: "td", content: "Directory: "},
					 {tag: 'td', attributes: {colspan: 3}, content: "", name: "projectDirectory" }
				]}
			]}
		]},
		// FIXME: use true for debug
		{name: "phoneGapDrawer", kind: "onyx.Drawer", open: false, components: [
			{content: "PhoneGap", tag:"h2"},
			{kind: "onyx.ToggleButton", name: 'pgConfEnabled', onContent: "enabled", offContent: "disabled"},
			{tag: 'table', attributes: {'class': 'ares_projectView_table'}, components: [
				{tag: "tr" , components: [
					 {tag: "td" , content: "AppId: "},
					 {tag: 'td', attributes: {colspan: 3}, components:[
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", name: "pgConfId", placeholder: "com.example.myapp",
								attributes: {title: "unique identifier, assigned by build.phonegap.com"}
							   }
						   ]}
					 ]}
				]},
				{tag: "tr" , components: [
					 {tag: 'td', content: "PhoneGap targets", attributes: {colspan: 3}}
				]},
				{tag: "tr" , components: [
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'androidTarget', onContent: "Android", offContent: "Android"}
					]},
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'iosTarget', onContent: "Ios", offContent: "Ios"}
					]},
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'winphoneTarget', onContent: "Winphone", offContent: "Winphone"}
					]}
				]},
				{tag: "tr" , components: [
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'blackberryTarget', onContent: "Blackberry", offContent: "Blackberry"}
					]},
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'webosTarget',onContent: "Webos", offContent: "Webos"}
					]}
				]}
			]}
		]},

		// FIXME: there should be an HTML/CSS way to avoid using FittableStuff...
		{kind: "FittableRows", style: "margin-top: 10px; width: 100%", fit: true, components: [
			{kind: "onyx.Button", classes: "onyx-negative", content: "Cancel", ontap: "doCanceled"},
			{name: "ok", kind: "onyx.Button", classes: "onyx-affirmative", content: "OK", ontap: "createProject"}
		]},

		{kind: "Ares.ErrorPopup", name: "errorPopup", msg: "unknown error"}
	],

	debug: false,

	/**
	 * Tune the widget for project creation
	 */
	setup_create: function() {
		this.$.ok.setDisabled(true) ;
		this.$.directoryEntry.show() ;
	},

	/**
	 * close one drawer and open the other depending on which radio button was tapped
	 */
	switchDrawers: function(inSender, inEvent) {
		if (inEvent.originator.active === true ) {
			if (inEvent.originator.getContent() === "Project") {
				this.$.projectDrawer.setOpen(true) ;
				this.$.phoneGapDrawer.setOpen(false) ;
			}
			else {
				this.$.projectDrawer.setOpen(false) ;
				this.$.phoneGapDrawer.setOpen(true) ;
			}
		}
	},

	/**
	 * pre-fill the widget with configuration data
	 * @param {Object} config is configuration data (typically from project.json)
	 *  can be a json string or an object.
	 */
	preFill: function(inData) {
		this.log(inData) ;
		var config = typeof inData === 'object' ? inData : JSON.parse(inData) ;
		var pgConf ;
		var pgTarget ;

		this.$.projectId.setValue(config.id);
		this.$.projectVersion.setValue(config.version);
		this.$.projectName.setValue(config.name);
		this.$.projectTitle.setValue(config.title);

		if (config.build && config.build.phonegap) {
		    pgConf = config.build.phonegap ;
			this.$.pgConfEnabled.setValue(pgConf.enabled);
			this.$.pgConfId.setValue(pgConf.appId);

			if (pgConf.targets) {
				for (pgTarget in pgConf.targets ) {
					this.$[ pgTarget + 'Target' ].setContent(pgConf.targets[pgTarget]) ;
				}
			}
		}
		return this ;
	},

	confirmTap: function(inSender, inEvent) {
		// retrieve modified values
		var obj = {
			name: this.$.projectName.getValue(),
			id: this.$.projectId.getValue(),
			title: this.$.projectTitle.getValue(),
			description: this.$.projectDescription.getValue()
		}
		this.doCustomConfigProject(obj);
		// handled here (don't bubble)
		return true;
	}
});

enyo.kind({
	name: "ProjectPropertiesPopup",
	kind: "onyx.Popup",
	modal: true, centered: true, floating: true, autoDismiss: false,
	handlers: {
		onCanceled: "hide"
	},
	components: [
		{kind: "ProjectProperties"}
	],
	reset: function() {
		this.$.projectProperties.reset();
	},
	preFillConfig: function(inData) {
		this.$.projectProperties.preFill(inData);
		return this ;
	},
});
<commit_msg>ENYO-1222: renamed onCanceled to onCancel to be consistent with other kinds<commit_after>/**
 * This kind provide a widget to tune project properties (phonegap
 * stuff included).
 *
 * By default, this widget is tuned for project modification.  In case
 * of project *creation*, the method setup_create must be called after
 * construction.
 */
enyo.kind({
	name: "ProjectProperties",
	classes: "enyo-unselectable",
	fit: true,
	events: {
		onCustomConfigProject: "",
		onSaveGeneratedXml: "",
		onCancel: "",
	},
	createMode: true,

	components: [
		{kind: "onyx.RadioGroup", onActivate: "switchDrawers", name: "thumbnail", components: [
			{content: "Project", active: true, attributes: {title: 'project attributes...'}},
			{content: "PhoneGap", attributes: {title: 'phonegap build parameters...'}}
		]},
		{name: "projectDrawer", kind: "onyx.Drawer", open:true, components: [
			{content: "Project", tag:"h2"},
			{tag: 'table', components: [
				{tag: "tr" , components: [
					 {tag: "td" , content: "Name: "},
					 {tag: 'td', components:[
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", defaultFocus: true, name: "projectName"}
						  ]}
					 ]},
					 {tag: 'td', content: "Title: "},
					 {tag: "td" , components: [
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", defaultFocus: true, name: "projectTitle"}
						   ]}
					  ]}
				]},
				{tag: "tr" , components: [
					 {tag: "td" , content: "Version: "},
					 {tag: 'td', components:[
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", defaultFocus: true, name: "projectVersion"}
						  ]}
					 ]},
					 {tag: 'td', content: "Id: "},
					 {tag: "td" , components: [
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", defaultFocus: true, name: "projectId",
								attributes: {title: "Application ID in reverse domain-name format: com.example.apps.myapp"}}
						   ]}
					  ]}
				]},
				{tag: "tr" , name:'directoryEntry', canGenerate:false, components: [
					 {tag: "td", content: "Directory: "},
					 {tag: 'td', attributes: {colspan: 3}, content: "", name: "projectDirectory" }
				]}
			]}
		]},
		// FIXME: use true for debug
		{name: "phoneGapDrawer", kind: "onyx.Drawer", open: false, components: [
			{content: "PhoneGap", tag:"h2"},
			{kind: "onyx.ToggleButton", name: 'pgConfEnabled', onContent: "enabled", offContent: "disabled"},
			{tag: 'table', attributes: {'class': 'ares_projectView_table'}, components: [
				{tag: "tr" , components: [
					 {tag: "td" , content: "AppId: "},
					 {tag: 'td', attributes: {colspan: 3}, components:[
						  {kind: "onyx.InputDecorator", components: [
							   {kind: "Input", name: "pgConfId", placeholder: "com.example.myapp",
								attributes: {title: "unique identifier, assigned by build.phonegap.com"}
							   }
						   ]}
					 ]}
				]},
				{tag: "tr" , components: [
					 {tag: 'td', content: "PhoneGap targets", attributes: {colspan: 3}}
				]},
				{tag: "tr" , components: [
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'androidTarget', onContent: "Android", offContent: "Android"}
					]},
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'iosTarget', onContent: "Ios", offContent: "Ios"}
					]},
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'winphoneTarget', onContent: "Winphone", offContent: "Winphone"}
					]}
				]},
				{tag: "tr" , components: [
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'blackberryTarget', onContent: "Blackberry", offContent: "Blackberry"}
					]},
					{tag: "td" , components: [
						  {kind: "onyx.ToggleButton", name: 'webosTarget',onContent: "Webos", offContent: "Webos"}
					]}
				]}
			]}
		]},

		// FIXME: there should be an HTML/CSS way to avoid using FittableStuff...
		{kind: "FittableRows", style: "margin-top: 10px; width: 100%", fit: true, components: [
			{kind: "onyx.Button", classes: "onyx-negative", content: "Cancel", ontap: "doCancel"},
			{name: "ok", kind: "onyx.Button", classes: "onyx-affirmative", content: "OK", ontap: "createProject"}
		]},

		{kind: "Ares.ErrorPopup", name: "errorPopup", msg: "unknown error"}
	],

	debug: false,

	/**
	 * Tune the widget for project creation
	 */
	setup_create: function() {
		this.$.ok.setDisabled(true) ;
		this.$.directoryEntry.show() ;
	},

	/**
	 * close one drawer and open the other depending on which radio button was tapped
	 */
	switchDrawers: function(inSender, inEvent) {
		if (inEvent.originator.active === true ) {
			if (inEvent.originator.getContent() === "Project") {
				this.$.projectDrawer.setOpen(true) ;
				this.$.phoneGapDrawer.setOpen(false) ;
			}
			else {
				this.$.projectDrawer.setOpen(false) ;
				this.$.phoneGapDrawer.setOpen(true) ;
			}
		}
	},

	/**
	 * pre-fill the widget with configuration data
	 * @param {Object} config is configuration data (typically from project.json)
	 *  can be a json string or an object.
	 */
	preFill: function(inData) {
		this.log(inData) ;
		var config = typeof inData === 'object' ? inData : JSON.parse(inData) ;
		var pgConf ;
		var pgTarget ;

		this.$.projectId.setValue(config.id);
		this.$.projectVersion.setValue(config.version);
		this.$.projectName.setValue(config.name);
		this.$.projectTitle.setValue(config.title);

		if (config.build && config.build.phonegap) {
		    pgConf = config.build.phonegap ;
			this.$.pgConfEnabled.setValue(pgConf.enabled);
			this.$.pgConfId.setValue(pgConf.appId);

			if (pgConf.targets) {
				for (pgTarget in pgConf.targets ) {
					this.$[ pgTarget + 'Target' ].setContent(pgConf.targets[pgTarget]) ;
				}
			}
		}
		return this ;
	},

	confirmTap: function(inSender, inEvent) {
		// retrieve modified values
		var obj = {
			name: this.$.projectName.getValue(),
			id: this.$.projectId.getValue(),
			title: this.$.projectTitle.getValue(),
			description: this.$.projectDescription.getValue()
		}
		this.doCustomConfigProject(obj);
		// handled here (don't bubble)
		return true;
	}
});

enyo.kind({
	name: "ProjectPropertiesPopup",
	kind: "onyx.Popup",
	modal: true, centered: true, floating: true, autoDismiss: false,
	handlers: {
		onCancel: "hide"
	},
	components: [
		{kind: "ProjectProperties"}
	],
	reset: function() {
		this.$.projectProperties.reset();
	},
	preFillConfig: function(inData) {
		this.$.projectProperties.preFill(inData);
		return this ;
	},
});
<|endoftext|>


<commit_before>var path = require('path');
var Discord = require('discord.js');

function TheAwesomeBot(token, discord_opt) {
  this.token = token;
  this.client = new Discord.Client(discord_opt || { autoReconnect: true });
  this.settings = require('./settings.json');
  this.commands = {};
  this.usageList = '';

  // store the RE as they're expensive to create
  this.cmd_re = new RegExp(`^${this.settings.bot_cmd}[\\s]+([^ ]*)[\\s]*(.*)[\\s]*`, 'i');
};

TheAwesomeBot.prototype.onMessage = function () {
  var instance = this;
  return (function (message) {
    // don't respond to own messages
    if (instance.client.user.username === message.author.username)
      return;

    // check if message is a command
    var cmd_match = message.cleanContent.match(instance.cmd_re);

    // not a known command
    if (!cmd_match || Object.keys(instance.commands).indexOf(cmd_match[1]) === -1) {

      if (message.content.match(new RegExp(`^${instance.settings.bot_cmd}[\\s]*( .*)?$`, 'i'))) {
        var helpText = 'maybe try these valid commands? *kthnxbye!*\n\n```';
        helpText += instance.usageList;
        helpText += '```';
        instance.client.reply(message, helpText);
      }

      return;
    }

    // process commands
    var cmd = cmd_match[1];
    var cmd_args = cmd_match[2].trim();

    instance.commands[cmd].run(instance, message, cmd_args);
  });
};

TheAwesomeBot.prototype.onReady = function () {
  var instance = this;
  return (function () {
    console.log('\nConnected to discord server!');

    console.log('Running initializations...');
    for (var cmd in instance.commands) {
      if (typeof instance.commands[cmd].init == 'function') {
        instance.commands[cmd].init(instance);
      }
    };
  });
};

TheAwesomeBot.prototype.serverNewMember = function () {
  var instance = this;
  return (function (server, user) {
    instance.client.sendMessage(user, instance.usageList);
  });
};

TheAwesomeBot.prototype.onDisconnected = function () {
  return (function () {
    console.warn('Bot has been disconnected from server...');
  });
};

TheAwesomeBot.prototype.onError = function () {
  return (function (err) {
    console.error('error: ', e);
    console.error(e.trace);
  });
};

TheAwesomeBot.prototype.loadCommands = function (cmdList) {
  var instance = this;
  instance.usageList = '';
  cmdList.forEach(cmd => {
    var fullpath = path.join(__dirname, 'commands', cmd, `${cmd}.js`);
    var script = require(fullpath);
    instance.commands[cmd] = script;

    var usageObj = script.usage;
    var usageStrs = [];
    if (Array.isArray(usageObj)) {
      usageObj.forEach(u => usageStrs.push(u));
    } else {
      usageStrs.push(usageObj.toString());
    }

    usageStrs.forEach(u => {
      instance.usageList += ` - ${instance.settings.bot_cmd} ${u}`
    });
  });
};

TheAwesomeBot.prototype.init = function () {
  // load commands
  console.log('Loading commands...');
  this.loadCommands(this.settings.commands);

  // setup events
  console.log('Setting up event bindings...');
  this.client
    .on('message', this.onMessage())
    .on('ready', this.onReady())
    .on('serverNewMember', this.serverNewMember())
    .on('disconnected', this.onDisconnected())
    .on('error', this.onError());

  console.log('Connecting...');
  this.client.loginWithToken(this.token, this.discord_opt);
};

module.exports = TheAwesomeBot;
<commit_msg>fixing usage list building<commit_after>var path = require('path');
var Discord = require('discord.js');

function TheAwesomeBot(token, discord_opt) {
  this.token = token;
  this.client = new Discord.Client(discord_opt || { autoReconnect: true });
  this.settings = require('./settings.json');
  this.commands = {};
  this.usageList = '';

  // store the RE as they're expensive to create
  this.cmd_re = new RegExp(`^${this.settings.bot_cmd}[\\s]+([^ ]*)[\\s]*(.*)[\\s]*`, 'i');
};

TheAwesomeBot.prototype.onMessage = function () {
  var instance = this;
  return (function (message) {
    // don't respond to own messages
    if (instance.client.user.username === message.author.username)
      return;

    // check if message is a command
    var cmd_match = message.cleanContent.match(instance.cmd_re);

    // not a known command
    if (!cmd_match || Object.keys(instance.commands).indexOf(cmd_match[1]) === -1) {

      if (message.content.match(new RegExp(`^${instance.settings.bot_cmd}[\\s]*( .*)?$`, 'i'))) {
        var helpText = 'maybe try these valid commands? *kthnxbye!*\n\n```';
        helpText += instance.usageList;
        helpText += '```';
        instance.client.reply(message, helpText);
      }

      return;
    }

    // process commands
    var cmd = cmd_match[1];
    var cmd_args = cmd_match[2].trim();

    instance.commands[cmd].run(instance, message, cmd_args);
  });
};

TheAwesomeBot.prototype.onReady = function () {
  var instance = this;
  return (function () {
    console.log('\nConnected to discord server!');

    console.log('Running initializations...');
    for (var cmd in instance.commands) {
      if (typeof instance.commands[cmd].init == 'function') {
        instance.commands[cmd].init(instance);
      }
    };
  });
};

TheAwesomeBot.prototype.serverNewMember = function () {
  var instance = this;
  return (function (server, user) {
    instance.client.sendMessage(user, instance.usageList);
  });
};

TheAwesomeBot.prototype.onDisconnected = function () {
  return (function () {
    console.warn('Bot has been disconnected from server...');
  });
};

TheAwesomeBot.prototype.onError = function () {
  return (function (err) {
    console.error('error: ', e);
    console.error(e.trace);
  });
};

TheAwesomeBot.prototype.loadCommands = function (cmdList) {
  var instance = this;
  instance.usageList = '';
  cmdList.forEach(cmd => {
    var fullpath = path.join(__dirname, 'commands', cmd, `${cmd}.js`);
    var script = require(fullpath);
    instance.commands[cmd] = script;

    var usageObj = script.usage;
    var usageStrs = [];
    if (Array.isArray(usageObj)) {
      usageObj.forEach(u => usageStrs.push(u));
    } else {
      usageStrs.push(usageObj.toString());
    }

    usageStrs.forEach(u => {
      instance.usageList += `\n- ${instance.settings.bot_cmd} ${u}`
    });
  });
};

TheAwesomeBot.prototype.init = function () {
  // load commands
  console.log('Loading commands...');
  this.loadCommands(this.settings.commands);

  // setup events
  console.log('Setting up event bindings...');
  this.client
    .on('message', this.onMessage())
    .on('ready', this.onReady())
    .on('serverNewMember', this.serverNewMember())
    .on('disconnected', this.onDisconnected())
    .on('error', this.onError());

  console.log('Connecting...');
  this.client.loginWithToken(this.token, this.discord_opt);
};

module.exports = TheAwesomeBot;
<|endoftext|>


<commit_before>// # ceb-feature-template.js

// ## Light DOM
//
// The template can contains a node having the attribute `ceb-content`.
// The marked node is intend to host the light DOM of the current element at the end of the templating process.
//
// If the template doesn't contain this node, the light DOM will be lost.
//
// ## DOM nodes references
//
// The template can contains nodes having the attribute `ceb-ref`.
// The marked nodes will be available at the end of the templating process from the feature function (`feature(el)`).
//
// That means, if a node has the attribute `ceb-ref="header"`.
// It will be available via `feature(el).header`.

(function (g, factory) {
    'use strict';

    /* istanbul ignore next */
    if (typeof exports === 'object') {
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        define('ceb-feature-template', [], factory);
    } else {
        g.cebFeatureTemplate = factory();
    }

}(this, function () {
    'use strict';

    // ## feature function

    // The template feature's function returns the nodes' reference of the template.
    function feature(el) {
        if (!el.__cebTemplateScope) {
            el.__cebTemplateScope = {};
        }
        return el.__cebTemplateScope;
    }

    // ## Templating stuff

    // The counter is used to generate unique DOM's id.
    var counter = 0;

    // Regex to detect the *ceb-ref* attributes
    var nodesRegEx = /ceb\-ref=\W*(\w*)/igm;

    // Regex to detect the *ceb-content* attribute
    var contentRegEx = /ceb\-content/im;

    // Apply a template to an element.
    function apply(tpl, el, isHandleLightDOM, isNodeReferences) {
        var lightChildren = [],
            bindedNodes = [],
            newCebContentId,
            template = tpl;

        if (isHandleLightDOM) {
            // When a node is cloned the light DOM of the cloned has to be retrived
            var oldCebContentId = el.getAttribute('ceb-old-content-id');
            // Get the light DOM
            var lightDomNode = el.querySelector('[' + oldCebContentId + ']') || el;
            // Remove the light DOM nodes from the element
            while (lightDomNode.childNodes.length > 0) {
                lightChildren.push(lightDomNode.removeChild(lightDomNode.childNodes[0]));
            }

            // Generate the new content's id value
            newCebContentId = 'ceb-' + (counter++) + '-content';
            // Update the tempate to contains the content's id
            template = template.replace(' ceb-content', ' ' + newCebContentId);
            // Keep a value of the content's id value if the node is cloned
            el.setAttribute('ceb-old-content-id', newCebContentId);
        }

        if (isNodeReferences) {
            // Update the template to detect the DOM nodes references.
            var result;
            while ((result = nodesRegEx.exec(template)) !== null) {
                var id = counter++;
                var property = result[1];
                var newAtt = 'ceb-' + id + '-ref';
                template = template.replace(' ceb-ref', ' ' + newAtt);
                bindedNodes.push({
                    attribute: newAtt,
                    property: property
                });
            }
        }

        // Make alive the template.
        el.innerHTML = template;

        // Push the light DOM nodes into the element
        if (isHandleLightDOM) {
            var contentNode = el.querySelector('[' + newCebContentId + ']');
            lightChildren.forEach(function (node) {
                contentNode.appendChild(node);
            });
        }

        if (isNodeReferences) {
            // Get the reference nodes.
            bindedNodes.forEach(function (entry) {
                feature(el)[entry.property] = el.querySelector('[' + entry.attribute + ']');
            });
        }
    }

    // ## Setup function

    // The templeting process is done before the call of the `createdCallback` method defined in the structure.
    function setup(struct, builder, options) {
        var tpl = options.template || '';
        var isHandleLightDOM = tpl.search(contentRegEx) !== -1;
        var isNodeReferences = tpl.search(nodesRegEx) !== -1;
        builder.wrap('createdCallback', function (next, el) {
            apply(tpl, el, isHandleLightDOM, isNodeReferences);
            next(arguments);
        });
    }
    feature.setup = setup;

    return feature;
}));
<commit_msg>review template feature<commit_after>// # ceb-feature-template.js

// ## Light DOM
//
// The template can contains a node having the attribute `ceb-content`.
// The marked node is intend to host the light DOM of the current element at the end of the templating process.
//
// If the template doesn't contain this node, the light DOM will be lost.
//
// ## DOM nodes references
//
// The template can contains nodes having the attribute `ceb-ref`.
// The marked nodes will be available at the end of the templating process from the feature function (`feature(el)`).
//
// That means, if a node has the attribute `ceb-ref="header"`.
// It will be available via `feature(el).header`.

(function (g, factory) {
    'use strict';

    /* istanbul ignore next */
    if (typeof exports === 'object') {
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        define('ceb-feature-template', [], factory);
    } else {
        g.cebFeatureTemplate = factory();
    }

}(this, function () {
    'use strict';

    // ## feature function

    // The template feature's function returns the nodes' reference of the template.
    function feature(el) {
        if (!el.__cebTemplateScope) {
            el.__cebTemplateScope = {};
        }
        return el.__cebTemplateScope;
    }

    // ## Templating stuff

    // The counter is used to generate unique DOM's id.
    var counter = 0;

    // Regex to detect the *ceb-ref* attributes
    var nodesRegEx = /ceb\-ref=\W*(\w*)/igm;

    // Regex to detect the *ceb-content* attribute
    var contentRegEx = /ceb\-content/im;

    // Apply a template to an element.
    function apply(tpl, el, isHandleLightDOM, isNodeReferences) {
        var lightChildren = [],
            refrencedNodes = [],
            newCebContentId,
            template = tpl;

        if (isHandleLightDOM) {
            // When a node is cloned the light DOM of the cloned has to be retrived
            var oldCebContentId = el.getAttribute('ceb-old-content-id');
            // Get the current root of light DOM nodes,
            // if the node has been cloned the root is the element binding old content id
            // else it's the current element.
            var lightDomNode = (oldCebContentId && el.querySelector('[' + oldCebContentId + ']')) || el;
            // Remove the light DOM nodes from the element
            while (lightDomNode.childNodes.length > 0) {
                lightChildren.push(lightDomNode.removeChild(lightDomNode.childNodes[0]));
            }

            // Generate the new content's id value
            newCebContentId = 'ceb-' + (counter++) + '-content';
            // Replace the original attribute name by the id
            template = template.replace(' ceb-content', ' ' + newCebContentId);
            // Keep a value of the content's id value if the node is cloned
            el.setAttribute('ceb-old-content-id', newCebContentId);
        }

        if (isNodeReferences) {
            // Update the template to detect the DOM nodes references.
            var result;
            while ((result = nodesRegEx.exec(template)) !== null) {
                var property = result[1];
                // build an id of the reference
                var newAtt = 'ceb-' + (counter++) + '-ref';
                // replace the original attribute name by the idenitifer
                template = template.replace(' ceb-ref', ' ' + newAtt);
                // push the entry
                refrencedNodes.push({
                    attribute: newAtt,
                    property: property
                });
            }
        }

        // Make alive the template.
        el.innerHTML = template;

        // Push the light DOM nodes into the element
        if (isHandleLightDOM) {
            var contentNode = el.querySelector('[' + newCebContentId + ']');
            lightChildren.forEach(function (node) {
                contentNode.appendChild(node);
            });
        }

        if (isNodeReferences) {
            // Get the reference nodes.
            refrencedNodes.forEach(function (entry) {
                feature(el)[entry.property] = el.querySelector('[' + entry.attribute + ']');
            });
        }
    }

    // ## Setup function

    // The templeting process is done before the call of the `createdCallback` method defined in the structure.
    function setup(struct, builder, options) {
        var tpl = options.template || '';
        var isHandleLightDOM = tpl.search(contentRegEx) !== -1;
        var isNodeReferences = tpl.search(nodesRegEx) !== -1;
        builder.wrap('createdCallback', function (next, el) {
            apply(tpl, el, isHandleLightDOM, isNodeReferences);
            next(arguments);
        });
    }
    feature.setup = setup;

    return feature;
}));
<|endoftext|>


<commit_before>/**
 * API.service.js
 * Modified from https://github.com/jadjoubran/laravel5-angular-material-starter/blob/master/angular/services/API.service.js
 * by anonymous on 04/01/16 1:19.
 */

(function() {
    'use strict';

    angular
        .module('appFoundation')
        .factory('API', API);

    API.$inject = ['Restangular', 'ToastService', '$localStorage'];

    /* @ngInject */
    function API(Restangular, ToastService, $localStorage) {
        //content negotiation
        var
            headers = {
                'Content-Type': 'application/json',
                'Accept'      : 'application/x.laravel.v1+json'
            },
            service = serviceFn();

        return service;

        ////////////////

        function serviceFn() {
            return Restangular.withConfig(function(RestangularConfigurer) {
                RestangularConfigurer
                    .setBaseUrl('/api/')
                    .setDefaultHeaders(headers)
                    .setErrorInterceptor(function(response) {
                        if (response.status === 422) {
                            for (var error in response.data.errors) {
                                return ToastService.error(response.data.errors[error][0]);
                            }
                        }
                    })
                    .addFullRequestInterceptor(function(element, operation, what, url, headers) {
                        if ($localStorage.app_token) {
                            headers.Authorization = 'Bearer ' + $localStorage.app_token;
                        }
                    })
                    .addResponseInterceptor(function(data, operation, what, url, response, deferred) {
                        var extractedData;
                        // look for getList operations
                        if (operation === 'getList') {
                            // handle the data and meta data
                            extractedData = data.data;
                            // extractedData.meta = data.data.meta;
                        } else {
                            extractedData = data;
                        }
                        return extractedData;
                    })
                    .setMethodOverriders(['put', 'patch', 'delete']);
            });
        }
    }

})();

<commit_msg>Modified API.service<commit_after>/**
 * API.service.js
 * Modified from https://github.com/jadjoubran/laravel5-angular-material-starter/blob/master/angular/services/API.service.js
 * by anonymous on 04/01/16 1:19.
 */

(function() {
    'use strict';

    angular
        .module('appFoundation')
        .factory('API', API);

    API.$inject = ['Restangular', 'ToastService', '$localStorage'];

    /* @ngInject */
    function API(Restangular, ToastService, $localStorage) {
        //content negotiation
        var
            headers = {
                'Content-Type': 'application/json',
                'Accept'      : 'application/x.onsigbaar.v1+json'
            },
            service = serviceFn();

        return service;

        ////////////////

        function serviceFn() {
            return Restangular.withConfig(function(RestangularConfigurer) {
                RestangularConfigurer
                    .setBaseUrl('/api/')
                    .setDefaultHeaders(headers)
                    .setErrorInterceptor(function(response) {
                        if (response.status === 422) {
                            for (var error in response.data.errors) {
                                return ToastService.error(response.data.errors[error][0]);
                            }
                        }
                    })
                    .addFullRequestInterceptor(function(element, operation, what, url, headers) {
                        if ($localStorage.onsigbaar_token) {
                            headers.Authorization = 'Bearer ' + $localStorage.onsigbaar_token;
                        }
                    })
                    .addResponseInterceptor(function(data, operation, what, url, response, deferred) {
                        var extractedData;
                        // look for getList operations
                        if (operation === 'getList') {
                            // handle the data and meta data
                            extractedData = data.data;
                            // extractedData.meta = data.data.meta;
                        } else {
                            extractedData = data;
                        }
                        return extractedData;
                    })
                    .setMethodOverriders(['put', 'patch', 'delete']);
            });
        }
    }

})();

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Cyclorama component
 * @author Meine Toonen
 */
Ext.define ("viewer.components.Cyclorama",{
    extend: "viewer.components.Component",
    toolMapClick:null,
    deActivatedTools:null,
    window:null,
    optionWindow:null,
    config:{
    },
    constructor: function (conf){
        viewer.components.Cyclorama.superclass.constructor.call(this, conf);
        this.initConfig(conf);
        // Registreer voor layerinitialized
        this.viewerController.addListener(viewer.viewercontroller.controller.Event.ON_LAYERS_INITIALIZED, this.initComp, this);
        return this;
    },
    initComp : function(){
        this.toolMapClick =  this.viewerController.mapComponent.createTool({
            type: viewer.viewercontroller.controller.Tool.MAP_CLICK,
            id: this.name + "toolMapClick",
            handler:{
                fn: this.mapClicked,
                scope:this
            },
            viewerController: this.config.viewerController
        });
        this.toolMapClick.activateTool();
    },
    processResponse: function (response){
        if(response.features.length >1 ){
            this.showOptions(response.features);
        }else if(response.features.length === 1){
            this.openGlobespotter(response.features[0]);
        }
    },
    showOptions : function(features){
        var store = Ext.create('Ext.data.Store', {
            fields:[this.config.imageIdAttribute],
            data:{'items':features},
            proxy: {
                type: 'memory',
                reader: {
                    type: 'json',
                    root: 'items'
                }
            }
        });

        var grid = Ext.create('Ext.grid.Panel', {
            store: store,
            columns: [
                { header: 'Image id',  dataIndex: this.config.imageIdAttribute,flex:1 }
            ],
            listeners:{
                itemdblclick:{
                    scope:this,
                    fn:function(grid,item){
                        this.openGlobespotter(item.data);
                    }
                }
            }
        });

        if(this.optionWindow){
            this.optionWindow.destroy();
        }
        this.optionWindow = Ext.create('Ext.window.Window', {
            title: "Maak een keuze uit de verschillende foto's",
            height: 200,
            width: 400,
            layout: 'fit',
            items: grid
        }).show();
    },
    openGlobespotter : function(feature){
        var params = {
            imageId: feature[this.config.imageIdAttribute] ,
            appId: appId,
            accountId: this.config.keyCombo
        };
        Ext.Ajax.request({
            url: actionBeans["cyclorama"],
            params: params,
            scope: this,
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText);
                this.linkReceived(response);
            },
            failure: function(result) {
               this.viewerController.logger.error(result);
            }
        });

    },
    linkReceived: function(response){
         // Get link from backend
        var width = parseInt(this.config.width);
        var height = parseInt(this.config.height);
        if(this.window){
            this.window.destroy();
        }
        this.window = Ext.create('Ext.window.Window', {
            title: "Cyclorama rondkijk foto's",
            height: height,
            resizable: false,
            width: width,
            layout: 'fit',
            html:
                '
' +
                    ' <object id="Globespotter" name="TID">' +
                        ' <param name="allowScriptAccess" value="always" />' +
                        ' <param name="allowFullScreen" value="true" />' +
                        ' <embed src="https://www.globespotter.nl/v2/api/bapi/viewer_bapi.swf"' +
                            ' quality="high" bgcolor="#888888"' +
                            ' width="' + (width - 10) + '" height="' + (height - 10)+
                            ' type="application/x-shockwave-flash"' +
                            ' allowScriptAccess="always"' +
                            ' allowfullscreen="true"' +
                            ' FlashVars="&APIKey=' + response.apiKey + '&imageid=' + response.imageId + '&MapSRSName=EPSG:28992&TID=' + response.tid + '">' +
                        ' </embed>' +
                    ' </object>' +
                '
'
        }).show();
    },
    mapClicked: function (tool, event) {
        var me = this;
        var appLayer = this.viewerController.getAppLayerById(this.config.layers);
        var coords = event.coord;
        var x = coords.x;
        var y = coords.y;

        var attributes = [];
        attributes.push(this.config.imageIdAttribute);
        attributes.push(this.config.imageDescriptionAttribute);

        var extraParams = {
            attributesToInclude: attributes,
            graph: true
        };
        this.viewerController.mapComponent.getMap().setMarker("edit", x, y);
        var featureInfo = Ext.create("viewer.FeatureInfo", {
            viewerController: me.viewerController
        });
        var radius = me.viewerController.mapComponent.getMap().getResolution() * 4;
        featureInfo.layersFeatureInfo(x, y, radius, [appLayer], extraParams,function(response){
            for ( var i = 0 ; i < response.length; i++){
                var resp = response[i];
                if(parseInt( resp.request.appLayer) === parseInt(me.config.layers)){
                    me.processResponse(resp, resp.request.appLayer);
                }
            }

        }, function(error){
               this.viewerController.logger.error(error);
        },me);
    }

});<commit_msg>Set the width and height correctly to show the whole picture<commit_after>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Cyclorama component
 * @author Meine Toonen
 */
Ext.define ("viewer.components.Cyclorama",{
    extend: "viewer.components.Component",
    toolMapClick:null,
    deActivatedTools:null,
    window:null,
    optionWindow:null,
    config:{
    },
    constructor: function (conf){
        viewer.components.Cyclorama.superclass.constructor.call(this, conf);
        this.initConfig(conf);
        // Registreer voor layerinitialized
        this.viewerController.addListener(viewer.viewercontroller.controller.Event.ON_LAYERS_INITIALIZED, this.initComp, this);
        return this;
    },
    initComp : function(){
        this.toolMapClick =  this.viewerController.mapComponent.createTool({
            type: viewer.viewercontroller.controller.Tool.MAP_CLICK,
            id: this.name + "toolMapClick",
            handler:{
                fn: this.mapClicked,
                scope:this
            },
            viewerController: this.config.viewerController
        });
        this.toolMapClick.activateTool();
    },
    processResponse: function (response){
        if(response.features.length >1 ){
            this.showOptions(response.features);
        }else if(response.features.length === 1){
            this.openGlobespotter(response.features[0]);
        }
    },
    showOptions : function(features){
        var store = Ext.create('Ext.data.Store', {
            fields:[this.config.imageIdAttribute],
            data:{'items':features},
            proxy: {
                type: 'memory',
                reader: {
                    type: 'json',
                    root: 'items'
                }
            }
        });

        var grid = Ext.create('Ext.grid.Panel', {
            store: store,
            columns: [
                { header: 'Image id',  dataIndex: this.config.imageIdAttribute,flex:1 }
            ],
            listeners:{
                itemdblclick:{
                    scope:this,
                    fn:function(grid,item){
                        this.openGlobespotter(item.data);
                    }
                }
            }
        });

        if(this.optionWindow){
            this.optionWindow.destroy();
        }
        this.optionWindow = Ext.create('Ext.window.Window', {
            title: "Maak een keuze uit de verschillende foto's",
            height: 200,
            width: 400,
            layout: 'fit',
            items: grid
        }).show();
    },
    openGlobespotter : function(feature){
        var params = {
            imageId: feature[this.config.imageIdAttribute] ,
            appId: appId,
            accountId: this.config.keyCombo
        };
        Ext.Ajax.request({
            url: actionBeans["cyclorama"],
            params: params,
            scope: this,
            success: function(result) {
                var response = Ext.JSON.decode(result.responseText);
                this.linkReceived(response);
            },
            failure: function(result) {
               this.viewerController.logger.error(result);
            }
        });

    },
    linkReceived: function(response){
         // Get link from backend
        var width = parseInt(this.config.width);
        var height = parseInt(this.config.height);
        if(this.window){
            this.window.destroy();
        }
        this.window = Ext.create('Ext.window.Window', {
            title: "Cyclorama rondkijk foto's",
            height: height,
            resizable: false,
            width: width,
            layout: 'fit',
            html:
                '
' +
                    ' <object id="Globespotter" name="TID">' +
                        ' <param name="allowScriptAccess" value="always" />' +
                        ' <param name="allowFullScreen" value="true" />' +
                        ' <embed src="https://www.globespotter.nl/v2/api/bapi/viewer_bapi.swf"' +
                            ' quality="high" bgcolor="#888888"' +
                            ' width="' + (width - 12) + '" height="' + (height - 33)+
                            ' type="application/x-shockwave-flash"' +
                            ' allowScriptAccess="always"' +
                            ' allowfullscreen="true"' +
                            ' FlashVars="&APIKey=' + response.apiKey + '&imageid=' + response.imageId + '&MapSRSName=EPSG:28992&TID=' + response.tid + '">' +
                        ' </embed>' +
                    ' </object>' +
                '
'
        }).show();
    },
    mapClicked: function (tool, event) {
        var me = this;
        var appLayer = this.viewerController.getAppLayerById(this.config.layers);
        var coords = event.coord;
        var x = coords.x;
        var y = coords.y;

        var attributes = [];
        attributes.push(this.config.imageIdAttribute);
        attributes.push(this.config.imageDescriptionAttribute);

        var extraParams = {
            attributesToInclude: attributes,
            graph: true
        };
        this.viewerController.mapComponent.getMap().setMarker("edit", x, y);
        var featureInfo = Ext.create("viewer.FeatureInfo", {
            viewerController: me.viewerController
        });
        var radius = me.viewerController.mapComponent.getMap().getResolution() * 4;
        featureInfo.layersFeatureInfo(x, y, radius, [appLayer], extraParams,function(response){
            for ( var i = 0 ; i < response.length; i++){
                var resp = response[i];
                if(parseInt( resp.request.appLayer) === parseInt(me.config.layers)){
                    me.processResponse(resp, resp.request.appLayer);
                }
            }

        }, function(error){
               this.viewerController.logger.error(error);
        },me);
    }

});<|endoftext|>


<commit_before>import editableValueFactory from './editableValueFactory'
import formattedValueFactory from './formattedValueFactory'

const editableMapping = {
  'binary': editableValueFactory('document'),
  'birthdate': editableValueFactory('date'),
  'boolean': editableValueFactory('boolean'),
  'char': editableValueFactory('string'),
  'code': editableValueFactory('text'),
  'count': editableValueFactory('string'),
  'counter': editableValueFactory('integer'),
  'createts': editableValueFactory('datetime'),
  'createuser': editableValueFactory('string'),
  'compressed-text': editableValueFactory('text'),
  'date': editableValueFactory('date'),
  'datetime': editableValueFactory('datetime'),
  'decimal': editableValueFactory('number'),
  'display': formattedValueFactory('html'),
  'description': formattedValueFactory('description'),
  'document': editableValueFactory('document'),
  'double': editableValueFactory('number'),
  'duration': editableValueFactory('duration'),
  'email': editableValueFactory('string'),
  'fulltext-search': editableValueFactory('string'),
  'html': editableValueFactory('html'),
  'image': editableValueFactory('document'),
  'identifier': editableValueFactory('string'),
  'integer': editableValueFactory('integer'),
  'ipaddress': editableValueFactory('string'),
  'latitude': editableValueFactory('string'),
  'location': editableValueFactory('location'),
  'login': editableValueFactory('string'),
  'long': editableValueFactory('integer'),
  'longitude': editableValueFactory('string'),
  'moneyamount': editableValueFactory('number'),
  'multi-remote-field': editableValueFactory('multi-remote'),
  'multi-select-box': editableValueFactory('multi-select'),
  'named-upload': editableValueFactory('document'),
  'percent': editableValueFactory('number'),
  'phone': editableValueFactory('phone'),
  'postcode': editableValueFactory('string'),
  'pulldown-date': editableValueFactory('date'),
  'search-filter': editableValueFactory('search-filter'),
  'serial': editableValueFactory('string'),
  'single-remote-field': editableValueFactory('remote'),
  'single-select-box': editableValueFactory('single-select'),
  'sorting': editableValueFactory('integer'),
  'string': editableValueFactory('string'),
  'text': editableValueFactory('text'),
  'text-area': editableValueFactory('text'),
  'time': editableValueFactory('time'),
  'updatets': editableValueFactory('datetime'),
  'upload': editableValueFactory('document'),
  'url': editableValueFactory('url'),
  'uuid': editableValueFactory('string'),
  'version': editableValueFactory('string')
}
const readOnlyMapping = {
  'binary': formattedValueFactory('document'),
  'birthdate': formattedValueFactory('birthdate'),
  'boolean': formattedValueFactory('boolean'),
  'code': formattedValueFactory('text'),
  'char': formattedValueFactory('string'),
  'counter': formattedValueFactory('integer'),
  'createuser': formattedValueFactory('string'),
  'createts': formattedValueFactory('datetime'),
  'compressed-text': formattedValueFactory('text'),
  'data-amount': formattedValueFactory('number'),
  'date': formattedValueFactory('date'),
  'datetime': formattedValueFactory('datetime'),
  'decimal': formattedValueFactory('number'),
  'display': formattedValueFactory('html'),
  'description': formattedValueFactory('description'),
  'duration': formattedValueFactory('duration'),
  'document': formattedValueFactory('document'),
  'double': formattedValueFactory('number'),
  'email': formattedValueFactory('email'),
  'html': formattedValueFactory('html'),
  'image': formattedValueFactory('document'),
  'ipaddress': formattedValueFactory('string'),
  'identifier': formattedValueFactory('string'),
  'latitude': formattedValueFactory('string'),
  'login': formattedValueFactory('string'),
  'long': formattedValueFactory('integer'),
  'longitude': formattedValueFactory('string'),
  'moneyamount': formattedValueFactory('moneyamount'),
  'multi-remote-field': formattedValueFactory('multi-remote'),
  'multi-select-box': formattedValueFactory('multi-select'),
  'named-upload': formattedValueFactory('document'),
  'integer': formattedValueFactory('integer'),
  'percent': formattedValueFactory('number'),
  'phone': formattedValueFactory('phone'),
  'postcode': formattedValueFactory('string'),
  'pulldown-date': formattedValueFactory('date'),
  'remote': formattedValueFactory('remote'),
  'search-filter': formattedValueFactory('search-filter'),
  'serial': formattedValueFactory('string'),
  'single-remote-field': formattedValueFactory('remote'),
  'single-select-box': formattedValueFactory('single-select'),
  'sorting': formattedValueFactory('integer'),
  'string': formattedValueFactory('string'),
  'text': formattedValueFactory('text'),
  'text-area': formattedValueFactory('text'),
  'time': formattedValueFactory('time'),
  'updatets': formattedValueFactory('datetime'),
  'upload': formattedValueFactory('document'),
  'url': formattedValueFactory('url'),
  'uuid': formattedValueFactory('string'),
  'version': formattedValueFactory('string')
}

const listMapping = {
  ...readOnlyMapping,
  binary: formattedValueFactory('document-compact'),
  document: formattedValueFactory('document-compact'),
  image: formattedValueFactory('document-compact')
}

const searchMapping = {
  ...editableMapping,
  text: editableValueFactory('string'),
  birthdate: editableValueFactory('date', true),
  date: editableValueFactory('date', true),
  updatets: editableValueFactory('datetime', true),
  createts: editableValueFactory('datetime', true),
  datetime: editableValueFactory('datetime', true),
  moneyamount: editableValueFactory('number', true),
  percent: editableValueFactory('number', true),
  long: editableValueFactory('integer', true),
  integer: editableValueFactory('integer', true),
  decimal: editableValueFactory('number', true),
  counter: editableValueFactory('integer', true),
  time: editableValueFactory('time', true)
}

export default {
  editable: editableMapping,
  readOnly: readOnlyMapping,
  list: listMapping,
  search: searchMapping
}
<commit_msg>fix(app-extension): map formatted email to string<commit_after>import editableValueFactory from './editableValueFactory'
import formattedValueFactory from './formattedValueFactory'

const editableMapping = {
  'binary': editableValueFactory('document'),
  'birthdate': editableValueFactory('date'),
  'boolean': editableValueFactory('boolean'),
  'char': editableValueFactory('string'),
  'code': editableValueFactory('text'),
  'count': editableValueFactory('string'),
  'counter': editableValueFactory('integer'),
  'createts': editableValueFactory('datetime'),
  'createuser': editableValueFactory('string'),
  'compressed-text': editableValueFactory('text'),
  'date': editableValueFactory('date'),
  'datetime': editableValueFactory('datetime'),
  'decimal': editableValueFactory('number'),
  'display': formattedValueFactory('html'),
  'description': formattedValueFactory('description'),
  'document': editableValueFactory('document'),
  'double': editableValueFactory('number'),
  'duration': editableValueFactory('duration'),
  'email': editableValueFactory('string'),
  'fulltext-search': editableValueFactory('string'),
  'html': editableValueFactory('html'),
  'image': editableValueFactory('document'),
  'identifier': editableValueFactory('string'),
  'integer': editableValueFactory('integer'),
  'ipaddress': editableValueFactory('string'),
  'latitude': editableValueFactory('string'),
  'location': editableValueFactory('location'),
  'login': editableValueFactory('string'),
  'long': editableValueFactory('integer'),
  'longitude': editableValueFactory('string'),
  'moneyamount': editableValueFactory('number'),
  'multi-remote-field': editableValueFactory('multi-remote'),
  'multi-select-box': editableValueFactory('multi-select'),
  'named-upload': editableValueFactory('document'),
  'percent': editableValueFactory('number'),
  'phone': editableValueFactory('phone'),
  'postcode': editableValueFactory('string'),
  'pulldown-date': editableValueFactory('date'),
  'search-filter': editableValueFactory('search-filter'),
  'serial': editableValueFactory('string'),
  'single-remote-field': editableValueFactory('remote'),
  'single-select-box': editableValueFactory('single-select'),
  'sorting': editableValueFactory('integer'),
  'string': editableValueFactory('string'),
  'text': editableValueFactory('text'),
  'text-area': editableValueFactory('text'),
  'time': editableValueFactory('time'),
  'updatets': editableValueFactory('datetime'),
  'upload': editableValueFactory('document'),
  'url': editableValueFactory('url'),
  'uuid': editableValueFactory('string'),
  'version': editableValueFactory('string')
}
const readOnlyMapping = {
  'binary': formattedValueFactory('document'),
  'birthdate': formattedValueFactory('birthdate'),
  'boolean': formattedValueFactory('boolean'),
  'code': formattedValueFactory('text'),
  'char': formattedValueFactory('string'),
  'counter': formattedValueFactory('integer'),
  'createuser': formattedValueFactory('string'),
  'createts': formattedValueFactory('datetime'),
  'compressed-text': formattedValueFactory('text'),
  'data-amount': formattedValueFactory('number'),
  'date': formattedValueFactory('date'),
  'datetime': formattedValueFactory('datetime'),
  'decimal': formattedValueFactory('number'),
  'display': formattedValueFactory('html'),
  'description': formattedValueFactory('description'),
  'duration': formattedValueFactory('duration'),
  'document': formattedValueFactory('document'),
  'double': formattedValueFactory('number'),
  'email': formattedValueFactory('string'),
  'html': formattedValueFactory('html'),
  'image': formattedValueFactory('document'),
  'ipaddress': formattedValueFactory('string'),
  'identifier': formattedValueFactory('string'),
  'latitude': formattedValueFactory('string'),
  'login': formattedValueFactory('string'),
  'long': formattedValueFactory('integer'),
  'longitude': formattedValueFactory('string'),
  'moneyamount': formattedValueFactory('moneyamount'),
  'multi-remote-field': formattedValueFactory('multi-remote'),
  'multi-select-box': formattedValueFactory('multi-select'),
  'named-upload': formattedValueFactory('document'),
  'integer': formattedValueFactory('integer'),
  'percent': formattedValueFactory('number'),
  'phone': formattedValueFactory('phone'),
  'postcode': formattedValueFactory('string'),
  'pulldown-date': formattedValueFactory('date'),
  'remote': formattedValueFactory('remote'),
  'search-filter': formattedValueFactory('search-filter'),
  'serial': formattedValueFactory('string'),
  'single-remote-field': formattedValueFactory('remote'),
  'single-select-box': formattedValueFactory('single-select'),
  'sorting': formattedValueFactory('integer'),
  'string': formattedValueFactory('string'),
  'text': formattedValueFactory('text'),
  'text-area': formattedValueFactory('text'),
  'time': formattedValueFactory('time'),
  'updatets': formattedValueFactory('datetime'),
  'upload': formattedValueFactory('document'),
  'url': formattedValueFactory('url'),
  'uuid': formattedValueFactory('string'),
  'version': formattedValueFactory('string')
}

const listMapping = {
  ...readOnlyMapping,
  binary: formattedValueFactory('document-compact'),
  document: formattedValueFactory('document-compact'),
  image: formattedValueFactory('document-compact')
}

const searchMapping = {
  ...editableMapping,
  text: editableValueFactory('string'),
  birthdate: editableValueFactory('date', true),
  date: editableValueFactory('date', true),
  updatets: editableValueFactory('datetime', true),
  createts: editableValueFactory('datetime', true),
  datetime: editableValueFactory('datetime', true),
  moneyamount: editableValueFactory('number', true),
  percent: editableValueFactory('number', true),
  long: editableValueFactory('integer', true),
  integer: editableValueFactory('integer', true),
  decimal: editableValueFactory('number', true),
  counter: editableValueFactory('integer', true),
  time: editableValueFactory('time', true)
}

export default {
  editable: editableMapping,
  readOnly: readOnlyMapping,
  list: listMapping,
  search: searchMapping
}
<|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const npmSass = require('npm-sass');
const autoprefixer = require('autoprefixer');
const postcssDiscardDuplicates = require('postcss-discard-duplicates');
const ManifestPlugin = require('webpack-manifest-plugin');
const sassImportGlobbing = require('@theme-tools/sass-import-globbing');
const assets = require('./utils/assets');

function createConfig(config) {
  // @TODO: move this setting to .boltrc config
  const sassExportData = require('@theme-tools/sass-export-data')({
    path: path.resolve(process.cwd(), config.wwwDir, config.buildDir, 'data'),
  });

  // Map out the global config verbosity setting to the 6 preset levels of Webpack stats: https://webpack.js.org/configuration/stats/#stats + https://github.com/webpack/webpack/blob/b059e07cf90db871fe9497f5c14b9383fc71d2ad/lib/Stats.js#L906

  const webpackStats = {
    0: 'none', // Output nothing
    1: 'errors-only', // only output when errors happen
    2: 'minimal', // only output when errors or new compilation happen
    3: 'normal', // standard output
    4: 'detailed',
    5: 'verbose', // output everything
  }

  function statsPreset(name) {
    /**
     * Accepted values: none, errors-only, minimal, normal, detailed,
     * verbose. Any other falsy value will behave as 'none', truthy
     * values as 'normal'
     */
    const pn = (typeof name === "string") && name.toLowerCase() || name || "none";

    switch (pn) {
      case 'none':
        return {
          all: false
        };
      case 'verbose':
        return {
          entrypoints: true,
          modules: false,
          colors: true,
          chunks: true,
          chunkModules: true,
          chunkOrigins: true,
          depth: true,
          env: true,
          reasons: true,
          usedExports: true,
          providedExports: true,
          optimizationBailout: true,
          errorDetails: true,
          publicPath: true,
          exclude: () => false,
          maxModules: Infinity,
        };
      case 'detailed':
        return {
          entrypoints: true,
          chunks: true,
          colors: true,
          chunkModules: false,
          chunkOrigins: true,
          depth: true,
          usedExports: true,
          providedExports: true,
          optimizationBailout: true,
          errorDetails: true,
          publicPath: true,
          exclude: () => false,
          maxModules: Infinity,
        };
      case 'minimal':
        return {
          all: false,
          colors: true,
          modules: true,
          maxModules: 0,
          errors: true,
          warnings: true,
        };
      case 'errors-only':
        return {
          all: false,
          colors: true,
          errors: true,
          moduleTrace: true,
        };
      default:
        return {
          colors: true
        }
    }
  }

  return {
    entry: assets.buildWebpackEntry(config.components),
    output: {
      path: path.resolve(process.cwd(), config.wwwDir, config.buildDir),
      filename: "[name].js",
      publicPath: config.publicPath
    },
    devtool: 'cheap-module-eval-source-map',
    resolve: {
      extensions: [".js", ".jsx", ".json", ".svg", ".scss"]
    },
    module: {
      rules: [
        {
          test: /\.scss$/,
          use: ExtractTextPlugin.extract({
            fallback: "style-loader",
            use: [
              {
                loader: "css-loader",
                options: {
                  sourceMap: true,
                  modules: false, // re-enable if/when using css-modules. was adding duplicate output of CSS to JS output
                  importLoaders: true,
                  localIdentName: "[local]"
                }
              },
              {
                loader: "postcss-loader",
                options: {
                  plugins: [
                    postcssDiscardDuplicates,
                    autoprefixer,
                  ],
                }
              },
              {
                loader: "clean-css-loader",
                options: {
                  skipWarn: true,
                  compatibility: "ie9",
                  level: process.env.NODE_ENV === "production" ? 2 : 0,
                  inline: ["remote"],
                  format: 'beautify',
                }
              },
              {
                loader: "sass-loader",
                options: {
                  importer: [
                    sassImportGlobbing,
                    npmSass.importer,
                  ],
                  functions: sassExportData,
                  outputStyle: "expanded",
                  precision: 2
                }
              }
            ]
          })
        },
        {
          test: /\.js$/,
          exclude: /(node_modules\/\@webcomponents\/webcomponentsjs\/custom-elements-es5-adapter\.js)/,
          use: {
            loader: 'babel-loader',
            options: {
              babelrc: false,
              presets: ['@bolt/babel-preset-bolt'],
            }
          }
        },
      ],
    },
    plugins: [
      // Ignore generated output if generated output is on a dependency chain (causes endless loop)
      new webpack.WatchIgnorePlugin([
        /dist\/styleguide/,
        /dist\/annotations/,
        /styleguide/,
        path.join(__dirname, 'node_modules')
      ]),
      new webpack.HotModuleReplacementPlugin(),
      new webpack.optimize.CommonsChunkPlugin({
        deepChildren: true,
        children: true,
        minChunks: Infinity,
        async: true
      }),
      new webpack.IgnorePlugin(/vertx/), // needed to ignore vertx dependency in webcomponentsjs-lite
      new ExtractTextPlugin({
        filename: "[name].css",
        // disable: false,
        allChunks: true
      }),
      new ManifestPlugin({
        fileName: 'bolt-manifest.json',
        publicPath: config.publicPath,
        writeToFileEmit: true,
        seed: {
          name: 'Bolt Manifest'
        }
      }),
      new webpack.optimize.ModuleConcatenationPlugin(),
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': process.env.NODE_ENV === 'production' ? JSON.stringify(process.env.NODE_ENV) : JSON.stringify('development'),
      }),
      new webpack.ProvidePlugin({
        h: 'preact',
        Promise: 'es6-promise'
      }),
      // Show build progress
      new webpack.ProgressPlugin({ profile: false }),
    ],
    devServer: {
      contentBase: [
        path.resolve(process.cwd(), config.wwwDir),
        // @TODO: add Pattern Lab Styleguidekit Assets Default dist path here
      ],
      compress: true,
      clientLogLevel: 'info',
      port: 8080,
      stats: statsPreset(webpackStats[config.verbosity]),
      overlay: {
        errors: true
      },
      hot: true,
      inline: true,
      publicPath: config.publicPath,
      watchContentBase: true,
      historyApiFallback: true,
      watchOptions: {
        aggregateTimeout: 500,
        // ignored: /(annotations|fonts|bower_components|dist\/styleguide|node_modules|styleguide|images|fonts|assets)/
        // Poll using interval (in ms, accepts boolean too)
        poll: true,
      }
    }
  };
}

module.exports = createConfig;
<commit_msg>refactor: add examples of inline css imports + external css output in webpack config<commit_after>const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const npmSass = require('npm-sass');
const autoprefixer = require('autoprefixer');
const postcssDiscardDuplicates = require('postcss-discard-duplicates');
const ManifestPlugin = require('webpack-manifest-plugin');
const sassImportGlobbing = require('@theme-tools/sass-import-globbing');
const assets = require('./utils/assets');

function createConfig(config) {
  // @TODO: move this setting to .boltrc config
  const sassExportData = require('@theme-tools/sass-export-data')({
    path: path.resolve(process.cwd(), config.wwwDir, config.buildDir, 'data'),
  });

  // Map out the global config verbosity setting to the 6 preset levels of Webpack stats: https://webpack.js.org/configuration/stats/#stats + https://github.com/webpack/webpack/blob/b059e07cf90db871fe9497f5c14b9383fc71d2ad/lib/Stats.js#L906

  const webpackStats = {
    0: 'none', // Output nothing
    1: 'errors-only', // only output when errors happen
    2: 'minimal', // only output when errors or new compilation happen
    3: 'normal', // standard output
    4: 'detailed',
    5: 'verbose', // output everything
  }

  function statsPreset(name) {
    /**
     * Accepted values: none, errors-only, minimal, normal, detailed,
     * verbose. Any other falsy value will behave as 'none', truthy
     * values as 'normal'
     */
    const pn = (typeof name === "string") && name.toLowerCase() || name || "none";

    switch (pn) {
      case 'none':
        return {
          all: false
        };
      case 'verbose':
        return {
          entrypoints: true,
          modules: false,
          colors: true,
          chunks: true,
          chunkModules: true,
          chunkOrigins: true,
          depth: true,
          env: true,
          reasons: true,
          usedExports: true,
          providedExports: true,
          optimizationBailout: true,
          errorDetails: true,
          publicPath: true,
          exclude: () => false,
          maxModules: Infinity,
        };
      case 'detailed':
        return {
          entrypoints: true,
          chunks: true,
          colors: true,
          chunkModules: false,
          chunkOrigins: true,
          depth: true,
          usedExports: true,
          providedExports: true,
          optimizationBailout: true,
          errorDetails: true,
          publicPath: true,
          exclude: () => false,
          maxModules: Infinity,
        };
      case 'minimal':
        return {
          all: false,
          colors: true,
          modules: true,
          maxModules: 0,
          errors: true,
          warnings: true,
        };
      case 'errors-only':
        return {
          all: false,
          colors: true,
          errors: true,
          moduleTrace: true,
        };
      default:
        return {
          colors: true
        }
    }
  }

  return {
    entry: assets.buildWebpackEntry(config.components),
    output: {
      path: path.resolve(process.cwd(), config.wwwDir, config.buildDir),
      filename: "[name].js",
      publicPath: config.publicPath
    },
    devtool: 'cheap-module-eval-source-map',
    resolve: {
      extensions: [".js", ".jsx", ".json", ".svg", ".scss"]
    },
    module: {
      rules: [

        /**
         * Output .css files for <link> tags
         */
        // {
        //   test: /\.scss$/,
        //   use: ExtractTextPlugin.extract({
        //     fallback: "style-loader",
        //     use: [
        //     {
        //       loader: 'css-loader',
        //       options: {
        //         sourceMap: true,
        //         modules: true,
        //         importLoaders: true,
        //         localIdentName: '[local]'
        //       }
        //     },
        //     {
        //       loader: "postcss-loader",
        //       options: {
        //         plugins: [
        //           postcssDiscardDuplicates,
        //           autoprefixer,
        //         ],
        //       }
        //     },
        //     {
        //       loader: "clean-css-loader",
        //       options: {
        //         skipWarn: true,
        //         compatibility: "ie9",
        //         level: process.env.NODE_ENV === "production" ? 2 : 0,
        //         inline: ["remote"],
        //         format: 'beautify',
        //       }
        //     },
        //     {
        //       loader: "sass-loader",
        //       options: {
        //         importer: [
        //           sassImportGlobbing,
        //           npmSass.importer,
        //         ],
        //         functions: sassExportData,
        //         outputStyle: "expanded",
        //         precision: 2
        //       }
        //     }
        //   ]})
        // },

        /**
         * Expose CSS as JS import for inlining in components
         */
        {
          test: /\.scss$/,
          use: [
            {
              loader: 'css-loader',
              options: {
                sourceMap: true,
                modules: true,
                importLoaders: true,
                localIdentName: '[local]'
              }
            },
            {
              loader: "postcss-loader",
              options: {
                plugins: [
                  postcssDiscardDuplicates,
                  autoprefixer,
                ],
              }
            },
            {
              loader: "clean-css-loader",
              options: {
                skipWarn: true,
                compatibility: "ie9",
                level: process.env.NODE_ENV === "production" ? 2 : 0,
                inline: ["remote"],
                format: 'beautify',
              }
            },
            {
              loader: "sass-loader",
              options: {
                importer: [
                  sassImportGlobbing,
                  npmSass.importer,
                ],
                functions: sassExportData,
                outputStyle: "expanded",
                precision: 2
              }
            }
          ]
        },
        {
          test: /\.js$/,
          exclude: /(node_modules\/\@webcomponents\/webcomponentsjs\/custom-elements-es5-adapter\.js)/,
          use: {
            loader: 'babel-loader',
            options: {
              babelrc: false,
              presets: ['@bolt/babel-preset-bolt'],
            }
          }
        },
      ],
    },
    plugins: [
      // Ignore generated output if generated output is on a dependency chain (causes endless loop)
      new webpack.WatchIgnorePlugin([
        /dist\/styleguide/,
        /dist\/annotations/,
        /styleguide/,
        path.join(__dirname, 'node_modules')
      ]),
      new webpack.HotModuleReplacementPlugin(),
      new webpack.optimize.CommonsChunkPlugin({
        deepChildren: true,
        children: true,
        minChunks: Infinity,
        async: true
      }),
      new webpack.IgnorePlugin(/vertx/), // needed to ignore vertx dependency in webcomponentsjs-lite
      new ExtractTextPlugin({
        filename: "[name].css",
        // disable: false,
        allChunks: true
      }),
      new ManifestPlugin({
        fileName: 'bolt-manifest.json',
        publicPath: config.publicPath,
        writeToFileEmit: true,
        seed: {
          name: 'Bolt Manifest'
        }
      }),
      new webpack.optimize.ModuleConcatenationPlugin(),
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': process.env.NODE_ENV === 'production' ? JSON.stringify(process.env.NODE_ENV) : JSON.stringify('development'),
      }),
      new webpack.ProvidePlugin({
        h: 'preact',
        Promise: 'es6-promise'
      }),
      // Show build progress
      new webpack.ProgressPlugin({ profile: false }),
    ],
    devServer: {
      contentBase: [
        path.resolve(process.cwd(), config.wwwDir),
        // @TODO: add Pattern Lab Styleguidekit Assets Default dist path here
      ],
      compress: true,
      clientLogLevel: 'info',
      port: 8080,
      stats: statsPreset(webpackStats[config.verbosity]),
      overlay: {
        errors: true
      },
      hot: true,
      inline: true,
      publicPath: config.publicPath,
      watchContentBase: true,
      historyApiFallback: true,
      watchOptions: {
        aggregateTimeout: 500,
        // ignored: /(annotations|fonts|bower_components|dist\/styleguide|node_modules|styleguide|images|fonts|assets)/
        // Poll using interval (in ms, accepts boolean too)
        poll: true,
      }
    }
  };
}

module.exports = createConfig;
<|endoftext|>