<commit_before>/* eslint-disable jsx-a11y/label-has-for */
import PropTypes from 'prop-types';
import React from 'react';
import TinyMCE from 'react-tinymce';
import { css } from 'glamor';
import labeled from '../HOC/labeled';
import commonView from '../HOC/commonView';
import './../../../wegas-editor/js/plugin/wegas-tinymce-dynamictoolbar';
import { getY } from './../index';
import FormStyles from './form-styles';

const marginStyle = css({
    label: 'html-marginstyle',
    width: FormStyles.textInputWidth,
    marginTop: '4px',
    fontSize: '13px',
    minHeight: '145px',
    maxHeight: '500px',
    minWidth: '50px',
    overflow: 'auto',
    color: 'darkslategrey',
    backgroundColor: 'white',
    resize: 'both',
    '& > div': {
        // The inline DIV must fill up the entire container except a small (bottom) margin for the resize handle
        minHeight: 'calc( 100% - 15px )',
        boxSizing: 'border-box',
        // outline: 'none !important',
    },
});

const Wegas = getY().Wegas;

function onFileBrowserClick(fieldName, url, type, win) {
    const filePanel = new Wegas.FileSelect();

    filePanel.after('*:fileSelected', (e, path) => {
        e.stopImmediatePropagation();
        e.preventDefault();

        const window = filePanel.win;
        const targetInput = window.document.getElementById(
            filePanel.field_name
        );
        targetInput.value = Wegas.Facade.File.getPath() + path; // update the input field

        if (typeof window.ImageDialog !== 'undefined') {
            // are we an image browser
            if (window.ImageDialog.getImageData) {
                // we are, so update image dimensions...
                window.ImageDialog.getImageData();
            }

            if (window.ImageDialog.showPreviewImage) {
                // ... and preview if necessary
                window.ImageDialog.showPreviewImage(
                    Wegas.Facade.File.getPath() + path
                );
            }
        }
        if (window.Media) {
            // If in an editor window
            window.Media.formToData('src'); // update the data
        }
        filePanel.destroy();
    });
    filePanel.win = win;
    filePanel.field_name = fieldName;
    return false;
}

const TINY_CONFIG = {
    inline: false,
    plugins: [
        'autolink link image lists code media table contextmenu',
        'paste advlist textcolor dynamic_toolbar',
        // textcolor wordcount autosave
        // advlist charmap print preview hr anchor pagebreak spellchecker
        // directionality
    ],
    toolbar1: 'bold italic bullist | link image media code addToolbarButton',
    toolbar2: `forecolor backcolor underline
             alignleft aligncenter alignright alignjustify table`,
    toolbar3: 'fontselect fontsizeselect styleselect',
    // formatselect removeformat underline unlink forecolor backcolor anchor previewfontselect
    // fontsizeselect styleselect spellchecker template
    // contextmenu: 'link image inserttable | cell row
    // column deletetable | formatselect forecolor',
    menubar: false,
    statusbar: false,
    relative_urls: false,
    toolbar_items_size: 'small',
    hidden_tootlbar: [2, 3],
    file_browser_callback: onFileBrowserClick,
    image_advtab: true,
    content_css: [
        `${Wegas.app.get('base')}wegas-editor/css/wegas-inputex-rte.css`,
    ],
    style_formats: [
        {
            // Style formats
            title: 'Title 1',
            block: 'h1',
        },
        {
            title: 'Title 2',
            block: 'h2',
            // styles : {
            //    color : '#ff0000'
            // }
        },
        {
            title: 'Title 3',
            block: 'h3',
        },
        {
            title: 'Normal',
            inline: 'span',
        },
        {
            title: 'Code',
            // icon: 'code',
            block: 'code',
        },
    ],
    // setup: function setup(editor) {
    //     let tbs;
    //     editor.on('init', () => {
    //         tbs = editor.contentAreaContainer.parentElement
    //             .querySelectorAll('div.mce-toolbar-grp');
    //         tbs.forEach(e => { e.style.maxHeight = 0; e.style.overflow = 'hidden'; });
    //     });
    //     editor.on('focus', () => tbs.forEach(e => { e.style.maxHeight = '90px'; }));
    //     editor.on('blur', () => tbs.forEach(e => { e.style.maxHeight = 0; }));
    // }
};
/**
 * Replace data-file attribute with complete href and src
 * @param {string} content
 */
function toTinyMCE(content) {
    let updated = content;
    if (updated === null || typeof content !== 'string') {
        updated = undefined;
    }
    if (updated && Wegas.Facade.File) {
        updated = updated.replace(
            new RegExp('data-file="([^"]*)"', 'gi'),
            `src="${Wegas.Facade.File.getPath()}$1"
             href="${Wegas.Facade.File.getPath()}$1"`
        ); // @hack Place both href and src so it
        // will work for both  and
        // elements
    }
    return updated;
}
/**
 * Replace href/src with injector style data-file attribute
 * @param {string} content
 */
function toInjectorStyle(content) {
    // remove yui ids
    const root = document.createElement('div');
    root.innerHTML = content;
    const yuiId = root.querySelectorAll('[id^="yui_"]');
    for (let n = 0; n < yuiId.length; n += 1) {
        yuiId[n].removeAttribute('id');
    }

    return root.innerHTML
        .replace(
            new RegExp(
                '((src|href)="[^"]*/rest/File/GameModelId/[^"]*/read([^"]*)")',
                'gi'
            ),
            'data-file="$3"'
        ) // Replace absolute path with injector style path (old version)
        .replace(
            new RegExp(
                '((src|href)="[^"]*/rest/GameModel/[^"]*/File/read([^"]*)")',
                'gi'
            ),
            'data-file="$3"'
        ); // Replace absolute path with injector style path
}
class HTMLView extends React.Component {
    constructor(props) {
        super(props);
        this.state = { key: 0, content: props.value };
        this.onChangeHandler = this.onChangeHandler.bind(this);
        this.doNotCheck = false;
    }
    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.content) {
            // Generate a new key to force TinyMCE to re-render.
            this.setState({
                key: (this.state.key + 1) % 100, // avoid potential overflow
                content: nextProps.value,
            });
            this.doNotCheck = true;
        }
    }

    componentDidUpdate() {
        this.doNotCheck = false;
    }

    // Listens both to tinyMCE's synthetic 'change' events and to its basic 'onKeyup' events.
    // NB: the event parameter is not the same in both cases.
    onChangeHandler() {
        if (this.doNotCheck) {
            return;
        }
        const oldContent = this.state.content;
        const newContent = toInjectorStyle(tinymce.activeEditor.getContent());
        if (oldContent !== newContent) {
            this.setState({ content: newContent }, () =>
                this.props.onChange(newContent)
            );
        }
    }

    // A click on the container transfers the focus to the inner DIV containing TinyMCE.
    onClickHandler(event) {
        const elem = event.target.firstChild;
        if (elem && elem.focus) {
            elem.focus();
        }
    }

    render() {
        return (

                <TinyMCE
                    key={this.state.key}
                    content={toTinyMCE(this.state.content)}
                    config={TINY_CONFIG}
                    onChange={this.onChangeHandler}
                    onKeyup={this.onChangeHandler}
                />

        );
    }
}
HTMLView.propTypes = {
    onChange: PropTypes.func.isRequired,
    value: PropTypes.string,
};

export default commonView(labeled(HTMLView));
<commit_msg>html fix resize<commit_after>/* eslint-disable jsx-a11y/label-has-for */
import PropTypes from 'prop-types';
import React from 'react';
import TinyMCE from 'react-tinymce';
import { css } from 'glamor';
import labeled from '../HOC/labeled';
import commonView from '../HOC/commonView';
import './../../../wegas-editor/js/plugin/wegas-tinymce-dynamictoolbar';
import { getY } from './../index';
import FormStyles from './form-styles';

const marginStyle = css({
    width: FormStyles.textInputWidth,
});

const Wegas = getY().Wegas;

function onFileBrowserClick(fieldName, url, type, win) {
    const filePanel = new Wegas.FileSelect();

    filePanel.after('*:fileSelected', (e, path) => {
        e.stopImmediatePropagation();
        e.preventDefault();

        const window = filePanel.win;
        const targetInput = window.document.getElementById(
            filePanel.field_name
        );
        targetInput.value = Wegas.Facade.File.getPath() + path; // update the input field

        if (typeof window.ImageDialog !== 'undefined') {
            // are we an image browser
            if (window.ImageDialog.getImageData) {
                // we are, so update image dimensions...
                window.ImageDialog.getImageData();
            }

            if (window.ImageDialog.showPreviewImage) {
                // ... and preview if necessary
                window.ImageDialog.showPreviewImage(
                    Wegas.Facade.File.getPath() + path
                );
            }
        }
        if (window.Media) {
            // If in an editor window
            window.Media.formToData('src'); // update the data
        }
        filePanel.destroy();
    });
    filePanel.win = win;
    filePanel.field_name = fieldName;
    return false;
}

