<commit_before>if (typeof RedactorPlugins === 'undefined') var RedactorPlugins = {};

RedactorPlugins.concrete5magic = function() {

    return {
        styles: [],

        createButton: function(dropdown) {
            if (!dropdown) {
                var dropdown = [];
            }
            var plugin = this.concrete5magic;
            var btn;

            this.button.remove('styles');
            if (this.button.get('formatting').length) {
                btn = this.button.addAfter('formatting','styles', this.lang.get('customStyles'), false, dropdown);
            } else {
                btn = this.button.add('styles', this.lang.get('customStyles'), false, dropdown)
            }
            this.button.setAwesome('styles', 'fa-magic');
            this.button.addDropdown(btn, dropdown);
        },

        init: function() {

            var plugin = this.concrete5magic;
            var that = this;

            $.ajax({
                'type': 'get',
                'dataType': 'json',
                'url': CCM_DISPATCHER_FILENAME + '/ccm/system/backend/editor_data',
                'data': {
                    'ccm_token': CCM_EDITOR_SECURITY_TOKEN,
                    'cID': CCM_CID
                },

                success: function(response) {
                    var dropdown = {};

                    plugin.snippetsByHandle = {};
                    $.each(response.snippets, function(i, snippet) {
                        plugin.snippetsByHandle[snippet.scsHandle] = {
                            'scsHandle': snippet.scsHandle,
                            'scsName': snippet.scsName
                        }
                        dropdown[snippet.scsHandle] = {
                            'title': snippet.scsName,
                            'func': function(option, $item, obj, e) {
                                var selectedSnippet = plugin.snippetsByHandle[option];
                                var html = String() +
                                    '' +
                                    selectedSnippet.scsName +
                                    '';

                                that.insert.htmlWithoutClean(html);
                            }
                        }
                    });

                    var button = that.button.get('styles');

                    that.styles = response.classes;
                    jQuery.each(response.classes, function(i, s)
                    {
                        dropdown['s' + i] = { title: s.title, className:s.menuClass, func: function() { plugin.setCustomFormat(s); }};
                    });

                    dropdown['remove'] = { title: that.lang.get('remove_style'), func: function() { plugin.resetCustomFormat(); }};
                    plugin.createButton(dropdown);

                }
            });
            plugin.createButton();

        },

        setCustomFormat: function (s)
        {
            if (s.forceBlock != -1 && (s.forceBlock == 1 || (s.wrap && !(jQuery.inArray(s.wrap,['a','em','strong','small','s','cite','q','dfn','abbr','data','time','var','samp','kbd','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','sub','sup','code']) > -1)))) {
                this.selection.wrap(s.wrap);
                //this.inlineFormat(s.wrap);
                if(s.style) this.block.setAttr('style',s.style);
                if(s.spanClass) this.block.setClass(s.spanClass);
            }
            else {
                if(s.wrap) this.inline.format(s.wrap);
                if(s.style) this.block.setAttr('style', s.style);
                if(s.spanClass) this.inline.toggleClass(s.spanClass);
            }
        },
        resetCustomFormat: function()
        {
            var that = this;
            jQuery.each(this.styles, function(i,s) {
                if(s.spanClass) {
                    that.inline.removeFormat();
                    that.block.removeClass(s.spanClass);
                }
            });
        }
    }

}<commit_msg>Only wrap if we have a wrapping element<commit_after>if (typeof RedactorPlugins === 'undefined') var RedactorPlugins = {};

RedactorPlugins.concrete5magic = function() {

    return {
        styles: [],

        createButton: function(dropdown) {
            if (!dropdown) {
                var dropdown = [];
            }
            var plugin = this.concrete5magic;
            var btn;

            this.button.remove('styles');
            if (this.button.get('formatting').length) {
                btn = this.button.addAfter('formatting','styles', this.lang.get('customStyles'), false, dropdown);
            } else {
                btn = this.button.add('styles', this.lang.get('customStyles'), false, dropdown)
            }
            this.button.setAwesome('styles', 'fa-magic');
            this.button.addDropdown(btn, dropdown);
        },

        init: function() {

            var plugin = this.concrete5magic;
            var that = this;

            $.ajax({
                'type': 'get',
                'dataType': 'json',
                'url': CCM_DISPATCHER_FILENAME + '/ccm/system/backend/editor_data',
                'data': {
                    'ccm_token': CCM_EDITOR_SECURITY_TOKEN,
                    'cID': CCM_CID
                },

                success: function(response) {
                    var dropdown = {};

                    plugin.snippetsByHandle = {};
                    $.each(response.snippets, function(i, snippet) {
                        plugin.snippetsByHandle[snippet.scsHandle] = {
                            'scsHandle': snippet.scsHandle,
                            'scsName': snippet.scsName
                        }
                        dropdown[snippet.scsHandle] = {
                            'title': snippet.scsName,
                            'func': function(option, $item, obj, e) {
                                var selectedSnippet = plugin.snippetsByHandle[option];
                                var html = String() +
                                    '' +
                                    selectedSnippet.scsName +
                                    '';

                                that.insert.htmlWithoutClean(html);
                            }
                        }
                    });

                    var button = that.button.get('styles');

                    that.styles = response.classes;
                    jQuery.each(response.classes, function(i, s)
                    {
                        dropdown['s' + i] = { title: s.title, className:s.menuClass, func: function() { plugin.setCustomFormat(s); }};
                    });

                    dropdown['remove'] = { title: that.lang.get('remove_style'), func: function() { plugin.resetCustomFormat(); }};
                    plugin.createButton(dropdown);

                }
            });
            plugin.createButton();

        },

        setCustomFormat: function (s)
        {
            if (s.forceBlock != -1 && (s.forceBlock == 1 || (s.wrap && !(jQuery.inArray(s.wrap,['a','em','strong','small','s','cite','q','dfn','abbr','data','time','var','samp','kbd','i','b','u','mark','ruby','rt','rp','bdi','bdo','span','sub','sup','code']) > -1)))) {
                if(s.wrap) this.selection.wrap(s.wrap);
                if(s.style) this.block.setAttr('style',s.style);
                if(s.spanClass) this.block.setClass(s.spanClass);
            }
            else {
                if(s.wrap) this.inline.format(s.wrap);
                if(s.style) this.block.setAttr('style', s.style);
                if(s.spanClass) this.inline.toggleClass(s.spanClass);
            }
        },
        resetCustomFormat: function()
        {
            var that = this;
            jQuery.each(this.styles, function(i,s) {
                if(s.spanClass) {
                    that.inline.removeFormat();
                    that.block.removeClass(s.spanClass);
                }
            });
        }
    }

}
<|endoftext|>


<commit_before>import React, { PropTypes as Types } from 'react';
import { bindActionCreators } from 'redux';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { Message } from 'retranslate';

import { Loader } from '../common';
import PensionFundTable from './../onboardingFlow/selectSources/pensionFundTable';

export const AccountPage = ({
                              currentBalanceFunds,
                              loadingCurrentBalance,
                              initialCapital,
                              memberNumber,
                              conversion,
}) => (

        { memberNumber ?
          <Message params={{ memberNumber }}>account.member.statement</Message> :
          (

              <Message>account.non.member.statement</Message>
              { ' ' }
              <Link className="btn btn-link p-0 border-0" to="/steps/new-user">
                <Message>login.join.tuleva</Message>
              </Link>

          )
        }
        {
          initialCapital ? (
            <Message params={{ initialCapital: initialCapital.amount }}>
              account.initial-capital.statement
            </Message>) : ''
        }

    {
      conversion && conversion.transfersComplete && conversion.selectionComplete ? (

            <Message>account.converted.user.statement</Message>

      ) : ''
    }

        {
          loadingCurrentBalance ?
            <Loader className="align-middle" /> :
            <PensionFundTable funds={currentBalanceFunds} />
        }

    { /*

<Message>account.contact.info.title</Message>

          CONTACT INFO WILL COME HERE

    */ }

);

AccountPage.defaultProps = {
  currentBalanceFunds: [],
  loadingCurrentBalance: false,
  initialCapital: null,
  memberNumber: null,
  conversion: null,
};

AccountPage.propTypes = {
  currentBalanceFunds: Types.arrayOf(Types.shape({})),
  loadingCurrentBalance: Types.bool,
  initialCapital: Types.shape({}),
  memberNumber: Types.number,
  conversion: Types.shape({}),
};

// TODO: write component
const mapStateToProps = state => ({
  currentBalanceFunds: state.exchange.sourceFunds,
  loadingCurrentBalance: state.exchange.loadingSourceFunds,
  initialCapital: state.account.initialCapital,
  memberNumber: (state.login.user || {}).memberNumber,
  conversion: state.login.conversion,
});
const mapDispatchToProps = dispatch => bindActionCreators({}, dispatch);

const withRedux = connect(mapStateToProps, mapDispatchToProps);

export default withRedux(AccountPage);
<commit_msg>Account page loading bugfixes<commit_after>import React, { PropTypes as Types } from 'react';
import { bindActionCreators } from 'redux';
import { Link } from 'react-router';
import { connect } from 'react-redux';
import { Message } from 'retranslate';

import { Loader } from '../common';
import PensionFundTable from './../onboardingFlow/selectSources/pensionFundTable';

export const AccountPage = ({
                              currentBalanceFunds,
                              loadingCurrentBalance,
                              initialCapital,
                              memberNumber,
                              conversion,
}) => (

        { memberNumber ?
          <Message params={{ memberNumber }}>account.member.statement</Message> :
          (

              <Message>account.non.member.statement</Message>
              { ' ' }
              <Link className="btn btn-link p-0 border-0" to="/steps/new-user">
                <Message>login.join.tuleva</Message>
              </Link>

          )
        }
        { ' ' }
        {
          initialCapital ? (
            <Message params={{ initialCapital: initialCapital.amount }}>
              account.initial-capital.statement
            </Message>) : ''
        }

    {
      conversion && conversion.transfersComplete && conversion.selectionComplete ? (

            <Message>account.converted.user.statement</Message>

      ) : ''
    }

        {
          loadingCurrentBalance ?
            <Loader className="align-middle" /> :
            <PensionFundTable funds={currentBalanceFunds} />
        }

    { /*

<Message>account.contact.info.title</Message>

          CONTACT INFO WILL COME HERE

    */ }

);

AccountPage.defaultProps = {
  currentBalanceFunds: [],
  loadingCurrentBalance: false,
  initialCapital: {},
  memberNumber: null,
  conversion: {},
};

AccountPage.propTypes = {
  currentBalanceFunds: Types.arrayOf(Types.shape({})),
  loadingCurrentBalance: Types.bool,
  initialCapital: Types.shape({}),
  memberNumber: Types.number,
  conversion: Types.shape({}),
};

// TODO: write component
const mapStateToProps = state => ({
  currentBalanceFunds: state.exchange.sourceFunds,
  loadingCurrentBalance: state.exchange.loadingSourceFunds,
  initialCapital: state.account.initialCapital,
  memberNumber: (state.login.user || {}).memberNumber,
  conversion: state.login.conversion,
});
const mapDispatchToProps = dispatch => bindActionCreators({}, dispatch);

const withRedux = connect(mapStateToProps, mapDispatchToProps);

export default withRedux(AccountPage);
<|endoftext|>


<commit_before>/**
 * Created by epotignano on 29/02/16.
 */

import Firebase from "firebase";
import { FireRef, UidRef } from '../constants/Commons';
import {USER_CREATE, USER_DELETE, USER_UPDATE, USER_UPDATE_ERROR, USER_UPDATE_SUCCESS,
  USER_CREATE_FAILURE, USER_CREATE_SUCCESS, USER_READ, USER_READ_SUCCESS, USER_READ_FAILURE
} from "../constants/ActionTypes";

function updateUserSuccess(userData) {
  return {
    type: USER_CREATE_SUCCESS,
    userData
  }
}

function updateUserError(error) {
  return {
    type: USER_CREATE_FAILURE,
    error
  }
}

function userRetrieveError(error) {
  return {
    type: USER_READ_FAILURE,
    error
  }
}

function userRetrieveSuccess(userData) {
  return {
    type: USER_READ_SUCCESS,
    userData
  }
}

export function getUser() {
  return dispatch => {
    const _uid = localStorage.getItem(UidRef);
    let User = new Firebase(FireRef + '/users/' + _uid);
    User.on('value', (err, snapshot) => {
      if(err) {
        dispatch(userRetrieveError(err));
        Promise.reject(err);
      }
      dispatch(userRetrieveSuccess(snapshot.val()))
    });
  }
}

export function updateUser(userData) {
  //We're talking about a profile owner

  return dispatch => {
    const _uid = localStorage.getItem(UidRef);
    let User = new Firebase(FireRef + '/users/' + _uid);
    User.update(userData, (error) => {
      if(error) {
        dispatch(updateUserError(error));
        Promise.reject(error);
      }
      dispatch(updateUserSuccess(userData))
    })
  };
}

<commit_msg>User Actions<commit_after>/**
 * Created by epotignano on 29/02/16.
 */

import Firebase from "firebase";
import { FireRef, UidRef } from '../constants/Commons';
import {USER_CREATE, USER_DELETE, USER_UPDATE, USER_UPDATE_ERROR, USER_UPDATE_SUCCESS,
  USER_CREATE_FAILURE, USER_CREATE_SUCCESS, USER_READ, USER_READ_SUCCESS, USER_READ_FAILURE
} from "../constants/ActionTypes";

import axios from 'axios';

function updateUserSuccess(userData) {
  return {
    type: USER_CREATE_SUCCESS,
    userData
  }
}

function updateUserError(error) {
  return {
    type: USER_CREATE_FAILURE,
    error
  }
}

function userRetrieveError(error) {
  return {
    type: USER_READ_FAILURE,
    error
  }
}

function userRetrieveSuccess(userData) {
  return {
    type: USER_READ_SUCCESS,
    userData
  }
}

export function getUser(userData) {
  //userData = { domain, username };
  return dispatch => {
    axios.get('/usuarios/' + 'dominio=' + userData.domain + '/username='+ userData.username)
  }
}

export function updateUser(userData) {
  //We're talking about a profile owner

  return dispatch => {

  };
}

<|endoftext|>


<commit_before>import fetch from '../core/fetch';
import ActionTypes from '../constants/ActionTypes';
import { processResponse, credentials, jsonHeaders } from '../core/ApiClient';
import { flashError } from './flash.js';

export function invalidateRestaurants() {
  return { type: ActionTypes.INVALIDATE_RESTAURANTS };
}

export function postRestaurant(obj) {
  return {
    type: ActionTypes.POST_RESTAURANT,
    restaurant: obj
  };
}

export function restaurantPosted(obj) {
  return {
    type: ActionTypes.RESTAURANT_POSTED,
    restaurant: obj
  };
}

export function deleteRestaurant(id) {
  return {
    type: ActionTypes.DELETE_RESTAURANT,
    id
  };
}

export function restaurantDeleted(id) {
  return {
    type: ActionTypes.RESTAURANT_DELETED,
    id
  };
}

export function requestRestaurants() {
  return { type: ActionTypes.REQUEST_RESTAURANTS };
}

export function receiveRestaurants(json) {
  return {
    type: ActionTypes.RECEIVE_RESTAURANTS,
    items: json
  };
}

export function postVote(id) {
  return {
    type: ActionTypes.POST_VOTE,
    id
  };
}

export function votePosted(json) {
  return {
    type: ActionTypes.VOTE_POSTED,
    vote: json
  };
}

export function deleteVote(restaurantId, id) {
  return {
    type: ActionTypes.DELETE_VOTE,
    restaurantId,
    id
  };
}

export function voteDeleted(restaurantId, id) {
  return {
    type: ActionTypes.VOTE_DELETED,
    restaurantId,
    id
  };
}

export function postNewTagToRestaurant(restaurantId, value) {
  return {
    type: ActionTypes.POST_NEW_TAG_TO_RESTAURANT,
    restaurantId,
    value
  };
}

export function postedNewTagToRestaurant(restaurantId, tag) {
  return {
    type: ActionTypes.POSTED_NEW_TAG_TO_RESTAURANT,
    restaurantId,
    tag
  };
}

export function postTagToRestaurant(restaurantId, id) {
  return {
    type: ActionTypes.POST_TAG_TO_RESTAURANT,
    restaurantId,
    id
  };
}

export function postedTagToRestaurant(restaurantId, id) {
  return {
    type: ActionTypes.POSTED_TAG_TO_RESTAURANT,
    restaurantId,
    id
  };
}

export function deleteTagFromRestaurant(restaurantId, id) {
  return {
    type: ActionTypes.DELETE_TAG_FROM_RESTAURANT,
    restaurantId,
    id
  };
}

export function deletedTagFromRestaurant(restaurantId, id) {
  return {
    type: ActionTypes.DELETED_TAG_FROM_RESTAURANT,
    restaurantId,
    id
  };
}

function fetchRestaurants() {
  return dispatch => {
    dispatch(requestRestaurants());
    return fetch('/api/restaurants')
      .then(response => processResponse(response))
      .then(json => dispatch(receiveRestaurants(json)));
  };
}

function shouldFetchRestaurants(state) {
  const items = state.restaurants.items;
  if (!items) {
    return true;
  }
  if (items.isFetching) {
    return false;
  }
  return items.didInvalidate;
}

export function fetchRestaurantsIfNeeded() {
  // Note that the function also receives getState()
  // which lets you choose what to dispatch next.

  // This is useful for avoiding a network request if
  // a cached value is already available.

  return (dispatch, getState) => {
    if (shouldFetchRestaurants(getState())) {
      // Dispatch a thunk from thunk!
      return dispatch(fetchRestaurants());
    }

    // Let the calling code know there's nothing to wait for.
    return Promise.resolve();
  };
}

export function addRestaurant(name, placeId, address, lat, lng) {
  return (dispatch) => {
    dispatch(postRestaurant());
    return fetch('/api/restaurants', {
      method: 'post',
      credentials,
      jsonHeaders,
      body: JSON.stringify({ name, place_id: placeId, address, lat, lng })
    })
      .then(response => processResponse(response))
      .catch(
        err => dispatch(flashError(err.message))
      );
  };
}

export function removeRestaurant(id) {
  return (dispatch) => {
    dispatch(deleteRestaurant(id));
    return fetch(`/api/restaurants/${id}`, {
      credentials,
      method: 'delete'
    });
  };
}

export function addVote(id) {
  return (dispatch) => {
    dispatch(postVote(id));
    return fetch(`/api/restaurants/${id}/votes`, {
      method: 'post',
      credentials
    })
      .then(response => processResponse(response))
      .catch(
        err => dispatch(flashError(err.message))
      );
  };
}

export function removeVote(restaurantId, id) {
  return (dispatch) => {
    dispatch(deleteVote(restaurantId, id));
    return fetch(`/api/restaurants/${restaurantId}/votes/${id}`, {
      credentials,
      method: 'delete'
    });
  };
}

export function addNewTagToRestaurant(restaurantId, value) {
  return (dispatch) => {
    dispatch(postNewTagToRestaurant(restaurantId, value));
    return fetch(`/api/restaurants/${restaurantId}/tags`, {
      method: 'post',
      credentials,
      jsonHeaders,
      body: JSON.stringify({ name: value })
    })
      .then(response => processResponse(response))
      .catch(
        err => dispatch(flashError(err.message))
      );
  };
}

export function addTagToRestaurant(restaurantId, id) {
  return (dispatch) => {
    dispatch(postTagToRestaurant(restaurantId, id));
    return fetch(`/api/restaurants/${restaurantId}/tags`, {
      method: 'post',
      credentials,
      jsonHeaders,
      body: JSON.stringify({ id })
    })
      .then(response => processResponse(response))
      .catch(
        err => dispatch(flashError(err.message))
      );
  };
}

export function removeTagFromRestaurant(restaurantId, id) {
  return (dispatch) => {
    dispatch(deleteTagFromRestaurant(restaurantId, id));
    return fetch(`/api/restaurants/${restaurantId}/tags/${id}`, {
      credentials,
      method: 'delete'
    });
  };
}
<commit_msg>Fixing header submissions<commit_after>import fetch from '../core/fetch';
import ActionTypes from '../constants/ActionTypes';
import { processResponse, credentials, jsonHeaders } from '../core/ApiClient';
import { flashError } from './flash.js';