const TINY_CONFIG = {
    inline: false,
    plugins: [
        'autolink link image lists code media table contextmenu',
        'paste advlist textcolor dynamic_toolbar',
        // textcolor wordcount autosave
        // advlist charmap print preview hr anchor pagebreak spellchecker
        // directionality
    ],
    toolbar1: 'bold italic bullist | link image media code addToolbarButton',
    toolbar2: `forecolor backcolor underline
             alignleft aligncenter alignright alignjustify table`,
    toolbar3: 'fontselect fontsizeselect styleselect',
    // formatselect removeformat underline unlink forecolor backcolor anchor previewfontselect
    // fontsizeselect styleselect spellchecker template
    // contextmenu: 'link image inserttable | cell row
    // column deletetable | formatselect forecolor',
    menubar: false,
    resize: 'both',
    max_height: 500,
    statusbar: true,
    branding: false,
    relative_urls: false,
    toolbar_items_size: 'small',
    hidden_tootlbar: [2, 3],
    file_browser_callback: onFileBrowserClick,
    image_advtab: true,
    content_css: [
        `${Wegas.app.get('base')}wegas-editor/css/wegas-inputex-rte.css`,
    ],
    style_formats: [
        {
            // Style formats
            title: 'Title 1',
            block: 'h1',
        },
        {
            title: 'Title 2',
            block: 'h2',
            // styles : {
            //    color : '#ff0000'
            // }
        },
        {
            title: 'Title 3',
            block: 'h3',
        },
        {
            title: 'Normal',
            inline: 'span',
        },
        {
            title: 'Code',
            // icon: 'code',
            block: 'code',
        },
    ],
    // setup: function setup(editor) {
    //     let tbs;
    //     editor.on('init', () => {
    //         tbs = editor.contentAreaContainer.parentElement
    //             .querySelectorAll('div.mce-toolbar-grp');
    //         tbs.forEach(e => { e.style.maxHeight = 0; e.style.overflow = 'hidden'; });
    //     });
    //     editor.on('focus', () => tbs.forEach(e => { e.style.maxHeight = '90px'; }));
    //     editor.on('blur', () => tbs.forEach(e => { e.style.maxHeight = 0; }));
    // }
};
/**
 * Replace data-file attribute with complete href and src
 * @param {string} content
 */
function toTinyMCE(content) {
    let updated = content;
    if (updated === null || typeof content !== 'string') {
        updated = undefined;
    }
    if (updated && Wegas.Facade.File) {
        updated = updated.replace(
            new RegExp('data-file="([^"]*)"', 'gi'),
            `src="${Wegas.Facade.File.getPath()}$1"
             href="${Wegas.Facade.File.getPath()}$1"`
        ); // @hack Place both href and src so it
        // will work for both  and
        // elements
    }
    return updated;
}
/**
 * Replace href/src with injector style data-file attribute
 * @param {string} content
 */
function toInjectorStyle(content) {
    // remove yui ids
    const root = document.createElement('div');
    root.innerHTML = content;
    const yuiId = root.querySelectorAll('[id^="yui_"]');
    for (let n = 0; n < yuiId.length; n += 1) {
        yuiId[n].removeAttribute('id');
    }

    return root.innerHTML
        .replace(
            new RegExp(
                '((src|href)="[^"]*/rest/File/GameModelId/[^"]*/read([^"]*)")',
                'gi'
            ),
            'data-file="$3"'
        ) // Replace absolute path with injector style path (old version)
        .replace(
            new RegExp(
                '((src|href)="[^"]*/rest/GameModel/[^"]*/File/read([^"]*)")',
                'gi'
            ),
            'data-file="$3"'
        ); // Replace absolute path with injector style path
}
class HTMLView extends React.Component {
    constructor(props) {
        super(props);
        this.state = { key: 0, content: props.value };
        this.onChangeHandler = this.onChangeHandler.bind(this);
        this.doNotCheck = false;
    }
    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.content) {
            // Generate a new key to force TinyMCE to re-render.
            this.setState({
                key: (this.state.key + 1) % 100, // avoid potential overflow
                content: nextProps.value,
            });
            this.doNotCheck = true;
        }
    }

    componentDidUpdate() {
        this.doNotCheck = false;
    }

    // Listens both to tinyMCE's synthetic 'change' events and to its basic 'onKeyup' events.
    // NB: the event parameter is not the same in both cases.
    onChangeHandler() {
        if (this.doNotCheck) {
            return;
        }
        const oldContent = this.state.content;
        const newContent = toInjectorStyle(tinymce.activeEditor.getContent());
        if (oldContent !== newContent) {
            this.setState({ content: newContent }, () =>
                this.props.onChange(newContent)
            );
        }
    }

    // A click on the container transfers the focus to the inner DIV containing TinyMCE.
    onClickHandler(event) {
        const elem = event.target.firstChild;
        if (elem && elem.focus) {
            elem.focus();
        }
    }

    render() {
        return (

                <TinyMCE
                    key={this.state.key}
                    content={toTinyMCE(this.state.content)}
                    config={TINY_CONFIG}
                    onChange={this.onChangeHandler}
                    onKeyup={this.onChangeHandler}
                />

        );
    }
}
HTMLView.propTypes = {
    onChange: PropTypes.func.isRequired,
    value: PropTypes.string,
};

export default commonView(labeled(HTMLView));
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Denisov21. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
// Russian by Ent-ch
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */
define({
    "RIGHT_CLICK_MENU_UNDO_NAME"         : "Отменить",
    "RIGHT_CLICK_MENU_CUT_NAME"          : "Вырезать",
    "RIGHT_CLICK_MENU_COPY_NAME"         : "Копировать",
    "RIGHT_CLICK_MENU_PASTE_NAME"        : "Вставить",
    "RIGHT_CLICK_MENU_UPPERCASE_NAME"    : "Прописные",
    "RIGHT_CLICK_MENU_LOWERCASE_NAME"    : "Строчные",
    "RIGHT_CLICK_MENU_CAMELCASE_NAME"    : "Верблюжий стиль",
    "RIGHT_CLICK_MENU_BLOCKCOMMENT_NAME" : "Преобразовать в блочн. комментарий",
    "RIGHT_CLICK_MENU_LINECOMMENT_NAME"  : "Преобразовать в строчн. комментарий",
    "RIGHT_CLICK_MENU_SAVEALL_NAME"      : "Сохранить все",
	"RIGHT_CLICK_MENU_CONVERTTO_NAME"    : "Преобразовать в",
	"RIGHT_CLICK_MENU_ENCODE_HTMLENTITY_NAME" : "Кодировать в HTML",
	"RIGHT_CLICK_MENU_ENCODE_NAMEDHTMLENTITY_NAME" : "Кодировать в именной HTML",
	"RIGHT_CLICK_MENU_DECODE_HTMLENTITY_NAME" : "Декодировать HTML",
	"RIGHT_CLICK_MENU_ENCODE_URI_NAME" : "Кодировать URI",
	"RIGHT_CLICK_MENU_DECODE_URI_NAME" : "Декодировать URI"
});
<commit_msg>Update strings.js<commit_after>/*
 * Copyright (c) 2014 Denisov21. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */
// Russian by Ent-ch
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */
define({
    "RIGHT_CLICK_MENU_UNDO_NAME"         : "Отменить",
    "RIGHT_CLICK_MENU_CUT_NAME"          : "Вырезать",
    "RIGHT_CLICK_MENU_COPY_NAME"         : "Копировать",
    "RIGHT_CLICK_MENU_PASTE_NAME"        : "Вставить",
    "RIGHT_CLICK_MENU_UPPERCASE_NAME"    : "Прописные",
    "RIGHT_CLICK_MENU_LOWERCASE_NAME"    : "Строчные",
    "RIGHT_CLICK_MENU_CAMELCASE_NAME"    : "Верблюжий стиль",
    "RIGHT_CLICK_MENU_BLOCKCOMMENT_NAME" : "Преобразовать в блочн. комментарий",
    "RIGHT_CLICK_MENU_LINECOMMENT_NAME"  : "Преобразовать в строчн. комментарий",
    "RIGHT_CLICK_MENU_SAVEALL_NAME"      : "Сохранить все",
	"RIGHT_CLICK_MENU_CONVERTTO_NAME"    : "Преобразовать в",
	"RIGHT_CLICK_MENU_ENCODE_HTMLENTITY_NAME" : "Кодировать в HTML",
	"RIGHT_CLICK_MENU_ENCODE_NAMEDHTMLENTITY_NAME" : "Кодировать в именной HTML",
	"RIGHT_CLICK_MENU_DECODE_HTMLENTITY_NAME" : "Декодировать HTML",
	"RIGHT_CLICK_MENU_ENCODE_URI_NAME" : "Кодировать URI",
	"RIGHT_CLICK_MENU_DECODE_URI_NAME" : "Декодировать URI",
   "RIGHT_CLICK_MENU_UNDO_NAME"  : "Отменить"
});
<|endoftext|>


<commit_before>import Ember from 'ember';
import DS from 'ember-data';