export function invalidateRestaurants() {
  return { type: ActionTypes.INVALIDATE_RESTAURANTS };
}

export function postRestaurant(obj) {
  return {
    type: ActionTypes.POST_RESTAURANT,
    restaurant: obj
  };
}

export function restaurantPosted(obj) {
  return {
    type: ActionTypes.RESTAURANT_POSTED,
    restaurant: obj
  };
}

export function deleteRestaurant(id) {
  return {
    type: ActionTypes.DELETE_RESTAURANT,
    id
  };
}

export function restaurantDeleted(id) {
  return {
    type: ActionTypes.RESTAURANT_DELETED,
    id
  };
}

export function requestRestaurants() {
  return { type: ActionTypes.REQUEST_RESTAURANTS };
}

export function receiveRestaurants(json) {
  return {
    type: ActionTypes.RECEIVE_RESTAURANTS,
    items: json
  };
}

export function postVote(id) {
  return {
    type: ActionTypes.POST_VOTE,
    id
  };
}

export function votePosted(json) {
  return {
    type: ActionTypes.VOTE_POSTED,
    vote: json
  };
}

export function deleteVote(restaurantId, id) {
  return {
    type: ActionTypes.DELETE_VOTE,
    restaurantId,
    id
  };
}

export function voteDeleted(restaurantId, id) {
  return {
    type: ActionTypes.VOTE_DELETED,
    restaurantId,
    id
  };
}

export function postNewTagToRestaurant(restaurantId, value) {
  return {
    type: ActionTypes.POST_NEW_TAG_TO_RESTAURANT,
    restaurantId,
    value
  };
}

export function postedNewTagToRestaurant(restaurantId, tag) {
  return {
    type: ActionTypes.POSTED_NEW_TAG_TO_RESTAURANT,
    restaurantId,
    tag
  };
}

export function postTagToRestaurant(restaurantId, id) {
  return {
    type: ActionTypes.POST_TAG_TO_RESTAURANT,
    restaurantId,
    id
  };
}

export function postedTagToRestaurant(restaurantId, id) {
  return {
    type: ActionTypes.POSTED_TAG_TO_RESTAURANT,
    restaurantId,
    id
  };
}

export function deleteTagFromRestaurant(restaurantId, id) {
  return {
    type: ActionTypes.DELETE_TAG_FROM_RESTAURANT,
    restaurantId,
    id
  };
}

export function deletedTagFromRestaurant(restaurantId, id) {
  return {
    type: ActionTypes.DELETED_TAG_FROM_RESTAURANT,
    restaurantId,
    id
  };
}

function fetchRestaurants() {
  return dispatch => {
    dispatch(requestRestaurants());
    return fetch('/api/restaurants')
      .then(response => processResponse(response))
      .then(json => dispatch(receiveRestaurants(json)));
  };
}

function shouldFetchRestaurants(state) {
  const items = state.restaurants.items;
  if (!items) {
    return true;
  }
  if (items.isFetching) {
    return false;
  }
  return items.didInvalidate;
}

export function fetchRestaurantsIfNeeded() {
  // Note that the function also receives getState()
  // which lets you choose what to dispatch next.

  // This is useful for avoiding a network request if
  // a cached value is already available.

  return (dispatch, getState) => {
    if (shouldFetchRestaurants(getState())) {
      // Dispatch a thunk from thunk!
      return dispatch(fetchRestaurants());
    }

    // Let the calling code know there's nothing to wait for.
    return Promise.resolve();
  };
}

export function addRestaurant(name, placeId, address, lat, lng) {
  return (dispatch) => {
    dispatch(postRestaurant());
    return fetch('/api/restaurants', {
      method: 'post',
      credentials,
      headers: jsonHeaders,
      body: JSON.stringify({ name, place_id: placeId, address, lat, lng })
    })
      .then(response => processResponse(response))
      .catch(
        err => dispatch(flashError(err.message))
      );
  };
}

export function removeRestaurant(id) {
  return (dispatch) => {
    dispatch(deleteRestaurant(id));
    return fetch(`/api/restaurants/${id}`, {
      credentials,
      method: 'delete'
    });
  };
}

export function addVote(id) {
  return (dispatch) => {
    dispatch(postVote(id));
    return fetch(`/api/restaurants/${id}/votes`, {
      method: 'post',
      credentials
    })
      .then(response => processResponse(response))
      .catch(
        err => dispatch(flashError(err.message))
      );
  };
}

export function removeVote(restaurantId, id) {
  return (dispatch) => {
    dispatch(deleteVote(restaurantId, id));
    return fetch(`/api/restaurants/${restaurantId}/votes/${id}`, {
      credentials,
      method: 'delete'
    });
  };
}

export function addNewTagToRestaurant(restaurantId, value) {
  return (dispatch) => {
    dispatch(postNewTagToRestaurant(restaurantId, value));
    return fetch(`/api/restaurants/${restaurantId}/tags`, {
      method: 'post',
      credentials,
      headers: jsonHeaders,
      body: JSON.stringify({ name: value })
    })
      .then(response => processResponse(response))
      .catch(
        err => dispatch(flashError(err.message))
      );
  };
}

export function addTagToRestaurant(restaurantId, id) {
  return (dispatch) => {
    dispatch(postTagToRestaurant(restaurantId, id));
    return fetch(`/api/restaurants/${restaurantId}/tags`, {
      method: 'post',
      credentials,
      headers: jsonHeaders,
      body: JSON.stringify({ id })
    })
      .then(response => processResponse(response))
      .catch(
        err => dispatch(flashError(err.message))
      );
  };
}

export function removeTagFromRestaurant(restaurantId, id) {
  return (dispatch) => {
    dispatch(deleteTagFromRestaurant(restaurantId, id));
    return fetch(`/api/restaurants/${restaurantId}/tags/${id}`, {
      credentials,
      method: 'delete'
    });
  };
}
<|endoftext|>


<commit_before>/**
 * Подменяем и расширяем Backbone.View, добавляя в него милые методы для работы с селекторами, выбором элементов и
 * дата атрибутами
 * @class Backbone.ElementsView
 * @extends Backbone.View
 */
Backbone.ElementsView = Backbone.View.redefine(function (origin) {
    return /**@lends Backbone.View*/{

        setElement: function () {
            origin.setElement.apply(this, arguments);

            /**
             * Дата атрибуты {@link Backbone.View.$el} в camelCase
             * @type {Object.<string, string>}
             * @protected
             */
            this._data = this.$el.data() || {};
            this._resetCaches();
            return this;
        },

        /**
         * Сбрасывает кэши клаасов, селекторов и элементов
         * @private
         */
        _resetCaches: function () {

            /**
             * Здесь сохраняются закешированные классы, полученные из
             * {@link Backbone.ElementsView._classes}
             * @type {Object.<string, string>}
             * @private
             */
            this._cachedClasses = this._classes();

            /**
             * Здесь сохраняются закешированные селекторы, в том числе полученные из
             * {@link Backbone.ElementsView._classes}
             * @type {Object.<string, string>}
             * @private
             */
            this._cachedSelectors = this._selectors();

            /**
             * Кеш для {@link Backbone.ElementsView._elem}
             * @type {Object.<string, jQuery>}
             * @private
             */
            this._cachedElements = {};
        },

        /**
         * CSS классы используемые во вьюшке складываются сюда. Ключи - имена элементов, значение - названия классов.
         * Свойство можно переопределять в наследуемых классах
         * @returns {Object.<string, string>}
         * @protected
         * @example
         *     _classes: function(){
         *         return {
         *             table: 'js-table'
         *         };
         *     }
         *
         */
        _classes: function () {
            return {};
        },

        /**
         * Возвращает css класс элемента по его имени, классы берутся из {@link Backbone.ElementsView._classes}
         * @param {String} name название элемента
         * @returns {String} css класс
         * @throws {Error} если название елемента нигде не найдено
         * @protected
         */
        _class: function (name) {
            var cl = this._cachedClasses[name];
            if (cl == null) {
                throw new Error('Selector for ' + name + ' does not found');
            }

            return cl;
        },

        /**
         * Селекторы используемые во вьюшке описываются здесь. Метод надо переопределять в наследуемых классах
         * @returns {Object.<string, string>} Ключи - названия элементов, значения - селекторы
         * @protected
         * @example
         *      _selectors: function(){
         *          return {
         *              map: '.google-map:first'
         *          };
         *      }
         *
         */
        _selectors: function () {
            return {};
        },

        /**
         * Возвращает селектор элемента по его имени, селекторы берутся из {@link Backbone.ElementsView._selectors} или
         * {@link Backbone.ElementsView._classes}
         * @param {String} name название элемента
         * @returns {String} селектор
         * @protected
         * @example
         *      events: function(){
         *          var events = {};
         *          events['click ' + this._selector('map')] = this._clickOnMap;
         *          events['click ' + this._selector('table')] = this._clickOnTable;
         *          return events;
         *      }
         *
         */
        _selector: function (name) {
            var args = null,
                cacheKey = this._getCacheKey.apply(this, arguments),
                selector = this._cachedSelectors[cacheKey];

            if (selector == null) {
                if (!this._cachedSelectors[name]) {
                    selector = '.' + this._class(name);
                    this._cachedSelectors[name] = selector;
                }

                args = Array.prototype.slice.call(arguments, 1);
                if (args.length) {
                    args.unshift(this._cachedSelectors[name]);
                    selector = _.sprintf.apply(_, args);
                    this._cachedSelectors[cacheKey] = selector;
                }
            }
            return selector;
        },

        /**
         * @param {String} name
         * @returns {Boolean}
         * @protected
         */
        _hasSelector: function (name) {
            return !!(this._cachedClasses[name] || this._cachedSelectors[name]);
        },

        /**
         * Возвращает jQuery коллекцию по имени из {@link Backbone.ElementsView._selectors} или
         * {@link Backbone.ElementsView._classes}. Кэширует результаты, для сброса кеша см.
         * {@link Backbone.ElementsView._dropElemCache}
         * @param {String} name название элемента
         * @returns {jQuery}
         * @protected
         * @example
         *     this._elem('table').hide();
         *
         */
        _elem: function (name) {
            var cacheKey = this._getCacheKey.apply(this, arguments),
                $elem = this._cachedElements[cacheKey];

            if ($elem != null) {
                return $elem;
            }

            $elem = this._findElem.apply(this, arguments);
            this._cachedElements[cacheKey] = $elem;

            return $elem;
        },

        /**
         * @param name
         * @returns {string}
         * @private
         */
        _getCacheKey: function (name) {
            return Array.prototype.join.call(arguments, '|');
        },

        /**
         * Finds element without using cache
         * @param {string} name
         * @returns {jQuery}
         * @protected
         */
        _findElem: function (name) {
            return this.$(this._selector.apply(this, arguments));
        },

        /**
         * Replaces element with passed content
         * @param {string} name
         * @param {HTMLElement|jQuery|string} content
         * @protected
         */
        _replaceElem: function (name, content) {
            var $el = this._elem(name),
                focusOnElem = $el[0] == document.activeElement || $el.has(document.activeElement).length;

            this._elem(name).replaceWith(content);
            this._dropElemCache(name);

            if (focusOnElem) {
                this._fixFocus(this._elem(name));
            }
        },

        /**
         * Sets element innerHTML
         * @param {string} name
         * @param {HTMLElement|jQuery|string} content
         * @protected
         */
        _setElemContent: function (name, content) {
            var $el = this._elem(name),
                focusInsideElem = $el.has(document.activeElement).length;

            $el.html(content);
            if (focusInsideElem) {
                this._fixFocus($el);
            }
        },

        /**
         * Emulate focus on passed element (focuses closest focusable element)
         * @param {jQuery} $el
         * @private
         */
        _fixFocus: function ($el) {
            var $focused = $el.closest('[tabindex]');
            if ($focused.length) {
                $focused[0].focus();
            }
        },

        /**
         * Трет кеш для {@link Backbone.ElementsView._elem}
         * @param {String} [name] имя элемента для которого надо убрать кеш, если не задано - сотрется весь кеш
         * @protected
         */
        _dropElemCache: function (name) {
            if (name != null) {
                delete this._cachedElements[this._getCacheKey.apply(this, arguments)];
            }
            else {
                this._cachedElements = {};
            }
            return this;
        },

        /**
         * Возвращает дата атрибуты для элемента по его имени и имени атрибута
         * @param {String} name имя элемента
         * @param {String} [attr] имя атрибута, если не задано, то вернется объект со всеми дата атрибутами для элемента
         * @returns {*|Object}
         * @protected
         */
        _getElemData: function (name, attr) {
            var data = this._elem(name).data();
            if (attr == null) {
                return data;
            }

            return data[attr];
        },

        /**
         * Совместимость с Backbone.Decorate
         */
        beforeDecorate: function () {
            this._resetCaches();

            if (typeof origin.beforeDecorate == "function") {
                origin.beforeDecorate.apply(this, arguments);
            }
        }
    }
});<commit_msg>PSDJS-7053 ie9 calendar<commit_after>/**
 * Подменяем и расширяем Backbone.View, добавляя в него милые методы для работы с селекторами, выбором элементов и
 * дата атрибутами
 * @class Backbone.ElementsView
 * @extends Backbone.View
 */
Backbone.ElementsView = Backbone.View.redefine(function (origin) {
    return /**@lends Backbone.View*/{

        setElement: function () {
            origin.setElement.apply(this, arguments);

            /**
             * Дата атрибуты {@link Backbone.View.$el} в camelCase
             * @type {Object.<string, string>}
             * @protected
             */
            this._data = this.$el.data() || {};
            this._resetCaches();
            return this;
        },

        /**
         * Сбрасывает кэши клаасов, селекторов и элементов
         * @private
         */
        _resetCaches: function () {

            /**
             * Здесь сохраняются закешированные классы, полученные из
             * {@link Backbone.ElementsView._classes}
             * @type {Object.<string, string>}
             * @private
             */
            this._cachedClasses = this._classes();

            /**
             * Здесь сохраняются закешированные селекторы, в том числе полученные из
             * {@link Backbone.ElementsView._classes}
             * @type {Object.<string, string>}
             * @private
             */
            this._cachedSelectors = this._selectors();

            /**
             * Кеш для {@link Backbone.ElementsView._elem}
             * @type {Object.<string, jQuery>}
             * @private
             */
            this._cachedElements = {};
        },

        /**
         * CSS классы используемые во вьюшке складываются сюда. Ключи - имена элементов, значение - названия классов.
         * Свойство можно переопределять в наследуемых классах
         * @returns {Object.<string, string>}
         * @protected
         * @example
         *     _classes: function(){
         *         return {
         *             table: 'js-table'
         *         };
         *     }
         *
         */
        _classes: function () {
            return {};
        },

        /**
         * Возвращает css класс элемента по его имени, классы берутся из {@link Backbone.ElementsView._classes}
         * @param {String} name название элемента
         * @returns {String} css класс
         * @throws {Error} если название елемента нигде не найдено
         * @protected
         */
        _class: function (name) {
            var cl = this._cachedClasses[name];
            if (cl == null) {
                throw new Error('Selector for ' + name + ' does not found');
            }

            return cl;
        },

        /**
         * Селекторы используемые во вьюшке описываются здесь. Метод надо переопределять в наследуемых классах
         * @returns {Object.<string, string>} Ключи - названия элементов, значения - селекторы
         * @protected
         * @example
         *      _selectors: function(){
         *          return {
         *              map: '.google-map:first'
         *          };
         *      }
         *
         */
        _selectors: function () {
            return {};
        },

        /**
         * Возвращает селектор элемента по его имени, селекторы берутся из {@link Backbone.ElementsView._selectors} или
         * {@link Backbone.ElementsView._classes}
         * @param {String} name название элемента
         * @returns {String} селектор
         * @protected
         * @example
         *      events: function(){
         *          var events = {};
         *          events['click ' + this._selector('map')] = this._clickOnMap;
         *          events['click ' + this._selector('table')] = this._clickOnTable;
         *          return events;
         *      }
         *
         */
        _selector: function (name) {
            var args = null,
                cacheKey = this._getCacheKey.apply(this, arguments),
                selector = this._cachedSelectors[cacheKey];

            if (selector == null) {
                if (!this._cachedSelectors[name]) {
                    selector = '.' + this._class(name);
                    this._cachedSelectors[name] = selector;
                }

                args = Array.prototype.slice.call(arguments, 1);
                if (args.length) {
                    args.unshift(this._cachedSelectors[name]);
                    selector = _.sprintf.apply(_, args);
                    this._cachedSelectors[cacheKey] = selector;
                }
            }
            return selector;
        },

        /**
         * @param {String} name
         * @returns {Boolean}
         * @protected
         */
        _hasSelector: function (name) {
            return !!(this._cachedClasses[name] || this._cachedSelectors[name]);
        },

        /**
         * Возвращает jQuery коллекцию по имени из {@link Backbone.ElementsView._selectors} или
         * {@link Backbone.ElementsView._classes}. Кэширует результаты, для сброса кеша см.
         * {@link Backbone.ElementsView._dropElemCache}
         * @param {String} name название элемента
         * @returns {jQuery}
         * @protected
         * @example
         *     this._elem('table').hide();
         *
         */
        _elem: function (name) {
            var cacheKey = this._getCacheKey.apply(this, arguments),
                $elem = this._cachedElements[cacheKey];

            if ($elem != null) {
                return $elem;
            }

            $elem = this._findElem.apply(this, arguments);
            this._cachedElements[cacheKey] = $elem;

            return $elem;
        },

        /**
         * @param name
         * @returns {string}
         * @private
         */
        _getCacheKey: function (name) {
            return Array.prototype.join.call(arguments, '|');
        },

        /**
         * Finds element without using cache
         * @param {string} name
         * @returns {jQuery}
         * @protected
         */
        _findElem: function (name) {
            return this.$(this._selector.apply(this, arguments));
        },

        /**
         * Replaces element with passed content
         * @param {string} name
         * @param {HTMLElement|jQuery|string} content
         * @protected
         */
        _replaceElem: function (name, content) {
            var $el = this._elem(name),
                focusOnElem = $el[0] == document.activeElement || $el.has(document.activeElement).length;

            this._elem(name).replaceWith(content);
            this._dropElemCache(name);

            if (focusOnElem) {
                this._fixFocus(this._elem(name));
            }
        },

        /**
         * Sets element innerHTML
         * @param {string} name
         * @param {HTMLElement|jQuery|string} content
         * @protected
         */
        _setElemContent: function (name, content) {
            var $el = this._elem(name),
                focusInsideElem = $el.has(document.activeElement).length;

            $el.html(content);
            if (focusInsideElem) {
                this._fixFocus($el);
            }
        },

        /**
         * Emulate focus on passed element (focuses closest focusable element)
         * @param {jQuery} $el
         * @private
         */
        _fixFocus: function ($el) {
            var $focused = $el.closest('[tabindex],a,button:not(:disabled)');
            if ($focused.length) {
                $focused[0].focus();
            }
        },

        /**
         * Трет кеш для {@link Backbone.ElementsView._elem}
         * @param {String} [name] имя элемента для которого надо убрать кеш, если не задано - сотрется весь кеш
         * @protected
         */
        _dropElemCache: function (name) {
            if (name != null) {
                delete this._cachedElements[this._getCacheKey.apply(this, arguments)];
            }
            else {
                this._cachedElements = {};
            }
            return this;
        },

        /**
         * Возвращает дата атрибуты для элемента по его имени и имени атрибута
         * @param {String} name имя элемента
         * @param {String} [attr] имя атрибута, если не задано, то вернется объект со всеми дата атрибутами для элемента
         * @returns {*|Object}
         * @protected
         */
        _getElemData: function (name, attr) {
            var data = this._elem(name).data();
            if (attr == null) {
                return data;
            }

            return data[attr];
        },

        /**
         * Совместимость с Backbone.Decorate
         */
        beforeDecorate: function () {
            this._resetCaches();

            if (typeof origin.beforeDecorate == "function") {
                origin.beforeDecorate.apply(this, arguments);
            }
        }
    }
});<|endoftext|>


<commit_before>var ngActionCable = angular.module('ngActionCable',['ngWebSocket']);

// default websocket configs
// looks for Rails' <%= action_cable_meta_tag %> in this format:
// <meta name="action-cable-url" content="ws://localhost:3000/cable"/>
ngActionCable.value('WebsocketConfig', {
  autoStart: true,
  wsUri: angular.element("meta[name='action-cable-url']").attr("content") || "",
  debug: false
});