export default DS.RESTSerializer.extend({

  primaryKey: 'objectId',

  extractArray: function( store, primaryType, payload ) {
    var namespacedPayload = {};
    namespacedPayload[ Ember.String.pluralize( primaryType.typeKey ) ] = payload.results;

    return this._super( store, primaryType, namespacedPayload );
  },

  extractSingle: function( store, primaryType, payload, recordId ) {
    var namespacedPayload = {};
    namespacedPayload[ primaryType.typeKey ] = payload; // this.normalize(primaryType, payload);

    return this._super( store, primaryType, namespacedPayload, recordId );
  },

  modelNameFromPayloadKey: function( key ) {
    return Ember.String.dasherize( Ember.String.singularize( key ) );
  },

  /**
  * Because Parse only returns the updatedAt/createdAt values on updates
  * we have to intercept it here to assure that the adapter knows which
  * record ID we are dealing with (using the primaryKey).
  */
  extract: function( store, type, payload, id, requestType ) {
    if( id !== null && ( 'updateRecord' === requestType || 'deleteRecord' === requestType ) ) {
      payload[ this.get( 'primaryKey' ) ] = id;
    }

    return this._super( store, type, payload, id, requestType );
  },

  /**
  * Extracts count from the payload so that you can get the total number
  * of records in Parse if you're using skip and limit.
  */
  extractMeta: function( store, type, payload ) {
    if ( payload && payload.count ) {
      store.setMetadataFor( type, { count: payload.count } );
      delete payload.count;
    }
  },

  /**
  * Special handling for the Date objects inside the properties of
  * Parse responses.
  */
  normalizeAttributes: function( type, hash ) {
    type.eachAttribute( function( key, meta ) {
      if ( 'date' === meta.type && 'object' === Ember.typeOf( hash[key] ) && hash[key].iso ) {
        hash[key] = hash[key].iso; //new Date(hash[key].iso).toISOString();
      }
    });

    this._super( type, hash );
  },

  /**
  * Special handling of the Parse relation types. In certain
  * conditions there is a secondary query to retrieve the "many"
  * side of the "hasMany".
  */
  normalizeRelationships: function( type, hash ) {
    var store      = this.get('store'),
      serializer = this;

    type.eachRelationship( function( key, relationship ) {

      var options = relationship.options;

      // Handle the belongsTo relationships
      if ( hash[key] && 'belongsTo' === relationship.kind ) {
        hash[key] = hash[key].objectId;
      }

      // Handle the hasMany relationships
      if ( hash[key] && 'hasMany' === relationship.kind ) {

        // If this is a Relation hasMany then we need to supply
        // the links property so the adapter can async call the
        // relationship.
        // The adapter findHasMany has been overridden to make use of this.
        //if(options.relation) {
          // hash[key] contains the response of Parse.com: eg {__type: Relation, className: MyParseClassName}
          // this is an object that make ember-data fail, as it expects nothing or an array ids that represent the records
          hash[key] = [];

          // ember-data expects the link to be a string
          // The adapter findHasMany will parse it
          if (!hash.links) {
            hash.links = {};
          }

          hash.links[key] = JSON.stringify({typeKey: relationship.type.typeKey, key: key});
        //}

        if ( options.array ) {
          // Parse will return [null] for empty relationships
          if ( hash[key].length && hash[key] ) {
            hash[key].forEach( function( item, index, items ) {
              // When items are pointers we just need the id
              // This occurs when request was made without the include query param.
              if ( 'Pointer' === item.__type ) {
                items[index] = item.objectId;

              } else {
                // When items are objects we need to clean them and add them to the store.
                // This occurs when request was made with the include query param.
                delete item.__type;
                delete item.className;
                item.id = item.objectId;
                delete item.objectId;
                item.type = relationship.type;
                serializer.normalizeAttributes( relationship.type, item );
                serializer.normalizeRelationships( relationship.type, item );
                store.push( relationship.type, item );
              }
            });
          }
        }
      }
    }, this );

    this._super( type, hash );
  },

  serializeIntoHash: function( hash, type, snapshot, options ) {
    Ember.merge( hash, this.serialize( snapshot, options ) );
  },

  serializeAttribute: function( snapshot, json, key, attribute ) {
    // These are Parse reserved properties and we won't send them.
    if ( 'createdAt' === key ||
         'updatedAt' === key ||
         'emailVerified' === key ||
         'sessionToken' === key
    ) {
      delete json[key];

    } else {
      this._super( snapshot, json, key, attribute );
    }
  },

  serializeBelongsTo: function(snapshot, json, relationship) {
    var key         = relationship.key,
        belongsToId = snapshot.belongsTo(key, { id: true });

    if (belongsToId) {
      json[key] = {
        '__type'    : 'Pointer',
        'className' : this.parseClassName(relationship.type),
        'objectId'  : belongsToId
      };
    }
  },

  parseClassName: function(key) {
    if ('parseUser' === key) {
      return '_User';
    } else {
      return Ember.String.capitalize(Ember.String.camelize(key));
    }
  },

  serializeHasMany: function( snapshot, json, relationship ) {
    var key   = relationship.key,
      hasMany = snapshot.hasMany( key ),
      options = relationship.options,
      _this   = this;

    if ( hasMany && hasMany.get( 'length' ) > 0 ) {
      json[key] = { 'objects': [] };

      // an array is not a relationship, right?

      /*if ( options.relation ) {
        json[key].__op = 'AddRelation';
      }

      if ( options.array ) {
        json[key].__op = 'AddUnique';
      }*/

      json[key].__op = 'AddRelation';

      hasMany.forEach( function( child ) {
        json[key].objects.push({
          '__type'    : 'Pointer',
          'className' : _this.parseClassName(child.type.typeKey),
          'objectId'  : child.id
        });
      });

      if ( hasMany._deletedItems && hasMany._deletedItems.length ) {
        if ( options.relation ) {
          var addOperation    = json[key],
            deleteOperation = { '__op': 'RemoveRelation', 'objects': [] };

          hasMany._deletedItems.forEach( function( item ) {
            deleteOperation.objects.push({
              '__type'    : 'Pointer',
              'className' : item.type,
              'objectId'  : item.id
            });
          });

          json[key] = { '__op': 'Batch', 'ops': [addOperation, deleteOperation] };
        }

        if ( options.array ) {
          json[key].deleteds = { '__op': 'Remove', 'objects': [] };

          hasMany._deletedItems.forEach( function( item ) {
            json[key].deleteds.objects.push({
              '__type'    : 'Pointer',
              'className' : item.type,
              'objectId'  : item.id
            });
          });
        }
      }

    } else {
      json[key] = null;
    }
  }

});
<commit_msg>change relationship.type.typeKey to relationship.type in normalizeRelationships<commit_after>import Ember from 'ember';
import DS from 'ember-data';

export default DS.RESTSerializer.extend({

  primaryKey: 'objectId',

  extractArray: function( store, primaryType, payload ) {
    var namespacedPayload = {};
    namespacedPayload[ Ember.String.pluralize( primaryType.typeKey ) ] = payload.results;

    return this._super( store, primaryType, namespacedPayload );
  },

  extractSingle: function( store, primaryType, payload, recordId ) {
    var namespacedPayload = {};
    namespacedPayload[ primaryType.typeKey ] = payload; // this.normalize(primaryType, payload);

    return this._super( store, primaryType, namespacedPayload, recordId );
  },

  modelNameFromPayloadKey: function( key ) {
    return Ember.String.dasherize( Ember.String.singularize( key ) );
  },

  /**
  * Because Parse only returns the updatedAt/createdAt values on updates
  * we have to intercept it here to assure that the adapter knows which
  * record ID we are dealing with (using the primaryKey).
  */
  extract: function( store, type, payload, id, requestType ) {
    if( id !== null && ( 'updateRecord' === requestType || 'deleteRecord' === requestType ) ) {
      payload[ this.get( 'primaryKey' ) ] = id;
    }

    return this._super( store, type, payload, id, requestType );
  },

  /**
  * Extracts count from the payload so that you can get the total number
  * of records in Parse if you're using skip and limit.
  */
  extractMeta: function( store, type, payload ) {
    if ( payload && payload.count ) {
      store.setMetadataFor( type, { count: payload.count } );
      delete payload.count;
    }
  },

  /**
  * Special handling for the Date objects inside the properties of
  * Parse responses.
  */
  normalizeAttributes: function( type, hash ) {
    type.eachAttribute( function( key, meta ) {
      if ( 'date' === meta.type && 'object' === Ember.typeOf( hash[key] ) && hash[key].iso ) {
        hash[key] = hash[key].iso; //new Date(hash[key].iso).toISOString();
      }
    });

    this._super( type, hash );
  },

  /**
  * Special handling of the Parse relation types. In certain
  * conditions there is a secondary query to retrieve the "many"
  * side of the "hasMany".
  */
  normalizeRelationships: function( type, hash ) {
    var store      = this.get('store'),
      serializer = this;

    type.eachRelationship( function( key, relationship ) {

      var options = relationship.options;

      // Handle the belongsTo relationships
      if ( hash[key] && 'belongsTo' === relationship.kind ) {
        hash[key] = hash[key].objectId;
      }

      // Handle the hasMany relationships
      if ( hash[key] && 'hasMany' === relationship.kind ) {

        // If this is a Relation hasMany then we need to supply
        // the links property so the adapter can async call the
        // relationship.
        // The adapter findHasMany has been overridden to make use of this.
        //if(options.relation) {
          // hash[key] contains the response of Parse.com: eg {__type: Relation, className: MyParseClassName}
          // this is an object that make ember-data fail, as it expects nothing or an array ids that represent the records
          hash[key] = [];

          // ember-data expects the link to be a string
          // The adapter findHasMany will parse it
          if (!hash.links) {
            hash.links = {};
          }

          hash.links[key] = JSON.stringify({typeKey: relationship.type, key: key});
        //}

        if ( options.array ) {
          // Parse will return [null] for empty relationships
          if ( hash[key].length && hash[key] ) {
            hash[key].forEach( function( item, index, items ) {
              // When items are pointers we just need the id
              // This occurs when request was made without the include query param.
              if ( 'Pointer' === item.__type ) {
                items[index] = item.objectId;

              } else {
                // When items are objects we need to clean them and add them to the store.
                // This occurs when request was made with the include query param.
                delete item.__type;
                delete item.className;
                item.id = item.objectId;
                delete item.objectId;
                item.type = relationship.type;
                serializer.normalizeAttributes( relationship.type, item );
                serializer.normalizeRelationships( relationship.type, item );
                store.push( relationship.type, item );
              }
            });
          }
        }
      }
    }, this );

    this._super( type, hash );
  },

  serializeIntoHash: function( hash, type, snapshot, options ) {
    Ember.merge( hash, this.serialize( snapshot, options ) );
  },

  serializeAttribute: function( snapshot, json, key, attribute ) {
    // These are Parse reserved properties and we won't send them.
    if ( 'createdAt' === key ||
         'updatedAt' === key ||
         'emailVerified' === key ||
         'sessionToken' === key
    ) {
      delete json[key];

    } else {
      this._super( snapshot, json, key, attribute );
    }
  },

  serializeBelongsTo: function(snapshot, json, relationship) {
    var key         = relationship.key,
        belongsToId = snapshot.belongsTo(key, { id: true });

    if (belongsToId) {
      json[key] = {
        '__type'    : 'Pointer',
        'className' : this.parseClassName(relationship.type),
        'objectId'  : belongsToId
      };
    }
  },

  parseClassName: function(key) {
    if ('parseUser' === key) {
      return '_User';
    } else {
      return Ember.String.capitalize(Ember.String.camelize(key));
    }
  },

  serializeHasMany: function( snapshot, json, relationship ) {
    var key   = relationship.key,
      hasMany = snapshot.hasMany( key ),
      options = relationship.options,
      _this   = this;

    if ( hasMany && hasMany.get( 'length' ) > 0 ) {
      json[key] = { 'objects': [] };

      // an array is not a relationship, right?

      /*if ( options.relation ) {
        json[key].__op = 'AddRelation';
      }

      if ( options.array ) {
        json[key].__op = 'AddUnique';
      }*/

      json[key].__op = 'AddRelation';

      hasMany.forEach( function( child ) {
        json[key].objects.push({
          '__type'    : 'Pointer',
          'className' : _this.parseClassName(child.type.typeKey),
          'objectId'  : child.id
        });
      });

      if ( hasMany._deletedItems && hasMany._deletedItems.length ) {
        if ( options.relation ) {
          var addOperation    = json[key],
            deleteOperation = { '__op': 'RemoveRelation', 'objects': [] };

          hasMany._deletedItems.forEach( function( item ) {
            deleteOperation.objects.push({
              '__type'    : 'Pointer',
              'className' : item.type,
              'objectId'  : item.id
            });
          });

          json[key] = { '__op': 'Batch', 'ops': [addOperation, deleteOperation] };
        }

        if ( options.array ) {
          json[key].deleteds = { '__op': 'Remove', 'objects': [] };

          hasMany._deletedItems.forEach( function( item ) {
            json[key].deleteds.objects.push({
              '__type'    : 'Pointer',
              'className' : item.type,
              'objectId'  : item.id
            });
          });
        }
      }

    } else {
      json[key] = null;
    }
  }

});
<|endoftext|>


<commit_before>import moment from "moment-timezone";

import { TimeSeries, TimeRange, Event } from "pondjs";

module.exports = {
    getTimezone: function( date ) {
        let tz;
        let tzRe = /\(([^)]+)\)/;
        let out;
        let offset;

        if ( ( typeof date == "undefined" ) || date == null ) {
            return;
        } else if ( date == "Invalid Date" ) {
            tz = "";
            out = "";
        } else {
            tz = tzRe.exec( date );
            if ( typeof tz == "undefined" || tz === null ) {
                // timezone is unknown
                return "";
            } else {
                tz = tz[1];
                let dateObj = new Date( date );
                let dateMoment = moment( dateObj );
                offset = dateMoment.utcOffset() / 60;
                if ( typeof ( offset ) != "undefined" && offset >= 0 ) {
                    offset = "+" + offset;
                }
            }
        }

        out = " (GMT" + offset + ")";
        return out;

    },

    getTimeVars: function (period) {
	let timeframe = period.toString();
	if(timeframe.endsWith("h")||timeframe.endsWith("d")||timeframe.endsWith("w")||timeframe.endsWith("m")||timeframe.endsWith("y"))
        {
                var ch = timeframe.substring(0, timeframe.length - 1);
                var dmy = timeframe.charAt(timeframe.length - 1);
                timeframe = parseFloat(ch);
                switch(dmy){
                        case 'h': timeframe*= 60*60; break;
                        case 'd': timeframe*= 86400; break;
                        case 'w': timeframe*= 86400*7; break;
                        case 'm': timeframe*= 86400*31; break;
                        case 'y': timeframe*= 86400*365;
                }
                timeframe = Math.round(timeframe);
        }
        else{
                timeframe = parseFloat(timeframe);
                timeframe = Math.round(timeframe);
        }

	let timeDiff = timeframe;
        let summaryWindow;
        if (period == '1h') {
            timeDiff = 60*60 * 1;
            summaryWindow = 0;
        } else if (period == '12h') {
            timeDiff = 60*60 * 12;
            summaryWindow = 0;
        } else if (period == '1d') {
            timeDiff = 86400;
            summaryWindow = 300;
        } else if (period == '3d') {
            timeDiff = 86400 * 3;
            summaryWindow = 300;
        } else if (period == '1w') {
            timeDiff = 86400*7;
            summaryWindow = 3600;
        } else if (period == '2w') {
            timeDiff = 86400*14;
            summaryWindow = 3600;
        } else if (period == '3w') {
            timeDiff = 86400*21;
            summaryWindow = 3600;
        }else if (period == '30d') {
            timeDiff = 86400*30;
            summaryWindow = 3600;
        } else if (period == '1m') {
            timeDiff = 86400*31;
            summaryWindow = 3600;
        } else if (period == '1y') {
            timeDiff = 86400*365;
            summaryWindow = 86400;
        }
	else{
                summaryWindow = 86400;
        }
        //period = timeframe;
        let timeRange = {
            timeDiff: timeDiff,
            summaryWindow: summaryWindow,
            timeframe: period
        };
        return timeRange;
    }

};

<commit_msg>summarywindow fix for unit test<commit_after>import moment from "moment-timezone";

import { TimeSeries, TimeRange, Event } from "pondjs";

module.exports = {
    getTimezone: function( date ) {
        let tz;
        let tzRe = /\(([^)]+)\)/;
        let out;
        let offset;

        if ( ( typeof date == "undefined" ) || date == null ) {
            return;
        } else if ( date == "Invalid Date" ) {
            tz = "";
            out = "";
        } else {
            tz = tzRe.exec( date );
            if ( typeof tz == "undefined" || tz === null ) {
                // timezone is unknown
                return "";
            } else {
                tz = tz[1];
                let dateObj = new Date( date );
                let dateMoment = moment( dateObj );
                offset = dateMoment.utcOffset() / 60;
                if ( typeof ( offset ) != "undefined" && offset >= 0 ) {
                    offset = "+" + offset;
                }
            }
        }

        out = " (GMT" + offset + ")";
        return out;

    },

    getTimeVars: function (period) {
	let timeframe = period.toString();
	if(timeframe.endsWith("h")||timeframe.endsWith("d")||timeframe.endsWith("w")||timeframe.endsWith("m")||timeframe.endsWith("y"))
        {
                var ch = timeframe.substring(0, timeframe.length - 1);
                var dmy = timeframe.charAt(timeframe.length - 1);
                timeframe = parseFloat(ch);
                switch(dmy){
                        case 'h': timeframe*= 60*60; break;
                        case 'd': timeframe*= 86400; break;
                        case 'w': timeframe*= 86400*7; break;
                        case 'm': timeframe*= 86400*31; break;
                        case 'y': timeframe*= 86400*365;
                }
                timeframe = Math.round(timeframe);
        }
        else{
                timeframe = parseFloat(timeframe);
                timeframe = Math.round(timeframe);
        }

	let timeDiff = timeframe;
        let summaryWindow;
        if (period == '1h') {
            timeDiff = 60*60 * 1;
            summaryWindow = 0;
        } else if (period == '4h') {
            timeDiff = 60*60 * 4;
            summaryWindow = 0;
        } else if (period == '12h') {
            timeDiff = 60*60 * 12;
            summaryWindow = 0;
        } else if (period == '1d') {
            timeDiff = 86400;
            summaryWindow = 300;
        } else if (period == '3d') {
            timeDiff = 86400 * 3;
            summaryWindow = 300;
        } else if (period == '1w') {
            timeDiff = 86400*7;
            summaryWindow = 3600;
        } else if (period == '2w') {
            timeDiff = 86400*14;
            summaryWindow = 3600;
        } else if (period == '3w') {
            timeDiff = 86400*21;
            summaryWindow = 3600;
        }else if (period == '30d') {
            timeDiff = 86400*30;
            summaryWindow = 3600;
        } else if (period == '1m') {
            timeDiff = 86400*31;
            summaryWindow = 3600;
        } else if (period == '1y') {
            timeDiff = 86400*365;
            summaryWindow = 86400;
        }
	else{
                summaryWindow = 86400;
        }
        //period = timeframe;
        let timeRange = {
            timeDiff: timeDiff,
            summaryWindow: summaryWindow,
            timeframe: period
        };
        return timeRange;
    }

};

<|endoftext|>


<commit_before>const { parse } = require('path');
const webpack = require('webpack');
const { prependEntries, appendEntries } = require('webpack-cfg/tools');
const Html = require('html-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
const commonTemplate = require('../templates');

module.exports = $ => commonTemplate($).cfg('entry.devServerClient', [
  `webpack-dev-server/client?http://${$('dev.server.host')}:${$('dev.server.port')}`,
  'webpack/hot/only-dev-server',
  $('cwd', $('path.test', $('dev.entry.test'))),
]).cfg({
  name: '[dev]',
  target: 'web',
  devtool: $('dev.sourceMap'),
  devServer: $('dev.server'),
  output: {
    publicPath: $('dev.assetsPublicPath'),
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': $('dev.env'),
      'process.type': '"renderer"',
    }),
    new Html(Object.assign({}, $('dev.view.data'), {
      env: JSON.parse($('dev.env.NODE_ENV')),
      title: `${$('package.name')} // ${$('package.description')}`,
      template: `!!pug-loader!${$('path.test', $('dev.view.entry'))}`,
      minify: false,
      inject: false,
    })),
    new webpack.HotModuleReplacementPlugin({ quiet: true }),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.NamedModulesPlugin(),
    new FriendlyErrorsPlugin(),
  ],
});
<commit_msg>fix: order of scripts entry<commit_after>const { parse } = require('path');
const webpack = require('webpack');
const { prependEntries, appendEntries } = require('webpack-cfg/tools');
const Html = require('html-webpack-plugin');
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
const commonTemplate = require('../templates');