ngActionCable.factory('WebsocketController', function () {

  // add a hash of callbacks here that `route_channel` will call on an incoming message.
  // actions format: actions[channelName][dataParams] = [callback1, callback2, ...]
  // e.g. actions["GlobalsData"][JSON.stringify({"responder_id":1})]= [function(message){...}, assignment_2: function(message){...}, ... ]
  var actions = {
    welcome: function(message){
      // console.log('willkommen');
    },
    ping: function(message){
      // console.log('WS ping');
    },
    confirm_subscription: function(message){
      // console.log('WS confirm_subscription on channel: ' + message.identifier);
    },
    ws_404: function(message){
      // console.log('Route not found: ' + message);
    }
  };

  var routeToActions= function(actionCallbacks, message){
    angular.forEach(actionCallbacks, function(func, id){
      func.apply(null, [message]);
    });
  }

  var route = function(message){
    if (!!actions[message.type]) {
      actions[message.type](message);
    } else if (!!findActionCallbacksForChannel(channel_from(message), params_from(message))) {
      var actionCallbacks= findActionCallbacksForChannel(channel_from(message), params_from(message));
      routeToActions(actionCallbacks, message.message);
    } else {
      actions.ws_404(message);
    };
  };

  function findActionCallbacksForChannel(channelName, params){
    return (actions[channelName] && actions[channelName][params]);
  }

  function channel_from(message){
    if (message && message.identifier) {
      return JSON.parse(message.identifier).channel;
    };
  };

  function params_from(message){
    var paramsData= JSON.parse(message.identifier).data;
    return JSON.stringify(paramsData);
  }

  var methods= {
    post: function(message){
      return route(message);
    },
    actions: actions
  };

  return methods;
});

// ActionCable formats:
// ! Indentifier for subscribe, unsubscribe and message must be the same.
//
// {
//   "command": "subscribe",
//   "identifier": JSON.stringify({"channel": "UpdatesChannel",  "data": "name"}),
// }
//  - will set params to ["identifier"]["data"]
//
// {
//   "command": "unsubscribe",
//   "identifier": JSON.stringify({"channel": "UpdatesChannel",  "data": "name"}),
// }
//  - will set params to ["identifier"]["data"]
//
// {
//   "command": "message",
//   "identifier": JSON.stringify({"channel": "UpdatesChannel",  "data": "name"}),
//   "data": JSON.stringify({"message": "bla bla", "action": "foobar"})
// }
//  - will call foobar(data)
//  - will set params to ["identifier"]["data"]

ngActionCable.factory("Websocket", function($websocket, WebsocketController, WebsocketConfig) {
  var wsUrl = WebsocketConfig.wsUri;
  var controller = WebsocketController;
  var dataStream = null;
  var methods;
  var connected = false;
  var currentChannels = [];
  var close_connection = function(){
    if (dataStream){
      dataStream.close({"force":true});
      dataStream = null;
      connected = false;
    };
  };
  var subscribe_to = function(channel, data){
    if (typeof(data)==='undefined') data = "N/A";
    console.log("-> subscribing to: " + channel)
    new_data_stream().send(JSON.stringify({
        "command": "subscribe",
        "identifier": JSON.stringify({"channel": channel, "data": data})
      }));
  };
  var unsubscribe_from = function(channel, data){
    if (typeof(data)==='undefined') data = "N/A";
    console.log("<- unsubscribing from: " + channel)
    new_data_stream().send(JSON.stringify({
        "command": "unsubscribe",
        "identifier": JSON.stringify({"channel": channel, "data": data})
      }));
  };
  var send_to = function(channel, data, message, action){
    if (typeof(data)==='undefined') data = "N/A";
    console.log("=> sending to: " + channel)
    new_data_stream().send(JSON.stringify({
        "command": "message",
        "identifier": JSON.stringify({"channel": channel, "data": data}),
        "data": JSON.stringify({"message": message, "action": action})
      }));
  };
  var new_data_stream = function(){
    if(dataStream == null) {
      dataStream = $websocket(wsUrl);
      dataStream.onClose(function(arg){
        close_connection();
        connected = false;
        methods.on_connection_close_callback();
      });
      dataStream.onOpen(function(arg){
        connected = true;
        currentChannels.forEach(function(channel){ subscribe_to(channel.name, channel.data); });
        methods.on_connection_open_callback();
      });
      dataStream.onMessage(function(message) {   //arriving message from backend
        controller.post(JSON.parse(message.data));
      });
    };
    return dataStream;
  };
  methods = {
    connected: function(){ return connected },
    attempt_restart: function(){
      close_connection();
      new_data_stream();
      return true;
    },
    currentChannels: currentChannels,
    close: function(){ return close_connection(); },
    on_connection_close_callback: function(){},
    on_connection_open_callback: function(){},
    subscribe: function(channel, data){
      currentChannels.push({name: channel, data: data});
      this.connected() && subscribe_to(channel, data);
    },
    unsubscribe: function(channel, data){
      for(var i=0; i<currentChannels.length; i++){ if (currentChannels[i].name===channel) {currentChannels.splice(i, 1);} }
      this.connected() && unsubscribe_from(channel, data);
    },
    send: function(channel, data, message, action){
      console.log("send requested");
      this.connected() && send_to(channel, data, message, action);
    }
  };
  return methods;
});

ngActionCable.factory("WebsocketChannel",function (WebsocketController, Websocket){
  return function(channelName, channelParams){

  }

});

// SocketWrangler to start, stop or try reconnect websockets every intervalTime milliseconds.
//
// Current status is denoted by three booleans:
// connected(), connecting(), and disconnected(), in an abstraction
// of the internal trivalent logic. Exactly one will be true at all times.
//
// Actions are start() and stop()
ngActionCable.factory("SocketWrangler", function(Websocket) {
  var intervalTime= 8647;
  var websocket= Websocket;
  var _live= false;
  var _connecting= false;
  var connectNow= function(){
    websocket.attempt_restart();
  };
  var startInterval= function(){
    _connecting= _connecting || setInterval(function(){
      connectNow();
    }, intervalTime);
  };
  var stopInterval= function(){
    clearInterval(_connecting);
    _connecting= false;
  };
  websocket.on_connection_close_callback = function(){
    if (_live) { startInterval(); };
    console.log("close callback");
  };
  websocket.on_connection_open_callback = function(){
    stopInterval();
    console.log("open callback");
  };
  var methods= {
    connected: function(){
      return (_live && !_connecting);
    },
    connecting: function(){
      return (_live && !!_connecting);
    },
    disconnected: function(){
      return !_live;
    },
    start: function(){
      console.info("Live STARTED");
      _live= true;
      startInterval();
      connectNow();
    },
    stop: function(){
      console.info("Live stopped");
      _live= false;
      stopInterval();
      websocket.close();
    }
  };
  return methods;
});
<commit_msg>websocketControllerActions extractor method<commit_after>var ngActionCable = angular.module('ngActionCable',['ngWebSocket']);

// default websocket configs
// looks for Rails' <%= action_cable_meta_tag %> in this format:
// <meta name="action-cable-url" content="ws://localhost:3000/cable"/>
ngActionCable.value('WebsocketConfig', {
  autoStart: true,
  wsUri: angular.element("meta[name='action-cable-url']").attr("content") || "",
  debug: false
});

ngActionCable.factory('WebsocketController', function () {

  // add a hash of callbacks here that `route_channel` will call on an incoming message.
  // actions format: actions[channelName][dataParams] = [callback1, callback2, ...]
  // e.g. actions["GlobalsData"][JSON.stringify({"responder_id":1})]= [function(message){...}, assignment_2: function(message){...}, ... ]
  var actions = {
    welcome: function(message){
      // console.log('willkommen');
    },
    ping: function(message){
      // console.log('WS ping');
    },
    confirm_subscription: function(message){
      // console.log('WS confirm_subscription on channel: ' + message.identifier);
    },
    ws_404: function(message){
      // console.log('Route not found: ' + message);
    }
  };

  var routeToActions= function(actionCallbacks, message){
    angular.forEach(actionCallbacks, function(func, id){
      func.apply(null, [message]);
    });
  }

  var route = function(message){
    if (!!actions[message.type]) {
      actions[message.type](message);
    } else if (!!findActionCallbacksForChannel(channel_from(message), params_from(message))) {
      var actionCallbacks= findActionCallbacksForChannel(channel_from(message), params_from(message));
      routeToActions(actionCallbacks, message.message);
    } else {
      actions.ws_404(message);
    };
  };

  function findActionCallbacksForChannel(channelName, params){
    return (actions[channelName] && actions[channelName][params]);
  }

  function channel_from(message){
    if (message && message.identifier) {
      return JSON.parse(message.identifier).channel;
    };
  };

  function params_from(message){
    var paramsData= JSON.parse(message.identifier).data;
    return JSON.stringify(paramsData);
  }

  var methods= {
    post: function(message){
      return route(message);
    },
    actions: actions
  };

  return methods;
});

// ActionCable formats:
// ! Indentifier for subscribe, unsubscribe and message must be the same.
//
// {
//   "command": "subscribe",
//   "identifier": JSON.stringify({"channel": "UpdatesChannel",  "data": "name"}),
// }
//  - will set params to ["identifier"]["data"]
//
// {
//   "command": "unsubscribe",
//   "identifier": JSON.stringify({"channel": "UpdatesChannel",  "data": "name"}),
// }
//  - will set params to ["identifier"]["data"]
//
// {
//   "command": "message",
//   "identifier": JSON.stringify({"channel": "UpdatesChannel",  "data": "name"}),
//   "data": JSON.stringify({"message": "bla bla", "action": "foobar"})
// }
//  - will call foobar(data)
//  - will set params to ["identifier"]["data"]