module.exports = $ => commonTemplate($).cfg('entry.devServerClient', [
  `webpack-dev-server/client?http://${$('dev.server.host')}:${$('dev.server.port')}`,
  'webpack/hot/only-dev-server',
  $('cwd', $('path.test', $('dev.entry.test'))),
]).cfg({
  name: '[dev]',
  target: 'web',
  devtool: $('dev.sourceMap'),
  devServer: $('dev.server'),
  output: {
    publicPath: $('dev.assetsPublicPath'),
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': $('dev.env'),
      'process.type': '"renderer"',
    }),
    new Html(Object.assign({}, $('dev.view.data'), {
      env: JSON.parse($('dev.env.NODE_ENV')),
      title: `${$('package.name')} // ${$('package.description')}`,
      template: `!!pug-loader!${$('path.test', $('dev.view.entry'))}`,
      minify: false,
      inject: false,
      chunksSortMode: (a, b) => {
        const names = Object.keys($('script.entry'));
        return names.indexOf(b.names[0]) - names.indexOf(a.names[0]);
      },
    })),
    new webpack.HotModuleReplacementPlugin({ quiet: true }),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.NamedModulesPlugin(),
    new FriendlyErrorsPlugin(),
  ],
});
<|endoftext|>


<commit_before>/*
Copyright 2015 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var ReactDOM = require('react-dom');
var sdk = require('matrix-react-sdk');
var Signup = require("matrix-react-sdk/lib/Signup");
var PasswordLogin = require("matrix-react-sdk/lib/components/PasswordLogin");
var CasLogin = require("matrix-react-sdk/lib/components/CasLogin");

/**
 * A wire component which glues together login UI components and Signup logic
 */
module.exports = React.createClass({displayName: 'Login',
    propTypes: {
        onLoggedIn: React.PropTypes.func.isRequired,
        homeserverUrl: React.PropTypes.string,
        identityServerUrl: React.PropTypes.string,
        // login shouldn't know or care how registration is done.
        onRegisterClick: React.PropTypes.func.isRequired
    },

    getDefaultProps: function() {
        return {
            homeserverUrl: 'https://matrix.org/',
            identityServerUrl: 'https://matrix.org/'
        };
    },

    getInitialState: function() {
        return {
            busy: false,
            errorText: null,
            enteredHomeserverUrl: this.props.homeserverUrl,
            enteredIdentityServerUrl: this.props.identityServerUrl
        };
    },

    componentWillMount: function() {
        this._initLoginLogic();
    },

    onPasswordLogin: function(username, password) {
        var self = this;
        self.setState({
            busy: true
        });

        this._loginLogic.loginViaPassword(username, password).then(function(data) {
            self.props.onLoggedIn(data);
        }, function(error) {
            self._setErrorTextFromError(error);
        }).finally(function() {
            self.setState({
                busy: false
            });
        });
    },

    onHsUrlChanged: function(newHsUrl) {
        this._initLoginLogic(newHsUrl);
    },

    onIsUrlChanged: function(newIsUrl) {
        this._initLoginLogic(null, newIsUrl);
    },

    _initLoginLogic: function(hsUrl, isUrl) {
        var self = this;
        hsUrl = hsUrl || this.state.enteredHomeserverUrl;
        isUrl = isUrl || this.state.enteredIdentityServerUrl;

        var loginLogic = new Signup.Login(hsUrl, isUrl);
        this._loginLogic = loginLogic;

        loginLogic.getFlows().then(function(flows) {
            // old behaviour was to always use the first flow without presenting
            // options. This works in most cases (we don't have a UI for multiple
            // logins so let's skip that for now).
            loginLogic.chooseFlow(0);
        }, function(err) {
            self._setErrorTextFromError(err);
        }).finally(function() {
            self.setState({
                busy: false
            });
        });

        this.setState({
            enteredHomeserverUrl: hsUrl,
            enteredIdentityServerUrl: isUrl,
            busy: true,
            errorText: null // reset err messages
        });
    },

    _getCurrentFlowStep: function() {
        return this._loginLogic ? this._loginLogic.getCurrentFlowStep() : null
    },

    _setErrorTextFromError: function(err) {
        if (err.friendlyText) {
            this.setState({
                errorText: err.friendlyText
            });
            return;
        }

        var errCode = err.errcode;
        if (!errCode && err.httpStatus) {
            errCode = "HTTP " + err.httpStatus;
        }
        this.setState({
            errorText: (
                "Error: Problem communicating with the given homeserver " +
                (errCode ? "(" + errCode + ")" : "")
            )
        });
    },

    componentForStep: function(step) {
        switch (step) {
            case 'm.login.password':
                return (
                    <PasswordLogin onSubmit={this.onPasswordLogin} />
                );
            case 'm.login.cas':
                return (
                    <CasLogin />
                );
            default:
                if (!step) {
                    return;
                }
                return (

                    Sorry, this homeserver is using a login which is not
                    recognised by Vector ({step})

                );
        }
    },

    render: function() {
        var Loader = sdk.getComponent("atoms.Spinner");
        var loader = this.state.busy ?
<Loader />
 : null;
        var ServerConfig = sdk.getComponent("molecules.ServerConfig");

        return (

Sign in

                        {this.componentForStep(this._getCurrentFlowStep())}
                        <ServerConfig ref="serverConfig"
                            withToggleButton={true}
                            defaultHsUrl={this.props.homeserverUrl}
                            defaultIsUrl={this.props.identityServerUrl}
                            onHsUrlChanged={this.onHsUrlChanged}
                            onIsUrlChanged={this.onIsUrlChanged}
                            delayTimeMs={1000}/>

                                { loader }
                                {this.state.errorText}

                            Create a new account

                            blog  ·
                            twitter  ·
                            github  ·
                            powered by Matrix

        );
    }
});
<commit_msg>Vector is the default IS in Vector<commit_after>/*
Copyright 2015 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var ReactDOM = require('react-dom');
var sdk = require('matrix-react-sdk');
var Signup = require("matrix-react-sdk/lib/Signup");
var PasswordLogin = require("matrix-react-sdk/lib/components/PasswordLogin");
var CasLogin = require("matrix-react-sdk/lib/components/CasLogin");

/**
 * A wire component which glues together login UI components and Signup logic
 */
module.exports = React.createClass({displayName: 'Login',
    propTypes: {
        onLoggedIn: React.PropTypes.func.isRequired,
        homeserverUrl: React.PropTypes.string,
        identityServerUrl: React.PropTypes.string,
        // login shouldn't know or care how registration is done.
        onRegisterClick: React.PropTypes.func.isRequired
    },

    getDefaultProps: function() {
        return {
            homeserverUrl: 'https://matrix.org/',
            identityServerUrl: 'https://vector.im'
        };
    },

    getInitialState: function() {
        return {
            busy: false,
            errorText: null,
            enteredHomeserverUrl: this.props.homeserverUrl,
            enteredIdentityServerUrl: this.props.identityServerUrl
        };
    },

    componentWillMount: function() {
        this._initLoginLogic();
    },

    onPasswordLogin: function(username, password) {
        var self = this;
        self.setState({
            busy: true
        });

        this._loginLogic.loginViaPassword(username, password).then(function(data) {
            self.props.onLoggedIn(data);
        }, function(error) {
            self._setErrorTextFromError(error);
        }).finally(function() {
            self.setState({
                busy: false
            });
        });
    },

    onHsUrlChanged: function(newHsUrl) {
        this._initLoginLogic(newHsUrl);
    },

    onIsUrlChanged: function(newIsUrl) {
        this._initLoginLogic(null, newIsUrl);
    },

    _initLoginLogic: function(hsUrl, isUrl) {
        var self = this;
        hsUrl = hsUrl || this.state.enteredHomeserverUrl;
        isUrl = isUrl || this.state.enteredIdentityServerUrl;

        var loginLogic = new Signup.Login(hsUrl, isUrl);
        this._loginLogic = loginLogic;

        loginLogic.getFlows().then(function(flows) {
            // old behaviour was to always use the first flow without presenting
            // options. This works in most cases (we don't have a UI for multiple
            // logins so let's skip that for now).
            loginLogic.chooseFlow(0);
        }, function(err) {
            self._setErrorTextFromError(err);
        }).finally(function() {
            self.setState({
                busy: false
            });
        });

        this.setState({
            enteredHomeserverUrl: hsUrl,
            enteredIdentityServerUrl: isUrl,
            busy: true,
            errorText: null // reset err messages
        });
    },

    _getCurrentFlowStep: function() {
        return this._loginLogic ? this._loginLogic.getCurrentFlowStep() : null
    },

    _setErrorTextFromError: function(err) {
        if (err.friendlyText) {
            this.setState({
                errorText: err.friendlyText
            });
            return;
        }

        var errCode = err.errcode;
        if (!errCode && err.httpStatus) {
            errCode = "HTTP " + err.httpStatus;
        }
        this.setState({
            errorText: (
                "Error: Problem communicating with the given homeserver " +
                (errCode ? "(" + errCode + ")" : "")
            )
        });
    },

    componentForStep: function(step) {
        switch (step) {
            case 'm.login.password':
                return (
                    <PasswordLogin onSubmit={this.onPasswordLogin} />
                );
            case 'm.login.cas':
                return (
                    <CasLogin />
                );
            default:
                if (!step) {
                    return;
                }
                return (

                    Sorry, this homeserver is using a login which is not
                    recognised by Vector ({step})

                );
        }
    },

    render: function() {
        var Loader = sdk.getComponent("atoms.Spinner");
        var loader = this.state.busy ?
<Loader />
 : null;
        var ServerConfig = sdk.getComponent("molecules.ServerConfig");

        return (

Sign in

                        {this.componentForStep(this._getCurrentFlowStep())}
                        <ServerConfig ref="serverConfig"
                            withToggleButton={true}
                            defaultHsUrl={this.props.homeserverUrl}
                            defaultIsUrl={this.props.identityServerUrl}
                            onHsUrlChanged={this.onHsUrlChanged}
                            onIsUrlChanged={this.onIsUrlChanged}
                            delayTimeMs={1000}/>

                                { loader }
                                {this.state.errorText}

                            Create a new account

                            blog  ·
                            twitter  ·
                            github  ·
                            powered by Matrix

        );
    }
});
<|endoftext|>


<commit_before>// Main Project Config
// https://www.npmjs.com/package/config

'use strict';

const extend = require('extend');
const baseConfig = require('../app/core/config');
const defaultConfig = {
	assets: require('./default/assets'),
	code: {
		compatibility: {
			browserslist: ['> 1%', 'last 2 versions', 'ie 9', 'android 4', 'Firefox ESR', 'Opera 12.1',],
		},
		validation: {
			eslint: {
				live: true,
			},
			htmllint: {
				live: true,
			},
			jsonSchema: {
				live: true,
				logMissingSchemaAsError: false,
				logMissingSchemaAsWarning: true,
			},
			stylelint: {
				live: true,
			},
		},
	},
	nitro: {
		patterns: require('./default/patterns'),
		mode: {
			livereload: true,
			minified: false,
			offline: false,
		},
		watch: {
			partials: true,
			throttle: {
				base: 1000,
				cache: 3000,
			},
		},
	},
	server: {
		port: 8080,
		proxy: 8081,
	},<% if (options.exporter) { %>
	exporter: require('./default/exporter'),<% } %><% if (options.release) { %>
	release: require('./default/release'),<% } %>
};

const config = extend(true, {}, baseConfig, defaultConfig);

module.exports = config;
<commit_msg>#91 fix comma issue<commit_after>// Main Project Config
// https://www.npmjs.com/package/config

'use strict';

const extend = require('extend');
const baseConfig = require('../app/core/config');
const defaultConfig = {
	assets: require('./default/assets'),
	code: {
		compatibility: {
			browserslist: ['> 1%', 'last 2 versions', 'ie 9', 'android 4', 'Firefox ESR', 'Opera 12.1'],
		},
		validation: {
			eslint: {
				live: true,
			},
			htmllint: {
				live: true,
			},
			jsonSchema: {
				live: true,
				logMissingSchemaAsError: false,
				logMissingSchemaAsWarning: true,
			},
			stylelint: {
				live: true,
			},
		},
	},
	nitro: {
		patterns: require('./default/patterns'),
		mode: {
			livereload: true,
			minified: false,
			offline: false,
		},
		watch: {
			partials: true,
			throttle: {
				base: 1000,
				cache: 3000,
			},
		},
	},
	server: {
		port: 8080,
		proxy: 8081,
	},<% if (options.exporter) { %>
	exporter: require('./default/exporter'),<% } %><% if (options.release) { %>
	release: require('./default/release'),<% } %>
};

const config = extend(true, {}, baseConfig, defaultConfig);

module.exports = config;
<|endoftext|>


<commit_before>const getStyleRule = require('../utils/get_style_rule')

module.exports = getStyleRule(/\.(scss|sass)$/i, false, [
  {
    loader: 'sass-loader',
    options: { sourceMap: true }
  }
])
<commit_msg>Support .(sass|scss).erb (#2259)<commit_after>const getStyleRule = require('../utils/get_style_rule')

module.exports = getStyleRule(/\.(scss|sass)(\.erb)?$/i, false, [
  {
    loader: 'sass-loader',
    options: { sourceMap: true }
  }
])
<|endoftext|>


<commit_before>// Generated on 2014-07-01 using generator-angular 0.9.2
'use strict';

/* jshint camelcase: false */

var fs = require('fs');
var modRewrite = require('connect-modrewrite');

module.exports = function(grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  var getCreds = function() {
    var path = 'credentials.json';
    return (fs.existsSync(path)) ? grunt.file.readJSON(path) : {};
  };

  var mainFiles = ['<%%= yeoman.app %>/components/*/{,*/}*.js', '<%%= yeoman.app %>/common/*/{,*/}*.js', '<%%= yeoman.app %>/app.js'];
  var testFiles = ['<%%= yeoman.app %>/components/*/{,*/*}*.spec.js', '<%%= yeoman.app %>/common/*/{,*/*}*.spec.js'];
  var htmlFiles = ['components/*/views/{,*/}*.html', 'common/*/views/{,*/}*.html'];
  var includeSourceFiles = {
    'app/index.html': 'app/index.html',
    'app/assets/styles/main.scss': 'app/assets/styles/main.scss'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,
    creds: getCreds(),

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: mainFiles,
        tasks: ['newer:jshint:all', 'newer:includeSource'],
        options: {
          livereload: '<%%= connect.options.livereload %>'
        }
      },
      compass: {
        files: ['<%%= yeoman.app %>/**/*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer', 'newer:includeSource']
      },
      indexHtml: {
        files: ['<%%= yeoman.app %>/index.html'],
        tasks: ['newer:includeSource']
      },
      livereload: {
        options: {
          livereload: '<%%= connect.options.livereload %>'
        },
        files: [
        '<%%= yeoman.app %>/components/*/views/{,*/}*.html',
        '<%%= yeoman.app %>/common/*/views/{,*/}*.html',
        '<%%= yeoman.app %>/index.html',
        '.tmp/assets/styles/{,*/}*.css',
        '<%%= yeoman.app %>/assets/images/{,*/*}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },
    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        hostname: '0.0.0.0',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function(connect) {
            return [
            modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\woff|\\ttf|\\.png|\\.jpg|\\swf$ /index.html [L]']),
            connect.static('.tmp'),
            connect().use(
            '/bower_components',
            connect.static('./bower_components')
            ),
            connect.static(appConfig.app),
            connect().use(
            '/vendor',
            connect.static('./app/assets/vendor')
            ),
            connect().use(
              '/images',
              connect.static('./app/assets/images')
            )
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function(connect) {
            return [
            connect.static('.tmp'),
            connect.static('test'),
            connect().use(
            '/bower_components',
            connect.static('./bower_components')
            ),
            connect.static(appConfig.app)
            ];
          }
        }
      },
      doc: {
        options: {
          open: true,
          keepalive: true,
          port: 9002,
          base: 'doc'
        }
      },
      dist: {
        options: {
          open: true,
          port: 9002,
          keepalive: true,
          base: '<%%= yeoman.dist %>'
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
        'Gruntfile.js',
        mainFiles
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: testFiles
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
          '.tmp',
          '<%%= yeoman.dist %>/{,*/}*',
          '!<%%= yeoman.dist %>/.git*'
          ]
        }]
      },
      server: '.tmp',
      doc: 'doc/'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 2 versions', 'ie 9']
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/assets/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/assets/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%%= yeoman.app %>/index.html'],
        ignorePath: /\.\.\//,
        overrides: {
          'angulartics': {
            main: ['src/angulartics.js', 'src/angulartics-ga.js']
          }
        }
      },
      sass: {
        src: ['<%%= yeoman.app %>/{,*/}*.{scss,sass}'],
        ignorePath: /\.\.\.\//
      },
      testKarma: {
          src: ['test/karma.conf.js'],
          fileTypes: {
            js: {
              block: /(([\s\t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          },
          devDependencies: true,
          exclude: [/jasmine/]
      }
    },
    /* STYLES SECTION */
    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%%= yeoman.app %>/',
        cssDir: '.tmp',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%%= yeoman.app %>/assets/images',
        javascriptsDir: '<%%= yeoman.app %>/(components|common)/{,*/}*',
        fontsDir: '<%%= yeoman.app %>/assets/fonts',
        importPath: [
        'bower_components/'
        ],
        httpImagesPath: '/assets/images',
        httpGeneratedImagesPath: '/assets/images/generated',
        httpFontsPath: '/assets/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\nEncoding.default_external = "UTF-8"\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    },
    /* ENDS STYLES SECTION */
    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
        '<%%= yeoman.dist %>/scripts/{,*/}*.js',
        '<%%= yeoman.dist %>/assets/styles/{,*/}*.css',
        '<%%= yeoman.dist %>/assets/images/{,*/*}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%%= yeoman.dist %>/index.html',
      options: {
        dest: '<%%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%%= yeoman.dist %>/*.html', '<%%= yeoman.dist %>/components/*/views/{,*/}*.html', '<%%= yeoman.dist %>/common/*/views/{,*/}*.html'],
      htmlExtra: ['<%%= yeoman.dist %>/*.html', '<%%= yeoman.dist %>/components/*/views/{,*/*}*.html', '<%%= yeoman.dist %>/common/*/views/{,*/*}*.html', '<%%= yeoman.dist %>/{,*/}*.js'],
      css: ['<%%= yeoman.dist %>/assets/styles/{,*/}*.css'],
      options: {
        assetsDirs: ['<%%= yeoman.dist %>', '<%%= yeoman.dist %>/assets', '<%%= yeoman.dist %>/assets/images', '<%%= yeoman.dist %>/assets/images/{,*/*}*'],
        patterns: {
          htmlExtra: [
          [/(images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the angular directives that ref revved images']
          ]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   options: {
    //     target: '.tmp/styles/*.css',
    //     relativeTo: '.tmp/styles/'
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%%= yeoman.app %>/assets/images',
          src: ['**/*.{png,jpg,jpeg,gif}'],
          dest: '<%%= yeoman.dist %>/assets/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%%= yeoman.app %>/assets/images',
          src: '{,*/}*.svg',
          dest: '<%%= yeoman.dist %>/assets/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%%= yeoman.dist %>',
          src: ['*.html', htmlFiles],
          dest: '<%%= yeoman.dist %>'
        }]
      }
    },

    // ngAnnotate tries to make the code safe for minification automatically by
    // using the Angular long form for dependency injection. It doesn't work on
    // things like resolve or inject so those have to be done manually.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%%= yeoman.dist %>/*.html']
      }
    },

    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%%= yeoman.app %>',
          dest: '<%%= yeoman.dist %>',
          src: [
          '*.{ico,png,txt}',
          '.htaccess',
          '*.html',
          htmlFiles,
          'assets/images/{,*/*}*.{webp}',
          'assets/fonts/**/*',
          'locales/*.json'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%%= yeoman.dist %>/images',
          src: ['generated/*']
        }]
      },
      styles: {
        expand: true,
        cwd: '<%%= yeoman.app %>/assets/styles',
        dest: '.tmp/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
      'compass:server'
      ],
      test: [
      'compass'
      ],
      dist: [
      'compass:dist',
      'imagemin',
      'svgmin'
      ]
    },

    // Test settings

    //units
    karma: {
      options: {
        configFile: 'test/karma.conf.js',
      },
      unit: {
        singleRun: false,
      }
    },
    /*
    		 ***************************** NGTEMPLATES TASKS *****************************
    		 */
    ngtemplates: {
      app: {
        cwd: '<%%= yeoman.app %>/',
        src: htmlFiles,
        dest: 'app/templates.js',
        options: {
          module: '<%= appName %>',
          usemin: 'scripts/scripts.js'
        }
      }
    },
    /*
    		 ***************************** NGDOCS TASKS *****************************
    		 */
    ngdocs: {
      options: {
        dest: 'doc',
        scripts: ['bower_components/angular/angular.js'],
        html5Mode: false,
        startPage: '/',
        title: '<%= appName %>',
        titleLink: '/',
        bestMatch: true,
      },
      common: {
        src: ['app/common/**/{*,/}*.js'],
        title: '<%= appName %> common'
      }
    },
    /*
    		 ***************************** END NGDOCS TASKS *****************************
    		 */
         /**
              * INCLUDE AUTOMATICALLY SCRIPTS FROM COMMON AND COMPONENTS INTO INDEX
              */
              includeSource: {
                mainTarget: {
                  options: {
                    ordering: 'top-down'
                  },
                  files: includeSourceFiles
                }
              },
             /**
              * END INCLUDE
              */
    ngconstant: {
      options: {
        name: '<%= appName %>.env',
        dest: '<%%= yeoman.app %>/common/env/env.js',
        wrap: '\'use strict\';\n\n/**\n* Env module.\n* @ngdoc overview\n* @name Env\n* @description\n*\n* # Main module of the feature.\n*/\n\n(function() {\n  {%= __ngModule %}\n\n})();'
      },
      dev: {
        constants: {
          API: 'https://alpha.<%= appName %>.com/api/',
          environment: 'dev'
        }
      },
      beta: {
        constants: {
          API: 'https://beta.<%= appName %>.com/api/',
          environment: 'beta'
        }
      },
      production: {
        constants: {
          API: 'https://<%= appName %>.com/api/',
          environment: 'production'
        }
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function(target) {
    switch (target) {
      case 'dist':
        return grunt.task.run(['build', 'connect:dist:keepalive']);
        break;
      case 'alpha':
        grunt.task.run('ngconstant:dev');
        break;
    }

    grunt.task.run([
    'clean:server',
    'wiredep',
    'concurrent:server',
    'autoprefixer',
    'includeSource',
    'connect:livereload',
    'watch'
    ]);
  });

  var env = process.env.NODE_ENV;

  grunt.registerTask('build', function() {
    var tasks = [];
      switch (env) {
        case 'beta':
        case 'production': {
          tasks.push('ngconstant:' + env);
          break;
        }
        case 'local': {
          tasks.push('ngconstant:' + env);
          break;
        }
        default: {
          tasks.push('ngconstant:dev');
        }

      }
      tasks.push(
      'clean:dist',
      'wiredep',
      'useminPrepare',
      'compass:dist',
      'imagemin',
      'svgmin',
      'autoprefixer',
      'concat',
      'ngAnnotate',
      'copy:dist',
      'cdnify',
      'cssmin',
      'uglify',
      'filerev',
      'usemin',
      'htmlmin'
      );

      grunt.task.run(tasks);
  });

  grunt.registerTask('initTest', [
  'clean:server',
  'concurrent:test',
  'autoprefixer',
  'connect:test'
  ]);
  grunt.registerTask('units', [
  'initTest',
  'karma:unit'
  ]);
  grunt.registerTask('doc', [
  'clean:doc',
  'ngdocs',
  'connect:doc'
  ]);
  grunt.registerTask('default', [
  'newer:jshint',
  'test',
  'build'
  ]);
};
<commit_msg>refactor(gruntfile): Removes old credentials<commit_after>// Generated on 2014-07-01 using generator-angular 0.9.2
'use strict';