ngActionCable.factory("Websocket", function($websocket, WebsocketController, WebsocketConfig) {
  var wsUrl = WebsocketConfig.wsUri;
  var controller = WebsocketController;
  var dataStream = null;
  var methods;
  var connected = false;
  var currentChannels = [];
  var close_connection = function(){
    if (dataStream){
      dataStream.close({"force":true});
      dataStream = null;
      connected = false;
    };
  };
  var subscribe_to = function(channel, data){
    if (typeof(data)==='undefined') data = "N/A";
    console.log("-> subscribing to: " + channel)
    new_data_stream().send(JSON.stringify({
        "command": "subscribe",
        "identifier": JSON.stringify({"channel": channel, "data": data})
      }));
  };
  var unsubscribe_from = function(channel, data){
    if (typeof(data)==='undefined') data = "N/A";
    console.log("<- unsubscribing from: " + channel)
    new_data_stream().send(JSON.stringify({
        "command": "unsubscribe",
        "identifier": JSON.stringify({"channel": channel, "data": data})
      }));
  };
  var send_to = function(channel, data, message, action){
    if (typeof(data)==='undefined') data = "N/A";
    console.log("=> sending to: " + channel)
    new_data_stream().send(JSON.stringify({
        "command": "message",
        "identifier": JSON.stringify({"channel": channel, "data": data}),
        "data": JSON.stringify({"message": message, "action": action})
      }));
  };
  var new_data_stream = function(){
    if(dataStream == null) {
      dataStream = $websocket(wsUrl);
      dataStream.onClose(function(arg){
        close_connection();
        connected = false;
        methods.on_connection_close_callback();
      });
      dataStream.onOpen(function(arg){
        connected = true;
        currentChannels.forEach(function(channel){ subscribe_to(channel.name, channel.data); });
        methods.on_connection_open_callback();
      });
      dataStream.onMessage(function(message) {   //arriving message from backend
        controller.post(JSON.parse(message.data));
      });
    };
    return dataStream;
  };
  methods = {
    connected: function(){ return connected },
    attempt_restart: function(){
      close_connection();
      new_data_stream();
      return true;
    },
    currentChannels: currentChannels,
    close: function(){ return close_connection(); },
    on_connection_close_callback: function(){},
    on_connection_open_callback: function(){},
    subscribe: function(channel, data){
      currentChannels.push({name: channel, data: data});
      this.connected() && subscribe_to(channel, data);
    },
    unsubscribe: function(channel, data){
      for(var i=0; i<currentChannels.length; i++){ if (currentChannels[i].name===channel) {currentChannels.splice(i, 1);} }
      this.connected() && unsubscribe_from(channel, data);
    },
    send: function(channel, data, message, action){
      console.log("send requested");
      this.connected() && send_to(channel, data, message, action);
    }
  };
  return methods;
});

ngActionCable.factory("WebsocketChannel",function (WebsocketController, Websocket){
  return function(channelName, channelParams){
    this._websocketControllerActions= function(){
      var _channelParamsString= JSON.stringify(this.channelParams);
      WebsocketController.actions[this.channelName]= WebsocketController.actions[this.channelName] || {};
      WebsocketController.actions[this.channelName][_channelParamsString]= WebsocketController.actions[this.channelName][_channelParamsString] || [];
      return WebsocketController.actions[this.channelName][_channelParamsString];
    }

    this._subscriptionCount= function(){
      return this.callbacks.length;
    };

  }
});

// SocketWrangler to start, stop or try reconnect websockets every intervalTime milliseconds.
//
// Current status is denoted by three booleans:
// connected(), connecting(), and disconnected(), in an abstraction
// of the internal trivalent logic. Exactly one will be true at all times.
//
// Actions are start() and stop()
ngActionCable.factory("SocketWrangler", function(Websocket) {
  var intervalTime= 8647;
  var websocket= Websocket;
  var _live= false;
  var _connecting= false;
  var connectNow= function(){
    websocket.attempt_restart();
  };
  var startInterval= function(){
    _connecting= _connecting || setInterval(function(){
      connectNow();
    }, intervalTime);
  };
  var stopInterval= function(){
    clearInterval(_connecting);
    _connecting= false;
  };
  websocket.on_connection_close_callback = function(){
    if (_live) { startInterval(); };
    console.log("close callback");
  };
  websocket.on_connection_open_callback = function(){
    stopInterval();
    console.log("open callback");
  };
  var methods= {
    connected: function(){
      return (_live && !_connecting);
    },
    connecting: function(){
      return (_live && !!_connecting);
    },
    disconnected: function(){
      return !_live;
    },
    start: function(){
      console.info("Live STARTED");
      _live= true;
      startInterval();
      connectNow();
    },
    stop: function(){
      console.info("Live stopped");
      _live= false;
      stopInterval();
      websocket.close();
    }
  };
  return methods;
});
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    var defaultConfig, packageFile, toolsConfig, toolsFile;

    grunt.loadNpmTasks('grunt-contrib');
    grunt.loadNpmTasks('grunt-exec');
	grunt.loadNpmTasks('grunt-closure-tools');
	grunt.loadNpmTasks('grunt-replace');

	grunt.registerTask('patch_closure_tools_init', 'Initialize tools.', function(){
		grunt.initConfig({
			replace: {
				add_java_parm: {
					options: {
						  patterns: [
							{
							  match: '\'java \'',
							  replacement: '\'java -Xms1024m \''
							}
						  ],
						  usePrefix: false
					},
					files: [
						{
							src: 'node_modules/grunt-closure-tools/node_modules/task-closure-tools/lib/libCompiler.js',
							dest: 'node_modules/grunt-closure-tools/node_modules/task-closure-tools/lib/libCompiler.js'
						}
					]
				}
			}
		});
    });

	grunt.task.run(['patch_closure_tools_init', 'replace']);

	grunt.registerTask('setup_tools', 'Initialize tools.', function(){
        toolsConfig = 'tools.json';
        toolsFile = require('./' + toolsConfig);

        if (toolsFile)
            grunt.log.ok('Tools config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

	grunt.registerTask('cleanup_deploy_folder_init', 'Initialize tools.', function(){
		grunt.initConfig({
			clean: {
				options: {
					force: true
				},
				menu:[
					toolsFile['menu_path']
				]
			}
		});
    });

	grunt.registerTask('cleanup_deploy_folder',  ['cleanup_deploy_folder_init', 'clean']);

	grunt.registerTask('build_webword_init', 'Initialize build WebWord SDK.', function(){
        defaultConfig = './sdk_configs/webword.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebWord config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

	grunt.registerTask('build_nativeword_init', 'Initialize build NativeWord SDK.', function(){
        defaultConfig = './sdk_configs/nativeword.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('nativeword config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_webexcel_init', 'Initialize build WebExcel SDK.', function(){
        defaultConfig = './sdk_configs/webexcel.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebExcel config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_webpowerpoint_init', 'Initialize build WebPowerPoint SDK.', function(){
        defaultConfig = './sdk_configs/webpowerpoint.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebPowerPoint config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

	grunt.registerTask('build_sdk', 'Build sdk.', function(){
        if (packageFile) {
            if (packageFile['tasks']['build'])
                grunt.task.run(packageFile['tasks']['build']);
            else
                grunt.log.error().writeln('Not found "build" task in configure'.red);
        } else {
            grunt.log.error().writeln('Is not load configure file.'.red);
        }
    });

	grunt.registerTask('build_webword',     ['setup_tools', 'build_webword_init', 'build_sdk']);
	grunt.registerTask('build_nativeword', ['setup_tools', 'build_nativeword_init', 'build_sdk']);
    grunt.registerTask('build_webexcel',  ['setup_tools', 'build_webexcel_init', 'build_sdk']);
    grunt.registerTask('build_webpowerpoint', ['setup_tools', 'build_webpowerpoint_init', 'build_sdk']);

	grunt.registerTask('deploy_sdk_all', ['setup_tools', 'build_webword_init', 'deploy_sdk', 'build_webexcel_init', 'deploy_sdk', 'build_webpowerpoint_init', 'deploy_sdk']);

	grunt.registerTask('build_all_without_deploy', ['setup_tools', 'build_webword_init', 'build_sdk', 'build_webexcel_init', 'build_sdk', 'build_webpowerpoint_init', 'build_sdk']);
	grunt.registerTask('build_all', ['build_all_without_deploy', 'deploy_sdk_all']);
	grunt.registerTask('cleanup_and_build_all', ['setup_tools', 'cleanup_deploy_folder', 'build_all']);

	grunt.registerTask('up_sdk_src_init', 'Update SDK source', function() {
		grunt.initConfig({
			exec: {
				update_sources: {
					command: 'svn.exe up -q --non-interactive -r ' + packageFile['update_src']['revision'] + ' ' + packageFile['update_src']['src'],
					stdout: true
				},
				update_logs: {
					command: 'svn.exe up -q --non-interactive -r HEAD ' + packageFile['compile']['sdk']['log'],
					stdout: true
				}
			}
		});
    });

	grunt.registerTask('update_sources_webword', ['build_webword_init', 'up_sdk_src_init', 'exec']);
	grunt.registerTask('update_sources_webexcel', ['build_webexcel_init', 'up_sdk_src_init', 'exec']);
	grunt.registerTask('update_sources_webpowerpoint', ['build_webpowerpoint_init', 'up_sdk_src_init', 'exec']);

	grunt.registerTask('update_sources', ['update_sources_webword', 'update_sources_webexcel', 'update_sources_webpowerpoint']);

	grunt.registerTask('commit_logs_init', function() {
		var build_num = packageFile['info']['build'];
		var svn_rev = packageFile['update_src']['revision'];

		if(undefined !== process.env['BUILD_NUMBER'])
			build_num = parseInt(process.env['BUILD_NUMBER']);

		if(undefined !== process.env['SVN_REVISION'])
			svn_rev = parseInt(process.env['SVN_REVISION']);

		var commit_message ='\"Version: '+ packageFile['info']['version'] +
							' (build:' + build_num + ')' +
							' from svn rev: ' + svn_rev + '\"';
        grunt.initConfig({
			exec: {
				store_log: {
					command: 'svn.exe commit ' + packageFile['deploy']['store_log']['dst'] + ' -q -m ' + commit_message,
					stdout: false
				}
			}
        });
    });

	grunt.registerTask('commit_logs_webword', ['build_webword_init', 'commit_logs_init', 'exec']);
	grunt.registerTask('commit_logs_webexcel', ['build_webexcel_init', 'commit_logs_init', 'exec']);
	grunt.registerTask('commit_logs_webpowerpoint', ['build_webpowerpoint_init', 'commit_logs_init', 'exec']);

	grunt.registerTask('commit_logs', ['commit_logs_webword', 'commit_logs_webexcel', 'commit_logs_webpowerpoint']);

    grunt.registerTask('increment_build', function() {
		var pkg = grunt.file.readJSON(defaultConfig);
		pkg.info.build = parseInt(pkg.info.build) + 1;

		if(undefined !== process.env['BUILD_NUMBER']) {
			grunt.log.ok('Use Jenkins build number as sdk-all build number!'.yellow);
			packageFile['info']['build'] = parseInt(process.env['BUILD_NUMBER']);
			pkg.info.build = packageFile['info']['build'];
		}
		if(undefined !== process.env['SVN_REVISION']){
			packageFile['info']['rev'] = process.env['SVN_REVISION'];
		}
		else{
			packageFile['info']['rev'] = "unknown";
		}
		grunt.file.write(defaultConfig, JSON.stringify(pkg, null, 4));
    });

	grunt.registerTask('concat_js_api_init', 'Concatinate JS API', function() {
        grunt.initConfig({
            concat:  packageFile['concat_api']
        });
    });
	grunt.registerTask('concat_js_api', ['concat_js_api_init', 'concat']);

	grunt.registerTask('extract_js_api_init', 'Extract JS API', function(){
		grunt.initConfig({
			exec: {
				api: {
					command: 'bin\\ExtractJSApi.exe ' + packageFile['extract_api']['src'] + ' ' + packageFile['extract_api']['dst'],
					stdout: false
				}
			}
		});
	});
	grunt.registerTask('extract_js_api', ['extract_js_api_init', 'exec']);

	grunt.registerTask('create_map_file', function() {
		//      ,    .
		var map_file_path = packageFile['compile']['sdk']['dst'] + '.map';
		var map_record = '//@ sourceMappingURL=' + packageFile['compile']['source_map']['url'] + '/' + map_file_path;

		var map_record_file_path = map_file_path + '.tmp';
		grunt.file.write(map_record_file_path, map_record);
	});

	grunt.registerTask('compile_sdk_init', function(compilation_level) {
		var map_file_path = packageFile['compile']['sdk']['dst'] + '.map';
		var map_record_file_path = map_file_path + '.tmp';
		var concat_res = {};
		concat_res[packageFile['compile']['sdk']['dst']] = [
					packageFile['compile']['sdk']['dst'],
					packageFile['compile']['defines']['dst'],
					map_record_file_path ];
		grunt.initConfig({
			closureCompiler: {
				options: {
					compilerFile: toolsFile['closure_compiler'],
					d32: true
				},
				sdk: {
					TEMPcompilerOpts: {
						compilation_level: compilation_level,
						externs: packageFile['compile']['sdk']['externs'],
						define: packageFile['compile']['sdk']['define'],
						warning_level: 'QUIET',
						variable_renaming_report: packageFile['compile']['sdk']['log'] + '/variable.map',
						property_renaming_report: packageFile['compile']['sdk']['log'] + '/property.map'/*,
						create_source_map: map_file_path,
						source_map_format: "V3"*/
					},
					src: packageFile['compile']['sdk']['src'],
					dest: packageFile['compile']['sdk']['dst']
				},
				defines: {
					TEMPcompilerOpts: {
						compilation_level: 'SIMPLE',
						warning_level: 'QUIET'
					},
					src: packageFile['compile']['defines']['src'],
					dest: packageFile['compile']['defines']['dst']
				}
			},
			create_map_file: {},
			concat: concat_res,
			clean: [
				packageFile['compile']['defines']['dst'],
				map_record_file_path
			],
			pkg: grunt.file.readJSON(defaultConfig),
			replace: {
				version: {
					options: {
						variables: {
							Version: packageFile['info']['version'],
							Build: packageFile['info']['build'].toString(),
							Rev: packageFile['info']['rev'].toString()
						}
					},
					files: {
						'<%= pkg.compile.sdk.dst %>': '<%= pkg.compile.sdk.dst %>'
					}
				}
			}
		});
	});

	grunt.registerTask('compile_sdk', ['compile_sdk_init:ADVANCED', 'closureCompiler', 'concat', 'replace', 'clean']);
	grunt.registerTask('compile_sdk_fast', ['compile_sdk_init:WHITESPACE_ONLY', 'closureCompiler', 'concat', 'replace', 'clean']);

	grunt.registerTask('compile_sdk_native', ['compile_sdk_init:ADVANCED', 'closureCompiler:sdk', 'concat', 'replace', 'clean']);
	grunt.registerTask('compile_sdk_native_fast', ['compile_sdk_init:WHITESPACE_ONLY', 'closureCompiler:sdk', 'concat', 'replace', 'clean']);

	grunt.registerTask('deploy_sdk_init', function() {
        grunt.initConfig({
		    pkg: grunt.file.readJSON(toolsConfig),
            copy:  packageFile['deploy']['copy']
        });
    });

	grunt.registerTask('deploy_sdk', ['deploy_sdk_init', 'copy']);

	grunt.registerTask('default', 'build_all_without_deploy');
};<commit_msg>Отключана опция d32, т.к. не работает в 64-разрядной java.<commit_after>module.exports = function(grunt) {
    var defaultConfig, packageFile, toolsConfig, toolsFile;

    grunt.loadNpmTasks('grunt-contrib');
    grunt.loadNpmTasks('grunt-exec');
	grunt.loadNpmTasks('grunt-closure-tools');
	grunt.loadNpmTasks('grunt-replace');

	grunt.registerTask('patch_closure_tools_init', 'Initialize tools.', function(){
		grunt.initConfig({
			replace: {
				add_java_parm: {
					options: {
						  patterns: [
							{
							  match: '\'java \'',
							  replacement: '\'java -Xms1024m \''
							}
						  ],
						  usePrefix: false
					},
					files: [
						{
							src: 'node_modules/grunt-closure-tools/node_modules/task-closure-tools/lib/libCompiler.js',
							dest: 'node_modules/grunt-closure-tools/node_modules/task-closure-tools/lib/libCompiler.js'
						}
					]
				}
			}
		});
    });

	grunt.task.run(['patch_closure_tools_init', 'replace']);

	grunt.registerTask('setup_tools', 'Initialize tools.', function(){
        toolsConfig = 'tools.json';
        toolsFile = require('./' + toolsConfig);

        if (toolsFile)
            grunt.log.ok('Tools config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

	grunt.registerTask('cleanup_deploy_folder_init', 'Initialize tools.', function(){
		grunt.initConfig({
			clean: {
				options: {
					force: true
				},
				menu:[
					toolsFile['menu_path']
				]
			}
		});
    });

	grunt.registerTask('cleanup_deploy_folder',  ['cleanup_deploy_folder_init', 'clean']);

	grunt.registerTask('build_webword_init', 'Initialize build WebWord SDK.', function(){
        defaultConfig = './sdk_configs/webword.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebWord config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

	grunt.registerTask('build_nativeword_init', 'Initialize build NativeWord SDK.', function(){
        defaultConfig = './sdk_configs/nativeword.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('nativeword config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_webexcel_init', 'Initialize build WebExcel SDK.', function(){
        defaultConfig = './sdk_configs/webexcel.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebExcel config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_webpowerpoint_init', 'Initialize build WebPowerPoint SDK.', function(){
        defaultConfig = './sdk_configs/webpowerpoint.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebPowerPoint config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

	grunt.registerTask('build_sdk', 'Build sdk.', function(){
        if (packageFile) {
            if (packageFile['tasks']['build'])
                grunt.task.run(packageFile['tasks']['build']);
            else
                grunt.log.error().writeln('Not found "build" task in configure'.red);
        } else {
            grunt.log.error().writeln('Is not load configure file.'.red);
        }
    });

	grunt.registerTask('build_webword',     ['setup_tools', 'build_webword_init', 'build_sdk']);
	grunt.registerTask('build_nativeword', ['setup_tools', 'build_nativeword_init', 'build_sdk']);
    grunt.registerTask('build_webexcel',  ['setup_tools', 'build_webexcel_init', 'build_sdk']);
    grunt.registerTask('build_webpowerpoint', ['setup_tools', 'build_webpowerpoint_init', 'build_sdk']);

	grunt.registerTask('deploy_sdk_all', ['setup_tools', 'build_webword_init', 'deploy_sdk', 'build_webexcel_init', 'deploy_sdk', 'build_webpowerpoint_init', 'deploy_sdk']);

	grunt.registerTask('build_all_without_deploy', ['setup_tools', 'build_webword_init', 'build_sdk', 'build_webexcel_init', 'build_sdk', 'build_webpowerpoint_init', 'build_sdk']);
	grunt.registerTask('build_all', ['build_all_without_deploy', 'deploy_sdk_all']);
	grunt.registerTask('cleanup_and_build_all', ['setup_tools', 'cleanup_deploy_folder', 'build_all']);

	grunt.registerTask('up_sdk_src_init', 'Update SDK source', function() {
		grunt.initConfig({
			exec: {
				update_sources: {
					command: 'svn.exe up -q --non-interactive -r ' + packageFile['update_src']['revision'] + ' ' + packageFile['update_src']['src'],
					stdout: true
				},
				update_logs: {
					command: 'svn.exe up -q --non-interactive -r HEAD ' + packageFile['compile']['sdk']['log'],
					stdout: true
				}
			}
		});
    });

	grunt.registerTask('update_sources_webword', ['build_webword_init', 'up_sdk_src_init', 'exec']);
	grunt.registerTask('update_sources_webexcel', ['build_webexcel_init', 'up_sdk_src_init', 'exec']);
	grunt.registerTask('update_sources_webpowerpoint', ['build_webpowerpoint_init', 'up_sdk_src_init', 'exec']);

	grunt.registerTask('update_sources', ['update_sources_webword', 'update_sources_webexcel', 'update_sources_webpowerpoint']);

	grunt.registerTask('commit_logs_init', function() {
		var build_num = packageFile['info']['build'];
		var svn_rev = packageFile['update_src']['revision'];

		if(undefined !== process.env['BUILD_NUMBER'])
			build_num = parseInt(process.env['BUILD_NUMBER']);

		if(undefined !== process.env['SVN_REVISION'])
			svn_rev = parseInt(process.env['SVN_REVISION']);

		var commit_message ='\"Version: '+ packageFile['info']['version'] +
							' (build:' + build_num + ')' +
							' from svn rev: ' + svn_rev + '\"';
        grunt.initConfig({
			exec: {
				store_log: {
					command: 'svn.exe commit ' + packageFile['deploy']['store_log']['dst'] + ' -q -m ' + commit_message,
					stdout: false
				}
			}
        });
    });

	grunt.registerTask('commit_logs_webword', ['build_webword_init', 'commit_logs_init', 'exec']);
	grunt.registerTask('commit_logs_webexcel', ['build_webexcel_init', 'commit_logs_init', 'exec']);
	grunt.registerTask('commit_logs_webpowerpoint', ['build_webpowerpoint_init', 'commit_logs_init', 'exec']);

	grunt.registerTask('commit_logs', ['commit_logs_webword', 'commit_logs_webexcel', 'commit_logs_webpowerpoint']);

    grunt.registerTask('increment_build', function() {
		var pkg = grunt.file.readJSON(defaultConfig);
		pkg.info.build = parseInt(pkg.info.build) + 1;

		if(undefined !== process.env['BUILD_NUMBER']) {
			grunt.log.ok('Use Jenkins build number as sdk-all build number!'.yellow);
			packageFile['info']['build'] = parseInt(process.env['BUILD_NUMBER']);
			pkg.info.build = packageFile['info']['build'];
		}
		if(undefined !== process.env['SVN_REVISION']){
			packageFile['info']['rev'] = process.env['SVN_REVISION'];
		}
		else{
			packageFile['info']['rev'] = "unknown";
		}
		grunt.file.write(defaultConfig, JSON.stringify(pkg, null, 4));
    });

	grunt.registerTask('concat_js_api_init', 'Concatinate JS API', function() {
        grunt.initConfig({
            concat:  packageFile['concat_api']
        });
    });
	grunt.registerTask('concat_js_api', ['concat_js_api_init', 'concat']);

	grunt.registerTask('extract_js_api_init', 'Extract JS API', function(){
		grunt.initConfig({
			exec: {
				api: {
					command: 'bin\\ExtractJSApi.exe ' + packageFile['extract_api']['src'] + ' ' + packageFile['extract_api']['dst'],
					stdout: false
				}
			}
		});
	});
	grunt.registerTask('extract_js_api', ['extract_js_api_init', 'exec']);

	grunt.registerTask('create_map_file', function() {
		//      ,    .
		var map_file_path = packageFile['compile']['sdk']['dst'] + '.map';
		var map_record = '//@ sourceMappingURL=' + packageFile['compile']['source_map']['url'] + '/' + map_file_path;

		var map_record_file_path = map_file_path + '.tmp';
		grunt.file.write(map_record_file_path, map_record);
	});

	grunt.registerTask('compile_sdk_init', function(compilation_level) {
		var map_file_path = packageFile['compile']['sdk']['dst'] + '.map';
		var map_record_file_path = map_file_path + '.tmp';
		var concat_res = {};
		concat_res[packageFile['compile']['sdk']['dst']] = [
					packageFile['compile']['sdk']['dst'],
					packageFile['compile']['defines']['dst'],
					map_record_file_path ];
		grunt.initConfig({
			closureCompiler: {
				options: {
					compilerFile: toolsFile['closure_compiler']
				},
				sdk: {
					TEMPcompilerOpts: {
						compilation_level: compilation_level,
						externs: packageFile['compile']['sdk']['externs'],
						define: packageFile['compile']['sdk']['define'],
						warning_level: 'QUIET',
						variable_renaming_report: packageFile['compile']['sdk']['log'] + '/variable.map',
						property_renaming_report: packageFile['compile']['sdk']['log'] + '/property.map'/*,
						create_source_map: map_file_path,
						source_map_format: "V3"*/
					},
					src: packageFile['compile']['sdk']['src'],
					dest: packageFile['compile']['sdk']['dst']
				},
				defines: {
					TEMPcompilerOpts: {
						compilation_level: 'SIMPLE',
						warning_level: 'QUIET'
					},
					src: packageFile['compile']['defines']['src'],
					dest: packageFile['compile']['defines']['dst']
				}
			},
			create_map_file: {},
			concat: concat_res,
			clean: [
				packageFile['compile']['defines']['dst'],
				map_record_file_path
			],
			pkg: grunt.file.readJSON(defaultConfig),
			replace: {
				version: {
					options: {
						variables: {
							Version: packageFile['info']['version'],
							Build: packageFile['info']['build'].toString(),
							Rev: packageFile['info']['rev'].toString()
						}
					},
					files: {
						'<%= pkg.compile.sdk.dst %>': '<%= pkg.compile.sdk.dst %>'
					}
				}
			}
		});
	});

	grunt.registerTask('compile_sdk', ['compile_sdk_init:ADVANCED', 'closureCompiler', 'concat', 'replace', 'clean']);
	grunt.registerTask('compile_sdk_fast', ['compile_sdk_init:WHITESPACE_ONLY', 'closureCompiler', 'concat', 'replace', 'clean']);

	grunt.registerTask('compile_sdk_native', ['compile_sdk_init:ADVANCED', 'closureCompiler:sdk', 'concat', 'replace', 'clean']);
	grunt.registerTask('compile_sdk_native_fast', ['compile_sdk_init:WHITESPACE_ONLY', 'closureCompiler:sdk', 'concat', 'replace', 'clean']);

	grunt.registerTask('deploy_sdk_init', function() {
        grunt.initConfig({
		    pkg: grunt.file.readJSON(toolsConfig),
            copy:  packageFile['deploy']['copy']
        });
    });

	grunt.registerTask('deploy_sdk', ['deploy_sdk_init', 'copy']);

	grunt.registerTask('default', 'build_all_without_deploy');
};<|endoftext|>


<commit_before>module.exports = function(grunt) {
    var defaultConfig, packageFile;

    grunt.loadNpmTasks('grunt-contrib');

    grunt.registerTask('build_webword_init', 'Initialize build WebWord SDK.', function(){
        defaultConfig = './webword.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebWord config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_webexcel_init', 'Initialize build WebExcel SDK.', function(){
        defaultConfig = './webexcel.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebExcel config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_webpowerpoint_init', 'Initialize build WebPowerPoint SDK.', function(){
        defaultConfig = './webpowerpoint.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebPowerPoint config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_sdk', 'Build sdk.', function(){
        if (packageFile) {
            if (packageFile['tasks']['build'])
                grunt.task.run(packageFile['tasks']['build']);
            else
                grunt.log.error().writeln('Not found "build" task in configure'.red);
        } else {
            grunt.log.error().writeln('Is not load configure file.'.red);
        }
    });

    grunt.registerTask('build_webword',     'build_webword_init build_sdk');
    grunt.registerTask('build_webexcel',  'build_webexcel_init build_sdk');
    grunt.registerTask('build_webpowerpoint', 'build_webpowerpoint_init build_sdk');
    grunt.registerTask('build_all', 'build_webword_init build_sdk build_webexcel_init build_sdk build_webpowerpoint_init build_sdk');

    grunt.registerTask('compile_sdk_init', function() {
        grunt.initConfig({
            pkg: '<json:' + defaultConfig + '>',
            meta: {
                banner: '/*\n' +
                    ' * Copyright (c) Ascensio System SIA <%= grunt.template.today("yyyy") %>. All rights reserved\n' +
                    ' *\n' +
                    ' * <%= pkg.homepage %> \n' +
                    ' *\n' +
                    ' * Version: <%= pkg.version %> (build:<%= pkg.build %>)\n' +
                    ' */'
            },

            min: {
                sdk: {
                    src: ['<banner:meta.banner>'].concat(packageFile['compile']["sdk"]['src']),
                    dest: packageFile['compile']["sdk"]['dst']
                }
            }
        });
    });
    grunt.registerTask('compile_sdk', 'compile_sdk_init min');

    grunt.registerTask('default', 'build_all');
};<commit_msg>Усправлено формирование шапки.<commit_after>module.exports = function(grunt) {
    var defaultConfig, packageFile;

    grunt.loadNpmTasks('grunt-contrib');

    grunt.registerTask('build_webword_init', 'Initialize build WebWord SDK.', function(){
        defaultConfig = './webword.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebWord config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_webexcel_init', 'Initialize build WebExcel SDK.', function(){
        defaultConfig = './webexcel.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebExcel config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_webpowerpoint_init', 'Initialize build WebPowerPoint SDK.', function(){
        defaultConfig = './webpowerpoint.json';
        packageFile = require(defaultConfig);

        if (packageFile)
            grunt.log.ok('WebPowerPoint config loaded successfully'.green);
        else
            grunt.log.error().writeln('Could not load config file'.red);
    });

    grunt.registerTask('build_sdk', 'Build sdk.', function(){
        if (packageFile) {
            if (packageFile['tasks']['build'])
                grunt.task.run(packageFile['tasks']['build']);
            else
                grunt.log.error().writeln('Not found "build" task in configure'.red);
        } else {
            grunt.log.error().writeln('Is not load configure file.'.red);
        }
    });

    grunt.registerTask('build_webword',     'build_webword_init build_sdk');
    grunt.registerTask('build_webexcel',  'build_webexcel_init build_sdk');
    grunt.registerTask('build_webpowerpoint', 'build_webpowerpoint_init build_sdk');
    grunt.registerTask('build_all', 'build_webword_init build_sdk build_webexcel_init build_sdk build_webpowerpoint_init build_sdk');

    grunt.registerTask('compile_sdk_init', function() {
        grunt.initConfig({
            pkg: '<json:' + defaultConfig + '>',
            meta: {
                banner: '/*\n' +
                    ' * Copyright (c) Ascensio System SIA <%= grunt.template.today("yyyy") %>. All rights reserved\n' +
                    ' *\n' +
                    ' * <%= pkg.info.homepage %> \n' +
                    ' *\n' +
                    ' * Version: <%= pkg.info.version %> (build:<%= pkg.info.build %>)\n' +
                    ' */'
            },

            min: {
                sdk: {
                    src: ['<banner:meta.banner>'].concat(packageFile['compile']["sdk"]['src']),
                    dest: packageFile['compile']["sdk"]['dst']
                }
            }
        });
    });
    grunt.registerTask('compile_sdk', 'compile_sdk_init min');

    grunt.registerTask('default', 'build_all');
};<|endoftext|>