/* jshint camelcase: false */

var fs = require('fs');
var modRewrite = require('connect-modrewrite');

module.exports = function(grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  var mainFiles = ['<%%= yeoman.app %>/components/*/{,*/}*.js', '<%%= yeoman.app %>/common/*/{,*/}*.js', '<%%= yeoman.app %>/app.js'];
  var testFiles = ['<%%= yeoman.app %>/components/*/{,*/*}*.spec.js', '<%%= yeoman.app %>/common/*/{,*/*}*.spec.js'];
  var htmlFiles = ['components/*/views/{,*/}*.html', 'common/*/views/{,*/}*.html'];
  var includeSourceFiles = {
    'app/index.html': 'app/index.html',
    'app/assets/styles/main.scss': 'app/assets/styles/main.scss'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: mainFiles,
        tasks: ['newer:jshint:all', 'newer:includeSource'],
        options: {
          livereload: '<%%= connect.options.livereload %>'
        }
      },
      compass: {
        files: ['<%%= yeoman.app %>/**/*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer', 'newer:includeSource']
      },
      indexHtml: {
        files: ['<%%= yeoman.app %>/index.html'],
        tasks: ['newer:includeSource']
      },
      livereload: {
        options: {
          livereload: '<%%= connect.options.livereload %>'
        },
        files: [
        '<%%= yeoman.app %>/components/*/views/{,*/}*.html',
        '<%%= yeoman.app %>/common/*/views/{,*/}*.html',
        '<%%= yeoman.app %>/index.html',
        '.tmp/assets/styles/{,*/}*.css',
        '<%%= yeoman.app %>/assets/images/{,*/*}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },
    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        hostname: '0.0.0.0',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function(connect) {
            return [
            modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\woff|\\ttf|\\.png|\\.jpg|\\swf$ /index.html [L]']),
            connect.static('.tmp'),
            connect().use(
            '/bower_components',
            connect.static('./bower_components')
            ),
            connect.static(appConfig.app),
            connect().use(
            '/vendor',
            connect.static('./app/assets/vendor')
            ),
            connect().use(
              '/images',
              connect.static('./app/assets/images')
            )
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function(connect) {
            return [
            connect.static('.tmp'),
            connect.static('test'),
            connect().use(
            '/bower_components',
            connect.static('./bower_components')
            ),
            connect.static(appConfig.app)
            ];
          }
        }
      },
      doc: {
        options: {
          open: true,
          keepalive: true,
          port: 9002,
          base: 'doc'
        }
      },
      dist: {
        options: {
          open: true,
          port: 9002,
          keepalive: true,
          base: '<%%= yeoman.dist %>'
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
        'Gruntfile.js',
        mainFiles
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: testFiles
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
          '.tmp',
          '<%%= yeoman.dist %>/{,*/}*',
          '!<%%= yeoman.dist %>/.git*'
          ]
        }]
      },
      server: '.tmp',
      doc: 'doc/'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 2 versions', 'ie 9']
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/assets/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/assets/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%%= yeoman.app %>/index.html'],
        ignorePath: /\.\.\//,
        overrides: {
          'angulartics': {
            main: ['src/angulartics.js', 'src/angulartics-ga.js']
          }
        }
      },
      sass: {
        src: ['<%%= yeoman.app %>/{,*/}*.{scss,sass}'],
        ignorePath: /\.\.\.\//
      },
      testKarma: {
          src: ['test/karma.conf.js'],
          fileTypes: {
            js: {
              block: /(([\s\t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          },
          devDependencies: true,
          exclude: [/jasmine/]
      }
    },
    /* STYLES SECTION */
    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%%= yeoman.app %>/',
        cssDir: '.tmp',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%%= yeoman.app %>/assets/images',
        javascriptsDir: '<%%= yeoman.app %>/(components|common)/{,*/}*',
        fontsDir: '<%%= yeoman.app %>/assets/fonts',
        importPath: [
        'bower_components/'
        ],
        httpImagesPath: '/assets/images',
        httpGeneratedImagesPath: '/assets/images/generated',
        httpFontsPath: '/assets/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\nEncoding.default_external = "UTF-8"\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    },
    /* ENDS STYLES SECTION */
    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
        '<%%= yeoman.dist %>/scripts/{,*/}*.js',
        '<%%= yeoman.dist %>/assets/styles/{,*/}*.css',
        '<%%= yeoman.dist %>/assets/images/{,*/*}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%%= yeoman.dist %>/index.html',
      options: {
        dest: '<%%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%%= yeoman.dist %>/*.html', '<%%= yeoman.dist %>/components/*/views/{,*/}*.html', '<%%= yeoman.dist %>/common/*/views/{,*/}*.html'],
      htmlExtra: ['<%%= yeoman.dist %>/*.html', '<%%= yeoman.dist %>/components/*/views/{,*/*}*.html', '<%%= yeoman.dist %>/common/*/views/{,*/*}*.html', '<%%= yeoman.dist %>/{,*/}*.js'],
      css: ['<%%= yeoman.dist %>/assets/styles/{,*/}*.css'],
      options: {
        assetsDirs: ['<%%= yeoman.dist %>', '<%%= yeoman.dist %>/assets', '<%%= yeoman.dist %>/assets/images', '<%%= yeoman.dist %>/assets/images/{,*/*}*'],
        patterns: {
          htmlExtra: [
          [/(images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the angular directives that ref revved images']
          ]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   options: {
    //     target: '.tmp/styles/*.css',
    //     relativeTo: '.tmp/styles/'
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%%= yeoman.app %>/assets/images',
          src: ['**/*.{png,jpg,jpeg,gif}'],
          dest: '<%%= yeoman.dist %>/assets/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%%= yeoman.app %>/assets/images',
          src: '{,*/}*.svg',
          dest: '<%%= yeoman.dist %>/assets/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%%= yeoman.dist %>',
          src: ['*.html', htmlFiles],
          dest: '<%%= yeoman.dist %>'
        }]
      }
    },

    // ngAnnotate tries to make the code safe for minification automatically by
    // using the Angular long form for dependency injection. It doesn't work on
    // things like resolve or inject so those have to be done manually.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%%= yeoman.dist %>/*.html']
      }
    },

    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%%= yeoman.app %>',
          dest: '<%%= yeoman.dist %>',
          src: [
          '*.{ico,png,txt}',
          '.htaccess',
          '*.html',
          htmlFiles,
          'assets/images/{,*/*}*.{webp}',
          'assets/fonts/**/*',
          'locales/*.json'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%%= yeoman.dist %>/images',
          src: ['generated/*']
        }]
      },
      styles: {
        expand: true,
        cwd: '<%%= yeoman.app %>/assets/styles',
        dest: '.tmp/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
      'compass:server'
      ],
      test: [
      'compass'
      ],
      dist: [
      'compass:dist',
      'imagemin',
      'svgmin'
      ]
    },

    // Test settings

    //units
    karma: {
      options: {
        configFile: 'test/karma.conf.js',
      },
      unit: {
        singleRun: false,
      }
    },
    /*
    		 ***************************** NGTEMPLATES TASKS *****************************
    		 */
    ngtemplates: {
      app: {
        cwd: '<%%= yeoman.app %>/',
        src: htmlFiles,
        dest: 'app/templates.js',
        options: {
          module: '<%= appName %>',
          usemin: 'scripts/scripts.js'
        }
      }
    },
    /*
    		 ***************************** NGDOCS TASKS *****************************
    		 */
    ngdocs: {
      options: {
        dest: 'doc',
        scripts: ['bower_components/angular/angular.js'],
        html5Mode: false,
        startPage: '/',
        title: '<%= appName %>',
        titleLink: '/',
        bestMatch: true,
      },
      common: {
        src: ['app/common/**/{*,/}*.js'],
        title: '<%= appName %> common'
      }
    },
    /*
    		 ***************************** END NGDOCS TASKS *****************************
    		 */
         /**
              * INCLUDE AUTOMATICALLY SCRIPTS FROM COMMON AND COMPONENTS INTO INDEX
              */
              includeSource: {
                mainTarget: {
                  options: {
                    ordering: 'top-down'
                  },
                  files: includeSourceFiles
                }
              },
             /**
              * END INCLUDE
              */
    ngconstant: {
      options: {
        name: '<%= appName %>.env',
        dest: '<%%= yeoman.app %>/common/env/env.js',
        wrap: '\'use strict\';\n\n/**\n* Env module.\n* @ngdoc overview\n* @name Env\n* @description\n*\n* # Main module of the feature.\n*/\n\n(function() {\n  {%= __ngModule %}\n\n})();'
      },
      dev: {
        constants: {
          API: 'https://alpha.<%= appName %>.com/api/',
          environment: 'dev'
        }
      },
      beta: {
        constants: {
          API: 'https://beta.<%= appName %>.com/api/',
          environment: 'beta'
        }
      },
      production: {
        constants: {
          API: 'https://<%= appName %>.com/api/',
          environment: 'production'
        }
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function(target) {
    switch (target) {
      case 'dist':
        return grunt.task.run(['build', 'connect:dist:keepalive']);
        break;
      case 'alpha':
        grunt.task.run('ngconstant:dev');
        break;
    }

    grunt.task.run([
    'clean:server',
    'wiredep',
    'concurrent:server',
    'autoprefixer',
    'includeSource',
    'connect:livereload',
    'watch'
    ]);
  });

  var env = process.env.NODE_ENV;

  grunt.registerTask('build', function() {
    var tasks = [];
      switch (env) {
        case 'beta':
        case 'production': {
          tasks.push('ngconstant:' + env);
          break;
        }
        case 'local': {
          tasks.push('ngconstant:' + env);
          break;
        }
        default: {
          tasks.push('ngconstant:dev');
        }

      }
      tasks.push(
      'clean:dist',
      'wiredep',
      'useminPrepare',
      'compass:dist',
      'imagemin',
      'svgmin',
      'autoprefixer',
      'concat',
      'ngAnnotate',
      'copy:dist',
      'cdnify',
      'cssmin',
      'uglify',
      'filerev',
      'usemin',
      'htmlmin'
      );

      grunt.task.run(tasks);
  });

  grunt.registerTask('initTest', [
  'clean:server',
  'concurrent:test',
  'autoprefixer',
  'connect:test'
  ]);
  grunt.registerTask('units', [
  'initTest',
  'karma:unit'
  ]);
  grunt.registerTask('doc', [
  'clean:doc',
  'ngdocs',
  'connect:doc'
  ]);
  grunt.registerTask('default', [
  'newer:jshint',
  'test',
  'build'
  ]);
};
<|endoftext|>


<commit_before>/* globals atom */

// TODO: how do i get ahold of these ?
// import TextEditor from "../src/text-editor";
// import TextEditorElement from "../src/text-editor-element";
// import TokenizedBuffer from "../src/tokenized-buffer";
// import clipboard from "../src/safe-clipboard";

beforeEach(function () {
	// prevent specs from modifying Atom's menus
	spyOn(atom.menu, "sendToBrowserProcess");

	// reset config before each spec
	atom.config.set("core.destroyEmptyPanes", false);
	atom.config.set("editor.fontFamily", "Courier");
	atom.config.set("editor.fontSize", 16);
	atom.config.set("editor.autoIndent", false);

	// TODO: not sure how to get ahold of these
	// // make editor display updates synchronous
	// TextEditorElement.prototype.setUpdatedSynchronously(true);
	//
	// spyOn(TextEditor.prototype, "shouldPromptToSave").and.return(false);
	//
	// // make tokenization synchronous
	// TokenizedBuffer.prototype.chunkSize = Infinity;
	// spyOn(TokenizedBuffer.prototype, "tokenizeInBackground").and.callFake(function () { return this.tokenizeNextChunk(); });
	//
	// let clipboardContent = "initial clipboard content";
	// spyOn(clipboard, "writeText").and.callFake(text => clipboardContent = text);
	// spyOn(clipboard, "readText").and.callFake(() => clipboardContent);

});

afterEach(function () {
	atom.reset();
});
<commit_msg>move StringPrettyPrinter comment to atom.js<commit_after>/* globals atom */

// TODO: how do i get ahold of these ?
// import TextEditor from "../src/text-editor";
// import TextEditorElement from "../src/text-editor-element";
// import TokenizedBuffer from "../src/tokenized-buffer";
// import clipboard from "../src/safe-clipboard";

beforeEach(function () {
	// prevent specs from modifying Atom's menus
	spyOn(atom.menu, "sendToBrowserProcess");

	// reset config before each spec
	atom.config.set("core.destroyEmptyPanes", false);
	atom.config.set("editor.fontFamily", "Courier");
	atom.config.set("editor.fontSize", 16);
	atom.config.set("editor.autoIndent", false);

	// TODO: not sure how to get ahold of these
	// // make editor display updates synchronous
	// TextEditorElement.prototype.setUpdatedSynchronously(true);
	//
	// spyOn(TextEditor.prototype, "shouldPromptToSave").and.return(false);
	//
	// // make tokenization synchronous
	// TokenizedBuffer.prototype.chunkSize = Infinity;
	// spyOn(TokenizedBuffer.prototype, "tokenizeInBackground").and.callFake(function () { return this.tokenizeNextChunk(); });
	//
	// let clipboardContent = "initial clipboard content";
	// spyOn(clipboard, "writeText").and.callFake(text => clipboardContent = text);
	// spyOn(clipboard, "readText").and.callFake(() => clipboardContent);

});

afterEach(function () {
	atom.reset();
});

// TODO: not sure this is possible in 2.x
// const { emitObject } = jasmine.StringPrettyPrinter.prototype;
// jasmine.StringPrettyPrinter.prototype.emitObject = function (obj) {
// 	if (obj.inspect) {
// 		return this.append(obj.inspect());
// 	}
// 	return emitObject.call(this, obj);
// };
<|endoftext|>