<commit_before>import Vapi from 'vuex-rest-api'
import Vuex from 'vuex'
import viisiConfig from '~/distrochooser.json'
const indexStore = new Vapi({
  baseURL: viisiConfig.frontend.backendUrl,
  state: {
    data: null, //for initial bulk loading
    question: null,
    answers: null,
    categories: null,
    currentCategory: null,
    givenAnswers: [],
    token: null, //session token
    sessionToken: null, //private session token
    isStarted: false,
    result: null,
    translations: null,
    locales: ['en', 'gb', 'us', 'de', 'it', 'cn', 'vn'],
    voteResult: null,
    remarksAdded: false,
    language: 'en',
    testCount: 0,
    oldTestData: null,
    isSubmitted: false,
    rootUrl: viisiConfig.frontend.frontendUrl,
    socialNetworks: viisiConfig.frontend.socialNetworks,
    answerBlockedAnswers: [],
    sessionStatus: null,
    method: 'default'
  }
})
  .post({
    action: 'start',
    property: 'data',
    path: ({ language }) => `start/${language}/`
  })
  .get({
    action: 'language',
    property: 'data',
    path: ({ language }) => `translation/${language}/`
  })
  .get({
    action: 'loadQuestion',
    property: 'data',
    path: ({ index }) => `question/${index}/`
  })
  .post({
    action: 'submit',
    property: 'result',
    path: ({ language, token, method }) =>
      `submit/${language}/${token}/${method}/`
  })
  .post({
    action: 'voteSelection',
    property: 'voteResult',
    path: () => `vote/`
  })
  .post({
    action: 'addRemarks',
    property: 'remarksAdded',
    path: () => `remarks/`
  })
  .get({
    action: 'getOldAnswers',
    property: 'oldTestData',
    path: ({ slug }) => `answers/${slug}/`
  })
  .get({
    action: 'loadTranslations',
    property: 'translations',
    path: ({ language }) => `translations/${language}/`
  })
  .get({
    action: 'getAnswerBlockedAnswers',
    property: 'answerBlockedAnswers',
    path: ({ msgid }) => `blockedanswers/${msgid}/`
  })
  .get({
    action: 'getSessionStatus',
    property: 'sessionStatus',
    path: ({ token }) => `status/${token}/`
  })
  .getStore()

indexStore.actions.answerQuestion = async (store, payload) => {
  var answer = payload.selectedAnswer
  var answer = {
    msgid: answer.msgid,
    answered: true,
    important: false,
    category: payload.currentCategory.msgid,
    blockedAnswers: answer.blockedAnswers
  }
  store.commit('setAnswerQuestion', answer)
}

indexStore.actions.submitAnswers = async (store, payload) => {
  store.commit('toggleSubmitted')
  await store.dispatch('submit', payload)
  store.commit('toggleSubmitted')
}

indexStore.mutations.setAnswerQuestion = (state, answer) => {
  state.givenAnswers.push(answer)
}

indexStore.mutations.toggleSubmitted = state => {
  state.isSubmitted = !state.isSubmitted
}

indexStore.mutations.toggleImportanceState = (state, answer) => {
  state.givenAnswers.forEach(a => {
    if (a.msgid === answer.msgid) {
      a.important = !a.important
    }
  })
}

indexStore.mutations.removeAnswerQuestion = (state, answer) => {
  for (var i = 0; i < state.givenAnswers.length; i++) {
    if (state.givenAnswers[i].msgid === answer.msgid) {
      state.givenAnswers.splice(i, 1)
      break
    }
  }
}

indexStore.actions.selectCategory = async (store, payload) => {
  store.commit('setStarted') //make sure the test is active
  var category = payload.selectedCategory
  store.commit('setSelectCategory', category)
  await store.dispatch('loadQuestion', {
    params: {
      index: category.index
    }
  })
  store.commit('setCurrentQuestionData', store.state.data)
  store.commit('resetResult')
}

indexStore.mutations.setSelectCategory = (state, category) => {
  state.currentCategory = category
}

indexStore.actions.startTest = async (store, payload) => {
  await store.dispatch('start', payload)
  store.commit('setCurrentDisplayData', store.state.data)
  store.commit('setCurrentQuestionData', store.state.data)
}

indexStore.actions.switchLanguage = async (store, payload) => {
  await store.dispatch('language', payload)
  store.commit('setLanguageData', store.state.data)
}

indexStore.mutations.setLanguageData = (state, data) => {
  state.translations = data.translations
}

indexStore.mutations.setCurrentDisplayData = (state, data) => {
  state.categories = data.categories
  state.token = data.token
  state.sessionToken = data.sessionToken
  state.language = data.language
  state.testCount = data.testCount
  state.translations = data.translations
}

indexStore.mutations.setCurrentQuestionData = (state, data) => {
  state.question = data.question
  state.answers = data.answers
}

indexStore.mutations.setStarted = state => {
  state.isStarted = true
}

indexStore.mutations.resetStarted = state => {
  state.isStarted = false
  state.isSubmitted = false
  state.result = null
  state.currentCategory = null
}

indexStore.mutations.resetResult = state => {
  state.result = null
}

indexStore.mutations.resetRemarksAdded = state => {
  state.remarksAdded = false
}

indexStore.mutations.setOldTestData = state => {
  for (var i = 0; i < state.oldTestData.answers.length; i++) {
    var answer = state.oldTestData.answers[i]
    var category = state.oldTestData.categories[i]
    state.givenAnswers.push({
      //TODO: IS REDUNDANT
      msgid: answer,
      answered: true,
      important: state.oldTestData.important.indexOf(answer) !== -1,
      category: category,
      blockedAnswers: []
    })
  }
}

indexStore.actions.nextQuestion = (store, payload) => {
  store.commit('setStarted') //make sure the test is active
  const currentCategory = store.state.currentCategory
  var nextCategory = null
  if (currentCategory === null) {
    nextCategory = store.state.categories[0]
  } else {
    store.state.categories.forEach(c => {
      if (c.index === currentCategory.index + 1) {
        nextCategory = c
        return
      }
    })
  }
  store.dispatch('selectCategory', {
    language: payload.params.language,
    selectedCategory: nextCategory
  })
}

indexStore.actions.prevQuestion = (store, payload) => {
  store.commit('setStarted') //make sure the test is active
  const currentCategory = store.state.currentCategory
  var nextCategory = null
  if (currentCategory === null) {
    nextCategory = store.state.categories[0]
  } else {
    store.state.categories.forEach(c => {
      if (c.index === currentCategory.index - 1) {
        nextCategory = c
        return
      }
    })
  }
  store.dispatch('selectCategory', {
    language: payload.params.language,
    selectedCategory: nextCategory
  })
}

const createStore = () => {
  return new Vuex.Store(indexStore)
}

export default createStore
<commit_msg>Added ch as allowed language<commit_after>import Vapi from 'vuex-rest-api'
import Vuex from 'vuex'
import viisiConfig from '~/distrochooser.json'
const indexStore = new Vapi({
  baseURL: viisiConfig.frontend.backendUrl,
  state: {
    data: null, //for initial bulk loading
    question: null,
    answers: null,
    categories: null,
    currentCategory: null,
    givenAnswers: [],
    token: null, //session token
    sessionToken: null, //private session token
    isStarted: false,
    result: null,
    translations: null,
    locales: ['en', 'gb', 'us', 'de', 'it', 'cn', 'vn', 'ch'],
    voteResult: null,
    remarksAdded: false,
    language: 'en',
    testCount: 0,
    oldTestData: null,
    isSubmitted: false,
    rootUrl: viisiConfig.frontend.frontendUrl,
    socialNetworks: viisiConfig.frontend.socialNetworks,
    answerBlockedAnswers: [],
    sessionStatus: null,
    method: 'default'
  }
})
  .post({
    action: 'start',
    property: 'data',
    path: ({ language }) => `start/${language}/`
  })
  .get({
    action: 'language',
    property: 'data',
    path: ({ language }) => `translation/${language}/`
  })
  .get({
    action: 'loadQuestion',
    property: 'data',
    path: ({ index }) => `question/${index}/`
  })
  .post({
    action: 'submit',
    property: 'result',
    path: ({ language, token, method }) =>
      `submit/${language}/${token}/${method}/`
  })
  .post({
    action: 'voteSelection',
    property: 'voteResult',
    path: () => `vote/`
  })
  .post({
    action: 'addRemarks',
    property: 'remarksAdded',
    path: () => `remarks/`
  })
  .get({
    action: 'getOldAnswers',
    property: 'oldTestData',
    path: ({ slug }) => `answers/${slug}/`
  })
  .get({
    action: 'loadTranslations',
    property: 'translations',
    path: ({ language }) => `translations/${language}/`
  })
  .get({
    action: 'getAnswerBlockedAnswers',
    property: 'answerBlockedAnswers',
    path: ({ msgid }) => `blockedanswers/${msgid}/`
  })
  .get({
    action: 'getSessionStatus',
    property: 'sessionStatus',
    path: ({ token }) => `status/${token}/`
  })
  .getStore()

indexStore.actions.answerQuestion = async (store, payload) => {
  var answer = payload.selectedAnswer
  var answer = {
    msgid: answer.msgid,
    answered: true,
    important: false,
    category: payload.currentCategory.msgid,
    blockedAnswers: answer.blockedAnswers
  }
  store.commit('setAnswerQuestion', answer)
}

indexStore.actions.submitAnswers = async (store, payload) => {
  store.commit('toggleSubmitted')
  await store.dispatch('submit', payload)
  store.commit('toggleSubmitted')
}

indexStore.mutations.setAnswerQuestion = (state, answer) => {
  state.givenAnswers.push(answer)
}

indexStore.mutations.toggleSubmitted = state => {
  state.isSubmitted = !state.isSubmitted
}

indexStore.mutations.toggleImportanceState = (state, answer) => {
  state.givenAnswers.forEach(a => {
    if (a.msgid === answer.msgid) {
      a.important = !a.important
    }
  })
}

indexStore.mutations.removeAnswerQuestion = (state, answer) => {
  for (var i = 0; i < state.givenAnswers.length; i++) {
    if (state.givenAnswers[i].msgid === answer.msgid) {
      state.givenAnswers.splice(i, 1)
      break
    }
  }
}

indexStore.actions.selectCategory = async (store, payload) => {
  store.commit('setStarted') //make sure the test is active
  var category = payload.selectedCategory
  store.commit('setSelectCategory', category)
  await store.dispatch('loadQuestion', {
    params: {
      index: category.index
    }
  })
  store.commit('setCurrentQuestionData', store.state.data)
  store.commit('resetResult')
}

indexStore.mutations.setSelectCategory = (state, category) => {
  state.currentCategory = category
}

indexStore.actions.startTest = async (store, payload) => {
  await store.dispatch('start', payload)
  store.commit('setCurrentDisplayData', store.state.data)
  store.commit('setCurrentQuestionData', store.state.data)
}

indexStore.actions.switchLanguage = async (store, payload) => {
  await store.dispatch('language', payload)
  store.commit('setLanguageData', store.state.data)
}

indexStore.mutations.setLanguageData = (state, data) => {
  state.translations = data.translations
}

indexStore.mutations.setCurrentDisplayData = (state, data) => {
  state.categories = data.categories
  state.token = data.token
  state.sessionToken = data.sessionToken
  state.language = data.language
  state.testCount = data.testCount
  state.translations = data.translations
}

indexStore.mutations.setCurrentQuestionData = (state, data) => {
  state.question = data.question
  state.answers = data.answers
}

indexStore.mutations.setStarted = state => {
  state.isStarted = true
}

indexStore.mutations.resetStarted = state => {
  state.isStarted = false
  state.isSubmitted = false
  state.result = null
  state.currentCategory = null
}

indexStore.mutations.resetResult = state => {
  state.result = null
}

indexStore.mutations.resetRemarksAdded = state => {
  state.remarksAdded = false
}

indexStore.mutations.setOldTestData = state => {
  for (var i = 0; i < state.oldTestData.answers.length; i++) {
    var answer = state.oldTestData.answers[i]
    var category = state.oldTestData.categories[i]
    state.givenAnswers.push({
      //TODO: IS REDUNDANT
      msgid: answer,
      answered: true,
      important: state.oldTestData.important.indexOf(answer) !== -1,
      category: category,
      blockedAnswers: []
    })
  }
}

indexStore.actions.nextQuestion = (store, payload) => {
  store.commit('setStarted') //make sure the test is active
  const currentCategory = store.state.currentCategory
  var nextCategory = null
  if (currentCategory === null) {
    nextCategory = store.state.categories[0]
  } else {
    store.state.categories.forEach(c => {
      if (c.index === currentCategory.index + 1) {
        nextCategory = c
        return
      }
    })
  }
  store.dispatch('selectCategory', {
    language: payload.params.language,
    selectedCategory: nextCategory
  })
}

indexStore.actions.prevQuestion = (store, payload) => {
  store.commit('setStarted') //make sure the test is active
  const currentCategory = store.state.currentCategory
  var nextCategory = null
  if (currentCategory === null) {
    nextCategory = store.state.categories[0]
  } else {
    store.state.categories.forEach(c => {
      if (c.index === currentCategory.index - 1) {
        nextCategory = c
        return
      }
    })
  }
  store.dispatch('selectCategory', {
    language: payload.params.language,
    selectedCategory: nextCategory
  })
}

const createStore = () => {
  return new Vuex.Store(indexStore)
}

export default createStore
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { isEqual } from 'lodash-es'
import { Provider } from '../ChartContext';
import { validChartTypes } from '../../utils/propTypeValidators'

class BaseChart extends Component {

  static defaultProps = {
    children: null,
    className: '',
    callback: () => {}
  };

  static propTypes = {
    chartCreationFunc: PropTypes.func.isRequired,
    chartType: validChartTypes.isRequired,
    callback: PropTypes.func.isRequired
  };

  constructor (props) {
    super(props);

    this.state = {
      rendered: false
    };
  }

  componentDidMount () {
    // Need to wait for CSS to be applied to parent nodes, or chart is rendered at wrong size
    window.setTimeout(this.initHighcharts, 0);
  }

  initHighcharts = () => {
    if (!this.domNode) {
      return;
    }

    const { chartCreationFunc, callback, polar, gauge, children, ...rest } = this.props;

    const opts = {
      chart: {},
      title: {
        text: null
      },
      subtitle: {
        text: null
      },
      legend: {
        enabled: false
      },
      rangeSelector: {
        enabled: false
      },
      navigator: {
        enabled: false
      },
      scrollbar: {
        enabled: false
      },
      tooltip: {
        enabled: false
      },
      credits: {
        enabled: false
      },
      series: [],
      xAxis: [],
      yAxis: [],
      ...rest
    };
    this.chart = chartCreationFunc(this.domNode, opts);

    this.chart.polar = polar;
    this.chart.angular = gauge;

    callback(this.chart);

    this.setState({
      rendered: true
    })
  }

  componentDidUpdate (prevProps) {
    const { plotOptions } = this.props
    if (isEqual(prevProps.plotOptions, plotOptions) === false && this.chart) {
      this.chart.update({ plotOptions }, true)
    }
  }

  componentWillUnmount () {
    if (this.chart) { // Fixes #14
      window.setTimeout(this.chart.destroy.bind(this.chart), 1);
      this.chart.__destroyed = true;
    }
  }

  render () {
    const { chartType, children } = this.props;

    return (
      <div
        className={`chart ${this.props.className}`}
        ref={(node) => { this.domNode = node }}>
        {this.state.rendered && (
          <Provider value={{ chart: this.chart, chartType }}>
            {children}
          </Provider>
        )}
      </div>
    );
  }
}

export default BaseChart;
<commit_msg>Make setDomNode a function<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { isEqual } from 'lodash-es'
import { Provider } from '../ChartContext';
import { validChartTypes } from '../../utils/propTypeValidators'

class BaseChart extends Component {

  static defaultProps = {
    children: null,
    className: '',
    callback: () => {}
  };

  static propTypes = {
    chartCreationFunc: PropTypes.func.isRequired,
    chartType: validChartTypes.isRequired,
    callback: PropTypes.func.isRequired
  };

  constructor (props) {
    super(props);

    this.state = {
      rendered: false
    };
  }

  componentDidMount () {
    // Need to wait for CSS to be applied to parent nodes, or chart is rendered at wrong size
    window.setTimeout(this.initHighcharts, 0);
  }

  initHighcharts = () => {
    if (!this.domNode) {
      return;
    }

    const { chartCreationFunc, callback, polar, gauge, children, ...rest } = this.props;

    const opts = {
      chart: {},
      title: {
        text: null
      },
      subtitle: {
        text: null
      },
      legend: {
        enabled: false
      },
      rangeSelector: {
        enabled: false
      },
      navigator: {
        enabled: false
      },
      scrollbar: {
        enabled: false
      },
      tooltip: {
        enabled: false
      },
      credits: {
        enabled: false
      },
      series: [],
      xAxis: [],
      yAxis: [],
      ...rest
    };
    this.chart = chartCreationFunc(this.domNode, opts);

    this.chart.polar = polar;
    this.chart.angular = gauge;

    callback(this.chart);

    this.setState({
      rendered: true
    })
  }
  setDomNode = (node) => {
    this.domNode = node;
  }
  componentDidUpdate (prevProps) {
    const { plotOptions } = this.props
    if (isEqual(prevProps.plotOptions, plotOptions) === false && this.chart) {
      this.chart.update({ plotOptions }, true)
    }
  }

  componentWillUnmount () {
    if (this.chart) { // Fixes #14
      window.setTimeout(this.chart.destroy.bind(this.chart), 1);
      this.chart.__destroyed = true;
    }
  }

  render () {
    const { chartType, children } = this.props;

    return (
      <div
        className={`chart ${this.props.className}`}
        ref={ this.setDomNode }>
        {this.state.rendered && (
          <Provider value={{ chart: this.chart, chartType }}>
            {children}
          </Provider>
        )}
      </div>
    );
  }
}

export default BaseChart;
<|endoftext|>


<commit_before>/*---------------------------------------------------------
 * OpenERP base library
 *---------------------------------------------------------*/

openerp.base_diagram = function (openerp) {
QWeb.add_template('/base_diagram/static/src/xml/base_diagram.xml');
openerp.base.views.add('diagram', 'openerp.base_diagram.DiagramView');
openerp.base_diagram.DiagramView = openerp.base.View.extend({
	init: function(parent, element_id, dataset, view_id, options) {
		this._super(parent, element_id);
		this.set_default_options(options);
        this.view_manager = parent;
        this.dataset = dataset;
        this.model = this.dataset.model;
        this.view_id = view_id;
        this.name = "";
		this.domain = this.dataset._domain ? this.dataset._domain: [];
		this.context = {};
		this.ids = this.dataset.ids;
	},
	start: function() {
		return this.rpc("/base_diagram/diagram/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
	},

	toTitleCase: function(str) {
		return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
	},

	on_loaded: function(result) {

		var self = this;
		if(this.ids && this.ids.length) {
			this.id = this.ids[self.dataset.index || 0];
		}
		this.fields_view = result.fields_view;

		this.view_id = this.fields_view.view_id;
		this.name = this.fields_view.name;

		this.fields = this.fields_view.fields;
		var children = this.fields_view.arch.children;

		/*
		 * For Nodes (Fields)
		 */
		this.node = '';
		this.bgcolor = '';
		this.shape = '';
		this.visible_fields_nodes = [];
		this.invisible_fields_nodes = [];
		this.fields_nodes_string = [];

		/*
		 * For Arraows(Connector)
		 */
		this.connector = '';
		this.src_node = '';
		this.des_node = '';
		this.connector_fields = [];
		this.fields_connector_string = [];

		for(ch in children) {
			if(children[ch]['tag'] == 'node') {
				this.node = children[ch]['attrs']['object'];
				this.bgcolor = children[ch]['attrs']['bgcolor'] || '';
				this.shape = children[ch]['attrs']['shape'] || '';
				for(node_chld in children[ch]['children']) {
					if (children[ch]['children'][node_chld]['tag'] = 'field') {
						var ch_name = children[ch]['children'][node_chld]['attrs']['name'];

						if (children[ch]['children'][node_chld]['attrs']['invisible']) {
							if (children[ch]['children'][node_chld]['attrs']['invisible'] == 1 && children[ch]['children'][node_chld]['attrs']['invisible'] == '1') {
								this.invisible_fields_nodes.push(ch_name)
							}
						}
						else {
							this.visible_fields_nodes.push(ch_name);
							var ch_node_string = this.fields[ch_name]['string'] || this.toTitleCase(ch_name);
							this.fields_nodes_string.push(ch_node_string)
						}
					}
				}
			} else if(children[ch]['tag'] == 'arrow') {
				this.connector = children[ch]['attrs']['object'];
				this.src_node = children[ch]['attrs']['source'];
				this.des_node = children[ch]['attrs']['destination'];
				for (arrow_chld in children[ch]['children']) {
					if (children[ch]['children'][arrow_chld]['tag'] = 'field') {
						var arr_ch_name = children[ch]['children'][arrow_chld]['attrs']['name'];
						var ch_node_string = this.fields[arr_ch_name]['string'] || this.toTitleCase(arr_ch_name);
						this.fields_connector_string.push(ch_node_string);
						this.connector_fields.push(arr_ch_name);
					}
				}
			}
		}

		this.$element.html(QWeb.render("DiagramView", this));

		this.$element.find('div.oe_diagram_pager button[data-pager-action]').click(function() {
            var action = $(this).data('pager-action');
            self.on_pager_action(action);
        });

		this.do_update_pager();

		this.$element.find('.oe_diagram_button_new').click(function(){self.add_edit_node()})

        if(this.id) {
        	self.get_diagram_info();
        }
	},

	get_diagram_info: function() {
		var self = this;
        this.rpc(
            '/base_diagram/diagram/get_diagram_info',
            {
                'id': this.id,
                'model': this.model,
                'bgcolor': this.bgcolor,
                'shape': this.shape,
                'node': this.node,
                'connector': this.connector,
                'src_node': this.src_node,
                'des_node': this.des_node,
                'visible_node_fields': this.visible_fields_nodes,
                'invisible_node_fields': this.invisible_fields_nodes,
                'node_fields_string': this.fields_nodes_string,
                'connector_fields': this.connector_fields,
                'connector_fields_string': this.fields_connector_string
            },
            function(result) {
            	self.draw_diagram(result);
            }
        );
	},

	on_diagram_loaded: function(record) {
    	var self = this;
    	var id_record = record['id']
    	if(id_record) {
        	self.get_diagram_info();
        }
    },

    draw_diagram: function(result) {
        var dia = new Graph();

        this.active_model = result['id_model'];
        this.in_transition_field = result['in_transition_field'];
        this.out_transition_field = result['out_transition_field'];
        var res_nodes = result['nodes'];
        var res_connectors = result['conn'];

        //Custom logic
        var self = this;
        var renderer= function(r, n) {
	        var node;
	        var set;

	        // ellipse
	        if (n.node.shape == 'ellipse') {
	            var node = r.ellipse(n.node.x - 30, n.node.y - 13, 40, 20).attr({
	                    "fill": n.node.color,
	                    r: "12px",
	                    "stroke-width": n.distance == 0 ? "3px" : "1px"
	                });

	            set = r.set().push(node).push(r.text(n.node.x - 30, n.node.y - 10, (n.label || n.id)));
	        }

	        // rectangle
			else if(n.node.shape == 'rectangle') {
				var node = r.rect(n.node.x-30, n.node.y-13, 60, 44).attr({
	             	"fill": n.node.color,
	                 r : "12px",
	                "stroke-width" : n.distance == 0 ? "3px" : "1px"
	                });
	        	set = r.set().push(node).push(r.text(n.node.x , n.node.y+5 , (n.label || n.id)));
			}

	        // circle
			else {
	            var node = r.circle(n.node.x, n.node.y, 150).attr({
	                        "fill": n.node.color,
	                        r : "30px",
	                        "stroke-width" : n.distance == 0 ? "3px" : "1px"
	                });
	           	set = r.set().push(node).push(r.text(n.node.x , n.node.y , (n.label || n.id)));
			}

	        //Shape Node Event
	        jQuery(node.node).attr({
	            'id': n.node.id,
	            'name': n.id,
	            'kind': n.node.options['Kind'] || n.node.options['kind']
	        }).dblclick(function() {
	            var $this = jQuery(this);
	            self.search_activity($this.attr('id'), $this.attr('name'), $this.attr('kind'))
	        });

	        //Text Node Event
	        jQuery(node.next.node).attr({
	            'id': n.node.id,
	            'name': n.id,
	            'kind': n.node.options['Kind'] || n.node.options['kind']
	        }).dblclick(function() {
	            var $this = jQuery(this);
	            self.search_activity($this.attr('id'), $this.attr('name'), $this.attr('kind'))
	        });
	        return set;
        }

        for(node in res_nodes) {
            var res_node = res_nodes[node];
            dia.addNode(res_node['name'],{node: res_node,render: renderer});
        }

        for(cr in res_connectors) {
        	var res_connector = res_connectors[cr];
        	dia.addEdge(res_connector['source'], res_connector['destination'], {directed : true});
        }

        var layouter = new Graph.Layout.Spring(dia);
        layouter.layout();
        if ($('div#dia-canvas').children().length > 0) {
        	$('div#dia-canvas').children().remove();
        }
        var renderer = new Graph.Renderer.Raphael('dia-canvas', dia, $('div#dia-canvas').width(), $('div#dia-canvas').height());
        renderer.draw();

        //Path(Edges)
        jQuery('path',renderer.r.canvas).each(function(index, path) {

        	$(this).attr({
        		'd_id': res_connectors[index+1].d_id,
        		'id': res_connectors[index+1].id,
        		's_id': res_connectors[index+1].s_id,
    		})
        });
        jQuery('path',renderer.r.canvas).dblclick(function(){
        });
    },

    search_activity: function(id, name, kind) {
        var self = this;
        this.rpc(
        '/base_diagram/diagram/get_activity',
        {
            'id': id,
            'name': name,
            'kind': kind,
            'active_model': this.active_model,
            'model': this.node
        },
        function(result) {
            self.add_edit_node(result)
        }
        )
    },

    add_edit_node: function(result) {
    	var self = this;
    	var id;
    	if(result)
			id = result.activity_id[0];
    	var action_manager = new openerp.base.ActionManager(this);
    	var dialog = new openerp.base.Dialog(this, {
            title : 'Activity',
            width: 800,
            height: 600,
            buttons : {
                Cancel : function() {
                    $(this).dialog('destroy');
                },
                Save : function() {
                	var form_dataset = action_manager.inner_viewmanager.dataset;
                	var form_view = action_manager.inner_viewmanager.views.form.controller;

                	form_view.do_save(function() {
                		self.dataset.index = jQuery.inArray(parseInt(self.id,10), self.dataset.ids)
                		self.dataset.read_index(_.keys(self.fields_view.fields), self.on_diagram_loaded)
                	});
                    $(this).dialog('destroy');
                }
            }
        }).start().open();
    	action_manager.appendTo(dialog.$element);
    	action_manager.do_action({
            res_model : this.node,
            res_id: id,
            views : [[false, 'form']],
            type : 'ir.actions.act_window',
            auto_search : false,
            flags : {
    			search_view: false,
                sidebar : false,
                views_switcher : false,
                action_buttons : false
            }
        });
    },

    do_search: function(domains, contexts, groupbys) {
        var self = this;
        this.rpc('/base/session/eval_domain_and_context', {
            domains: domains,
            contexts: contexts,
            group_by_seq: groupbys
        }, function (results) {
            // TODO: handle non-empty results.group_by with read_group
            self.dataset.context = self.context = results.context;
            self.dataset.domain = self.domain = results.domain;
            self.dataset.read_slice(self.fields, 0, self.limit,function(events){
                self.schedule_events(events)
            });
        });
    },

    on_pager_action: function(action) {
    	switch (action) {
	        case 'first':
	            this.dataset.index = 0;
	            break;
	        case 'previous':
	            this.dataset.previous();
	            break;
	        case 'next':
	            this.dataset.next();
	            break;
	        case 'last':
	            this.dataset.index = this.dataset.ids.length - 1;
	            break;
    	}
	    this.dataset.read_index(_.keys(this.fields_view.fields), this.on_diagram_loaded);
	    this.do_update_pager();
    },

    do_update_pager: function(hide_index) {
        var $pager = this.$element.find('div.oe_diagram_pager');
        var index = hide_index ? '-' : this.dataset.index + 1;
        if(!this.dataset.count)
        	this.dataset.count = this.dataset.ids.length
        $pager.find('span.oe_pager_index').html(index);
        $pager.find('span.oe_pager_count').html(this.dataset.count);
    },

	do_show: function () {
        this.$element.show();
    },

    do_hide: function () {
        this.$element.hide();
    }
});
};

// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
<commit_msg>[FIX] Add or Edit activity,transition.<commit_after>/*---------------------------------------------------------
 * OpenERP base library
 *---------------------------------------------------------*/

openerp.base_diagram = function (openerp) {
QWeb.add_template('/base_diagram/static/src/xml/base_diagram.xml');
openerp.base.views.add('diagram', 'openerp.base_diagram.DiagramView');
openerp.base_diagram.DiagramView = openerp.base.View.extend({
	init: function(parent, element_id, dataset, view_id, options) {
		this._super(parent, element_id);
		this.set_default_options(options);
        this.view_manager = parent;
        this.dataset = dataset;
        this.model = this.dataset.model;
        this.view_id = view_id;
        this.name = "";
		this.domain = this.dataset._domain ? this.dataset._domain: [];
		this.context = {};
		this.ids = this.dataset.ids;
	},
	start: function() {
		return this.rpc("/base_diagram/diagram/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
	},

	toTitleCase: function(str) {
		return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
	},

	on_loaded: function(result) {

		var self = this;
		if(this.ids && this.ids.length) {
			this.id = this.ids[self.dataset.index || 0];
		}
		this.fields_view = result.fields_view;

		this.view_id = this.fields_view.view_id;
		this.name = this.fields_view.name;

		this.fields = this.fields_view.fields;
		var children = this.fields_view.arch.children;

		/*
		 * For Nodes (Fields)
		 */
		this.node = '';
		this.bgcolor = '';
		this.shape = '';
		this.visible_fields_nodes = [];
		this.invisible_fields_nodes = [];
		this.fields_nodes_string = [];

		/*
		 * For Arraows(Connector)
		 */
		this.connector = '';
		this.src_node = '';
		this.des_node = '';
		this.connector_fields = [];
		this.fields_connector_string = [];

		for(ch in children) {
			if(children[ch]['tag'] == 'node') {
				this.node = children[ch]['attrs']['object'];
				this.bgcolor = children[ch]['attrs']['bgcolor'] || '';
				this.shape = children[ch]['attrs']['shape'] || '';
				for(node_chld in children[ch]['children']) {
					if (children[ch]['children'][node_chld]['tag'] = 'field') {
						var ch_name = children[ch]['children'][node_chld]['attrs']['name'];

						if (children[ch]['children'][node_chld]['attrs']['invisible']) {
							if (children[ch]['children'][node_chld]['attrs']['invisible'] == 1 && children[ch]['children'][node_chld]['attrs']['invisible'] == '1') {
								this.invisible_fields_nodes.push(ch_name)
							}
						}
						else {
							this.visible_fields_nodes.push(ch_name);
							var ch_node_string = this.fields[ch_name]['string'] || this.toTitleCase(ch_name);
							this.fields_nodes_string.push(ch_node_string)
						}
					}
				}
			} else if(children[ch]['tag'] == 'arrow') {
				this.connector = children[ch]['attrs']['object'];
				this.src_node = children[ch]['attrs']['source'];
				this.des_node = children[ch]['attrs']['destination'];
				for (arrow_chld in children[ch]['children']) {
					if (children[ch]['children'][arrow_chld]['tag'] = 'field') {
						var arr_ch_name = children[ch]['children'][arrow_chld]['attrs']['name'];
						var ch_node_string = this.fields[arr_ch_name]['string'] || this.toTitleCase(arr_ch_name);
						this.fields_connector_string.push(ch_node_string);
						this.connector_fields.push(arr_ch_name);
					}
				}
			}
		}

		this.$element.html(QWeb.render("DiagramView", this));

		this.$element.find('div.oe_diagram_pager button[data-pager-action]').click(function() {
            var action = $(this).data('pager-action');
            self.on_pager_action(action);
        });

		this.do_update_pager();

		this.$element.find('.oe_diagram_button_new').click(function(){self.add_edit_node()})

        if(this.id) {
        	self.get_diagram_info();
        }
	},

	get_diagram_info: function() {
		var self = this;
        this.rpc(
            '/base_diagram/diagram/get_diagram_info',
            {
                'id': this.id,
                'model': this.model,
                'bgcolor': this.bgcolor,
                'shape': this.shape,
                'node': this.node,
                'connector': this.connector,
                'src_node': this.src_node,
                'des_node': this.des_node,
                'visible_node_fields': this.visible_fields_nodes,
                'invisible_node_fields': this.invisible_fields_nodes,
                'node_fields_string': this.fields_nodes_string,
                'connector_fields': this.connector_fields,
                'connector_fields_string': this.fields_connector_string
            },
            function(result) {
            	self.draw_diagram(result);
            }
        );
	},

	on_diagram_loaded: function(record) {
    	var self = this;
    	var id_record = record['id']
    	if(id_record) {
        	self.get_diagram_info();
        }
    },

    draw_diagram: function(result) {
        var dia = new Graph();

        this.active_model = result['id_model'];
        this.in_transition_field = result['in_transition_field'];
        this.out_transition_field = result['out_transition_field'];
        var res_nodes = result['nodes'];
        var res_connectors = result['conn'];

        //Custom logic
        var self = this;
        var renderer= function(r, n) {
	        var node;
	        var set;

	        // ellipse
	        if (n.node.shape == 'ellipse') {
	            var node = r.ellipse(n.node.x - 30, n.node.y - 13, 40, 20).attr({
	                    "fill": n.node.color,
	                    r: "12px",
	                    "stroke-width": n.distance == 0 ? "3px" : "1px"
	                });

	            set = r.set().push(node).push(r.text(n.node.x - 30, n.node.y - 10, (n.label || n.id)));
	        }

	        // rectangle
			else if(n.node.shape == 'rectangle') {
				var node = r.rect(n.node.x-30, n.node.y-13, 60, 44).attr({
	             	"fill": n.node.color,
	                 r : "12px",
	                "stroke-width" : n.distance == 0 ? "3px" : "1px"
	                });
	        	set = r.set().push(node).push(r.text(n.node.x , n.node.y+5 , (n.label || n.id)));
			}

	        // circle
			else {
	            var node = r.circle(n.node.x, n.node.y, 150).attr({
	                        "fill": n.node.color,
	                        r : "30px",
	                        "stroke-width" : n.distance == 0 ? "3px" : "1px"
	                });
	           	set = r.set().push(node).push(r.text(n.node.x , n.node.y , (n.label || n.id)));
			}

	        //Shape Node Event
	        jQuery(node.node).attr({
	            'id': n.node.id,
	            'name': n.id,
	            'kind': n.node.options['Kind'] || n.node.options['kind']
	        }).dblclick(function() {
	            var $this = jQuery(this);
	            self.add_edit_node($this.attr('id'), self.node);
//	            self.search_activity($this.attr('id'), $this.attr('name'), $this.attr('kind'))
	        });

	        //Text Node Event
	        jQuery(node.next.node).attr({
	            'id': n.node.id,
	            'name': n.id,
	            'kind': n.node.options['Kind'] || n.node.options['kind']
	        }).dblclick(function() {
	            var $this = jQuery(this);
	            self.add_edit_node($this.attr('id'), self.node);
//	            self.search_activity($this.attr('id'), $this.attr('name'), $this.attr('kind'))
	        });
	        return set;
        }

        for(node in res_nodes) {
            var res_node = res_nodes[node];
            dia.addNode(res_node['name'],{node: res_node,render: renderer});
        }

        for(cr in res_connectors) {
        	var res_connector = res_connectors[cr];
        	dia.addEdge(res_connector['source'], res_connector['destination'], {directed : true});
        }

        var layouter = new Graph.Layout.Spring(dia);
        layouter.layout();
        if ($('div#dia-canvas').children().length > 0) {
        	$('div#dia-canvas').children().remove();
        }
        var renderer = new Graph.Renderer.Raphael('dia-canvas', dia, $('div#dia-canvas').width(), $('div#dia-canvas').height());
        renderer.draw();

        //Path(Edges)
        jQuery('path',renderer.r.canvas).each(function(index, path) {

        	$(this).attr({
        		'd_id': res_connectors[index+1].d_id,
        		'id': res_connectors[index+1].id,
        		's_id': res_connectors[index+1].s_id,
    		})
        });
        jQuery('path',renderer.r.canvas).dblclick(function() {
        	self.add_edit_node(this.id, self.connector)
        });
    },

    add_edit_node: function(id, model) {
    	var self = this;

    	if(!model)
    		model = self.node;
    	if(id)
    		id = parseInt(id, 10);
    	var action_manager = new openerp.base.ActionManager(this);
    	var dialog = new openerp.base.Dialog(this, {
            width: 800,
            height: 600,
            buttons : {
                Cancel : function() {
                    $(this).dialog('destroy');
                },
                Save : function() {
                	var form_dataset = action_manager.inner_viewmanager.dataset;
                	var form_view = action_manager.inner_viewmanager.views.form.controller;

                	form_view.do_save(function() {
                		self.dataset.index = jQuery.inArray(parseInt(self.id,10), self.dataset.ids)
                		self.dataset.read_index(_.keys(self.fields_view.fields), self.on_diagram_loaded)
                	});
                    $(this).dialog('destroy');
                }
            }
        }).start().open();
    	action_manager.appendTo(dialog.$element);
    	action_manager.do_action({
            res_model : model,
            res_id: id,
            views : [[false, 'form']],
            type : 'ir.actions.act_window',
            auto_search : false,
            flags : {
    			search_view: false,
                sidebar : false,
                views_switcher : false,
                action_buttons : false
            }
        });
    },

    do_search: function(domains, contexts, groupbys) {
        var self = this;
        this.rpc('/base/session/eval_domain_and_context', {
            domains: domains,
            contexts: contexts,
            group_by_seq: groupbys
        }, function (results) {
            // TODO: handle non-empty results.group_by with read_group
            self.dataset.context = self.context = results.context;
            self.dataset.domain = self.domain = results.domain;
            self.dataset.read_slice(self.fields, 0, self.limit,function(events){
                self.schedule_events(events)
            });
        });
    },

    on_pager_action: function(action) {
    	switch (action) {
	        case 'first':
	            this.dataset.index = 0;
	            break;
	        case 'previous':
	            this.dataset.previous();
	            break;
	        case 'next':
	            this.dataset.next();
	            break;
	        case 'last':
	            this.dataset.index = this.dataset.ids.length - 1;
	            break;
    	}
	    this.dataset.read_index(_.keys(this.fields_view.fields), this.on_diagram_loaded);
	    this.do_update_pager();
    },

    do_update_pager: function(hide_index) {
        var $pager = this.$element.find('div.oe_diagram_pager');
        var index = hide_index ? '-' : this.dataset.index + 1;
        if(!this.dataset.count)
        	this.dataset.count = this.dataset.ids.length
        $pager.find('span.oe_pager_index').html(index);
        $pager.find('span.oe_pager_count').html(this.dataset.count);
    },

	do_show: function () {
        this.$element.show();
    },

    do_hide: function () {
        this.$element.hide();
    }
});
};

// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
<|endoftext|>


<commit_before>var toAdd = 23
  , val1 = 40
  , val2 = -40
  , result = val1 + val2
  , winter = summer(val2)
function summer (sumVal) {
    return function (toAdd) {
        if (!toAdd) throw new Error('trying to pull a fast one?')
        return sumVal + toAdd
    }
}
module.exports = {
    summer: summer,
    val1: val1,
    val2: val2,
    result: result,
    winter: winter
}<commit_msg>changing the comparison values to test codeship CI<commit_after>var toAdd = 23
  , val1 = 400
  , val2 = -400
  , result = val1 + val2
  , winter = summer(val2)
function summer (sumVal) {
    return function (toAdd) {
        if (!toAdd) throw new Error('trying to pull a fast one?')
        return sumVal + toAdd
    }
}
module.exports = {
    summer: summer,
    val1: val1,
    val2: val2,
    result: result,
    winter: winter
}<|endoftext|>


<commit_before>'use strict';

var React = require('react');

module.exports = React.createClass({
  displayName: 'VisibilitySensor',

  propTypes: {
    onChange: React.PropTypes.func.isRequired,
    active: React.PropTypes.bool,
    delay: React.PropTypes.number,
    containment: React.PropTypes.instanceOf(Element),
    className: React.PropTypes.string,
    style: React.PropTypes.object
  },

  getDefaultProps: function () {
    return {
      active: true,
      delay: 1000,
      containment: null
    };
  },

  getInitialState: function () {
    return {
      isVisible: true,
      visibilityRect: {}
    };
  },

  componentDidMount: function () {
    if (this.props.active) {
      this.startWatching();
    }
  },

  componentWillUnmount: function () {
    this.stopWatching();
  },

  componentWillReceiveProps: function (nextProps) {
    if (nextProps.active) {
      this.startWatching();
    } else {
      this.stopWatching();
    }
  },

  startWatching: function () {
    if (this.interval) { return; }
    this.interval = setInterval(this.check, this.props.delay);
  },

  stopWatching: function () {
    this.interval = clearInterval(this.interval);
  },

  /**
   * Check if the element is within the visible viewport
   */
  check: function () {
    var el = this.getDOMNode();
    var rect = el.getBoundingClientRect();
    var containmentRect;

    if (this.props.containment) {
      containmentRect = this.props.containment.getBoundingClientRect();
    } else {
      containmentRect = {
        top: 0,
        left: 0,
        bottom: window.innerHeight || document.documentElement.clientHeight,
        right: window.innerWidth || document.documentElement.clientWidth
      };
    }

    var visibilityRect = {
      top: rect.top >= containmentRect.top,
      left: rect.left >= containmentRect.left,
      bottom: rect.bottom <= containmentRect.bottom,
      right: rect.right <= containmentRect.right
    };

    var isVisible = (
      visibilityRect.top &&
      visibilityRect.left &&
      visibilityRect.bottom &&
      visibilityRect.right
    );

    // notify the parent when the value changes
    if (this.state.isVisible !== isVisible) {
      this.setState({
        isVisible: isVisible,
        visibilityRect: visibilityRect
      });
      this.props.onChange(isVisible, visibilityRect);
    }

    return this.state;
  },

  render: function () {
    return React.createElement('div', {
      className: this.props.className,
      style: this.props.style
    }, [this.props.children]);
  }
});
<commit_msg>initial value of isVisible should be null<commit_after>'use strict';

var React = require('react');

module.exports = React.createClass({
  displayName: 'VisibilitySensor',

  propTypes: {
    onChange: React.PropTypes.func.isRequired,
    active: React.PropTypes.bool,
    delay: React.PropTypes.number,
    containment: React.PropTypes.instanceOf(Element),
    className: React.PropTypes.string,
    style: React.PropTypes.object
  },

  getDefaultProps: function () {
    return {
      active: true,
      delay: 1000,
      containment: null
    };
  },

  getInitialState: function () {
    return {
      isVisible: null,
      visibilityRect: {}
    };
  },

  componentDidMount: function () {
    if (this.props.active) {
      this.startWatching();
    }
  },

  componentWillUnmount: function () {
    this.stopWatching();
  },

  componentWillReceiveProps: function (nextProps) {
    if (nextProps.active) {
      this.setState(this.getInitialState());
      this.startWatching();
    } else {
      this.stopWatching();
    }
  },

  startWatching: function () {
    if (this.interval) { return; }
    this.interval = setInterval(this.check, this.props.delay);
  },

  stopWatching: function () {
    this.interval = clearInterval(this.interval);
  },

  /**
   * Check if the element is within the visible viewport
   */
  check: function () {
    var el = this.getDOMNode();
    var rect = el.getBoundingClientRect();
    var containmentRect;

    if (this.props.containment) {
      containmentRect = this.props.containment.getBoundingClientRect();
    } else {
      containmentRect = {
        top: 0,
        left: 0,
        bottom: window.innerHeight || document.documentElement.clientHeight,
        right: window.innerWidth || document.documentElement.clientWidth
      };
    }

    var visibilityRect = {
      top: rect.top >= containmentRect.top,
      left: rect.left >= containmentRect.left,
      bottom: rect.bottom <= containmentRect.bottom,
      right: rect.right <= containmentRect.right
    };

    var isVisible = (
      visibilityRect.top &&
      visibilityRect.left &&
      visibilityRect.bottom &&
      visibilityRect.right
    );

    // notify the parent when the value changes
    if (this.state.isVisible !== isVisible) {
      this.setState({
        isVisible: isVisible,
        visibilityRect: visibilityRect
      });
      this.props.onChange(isVisible, visibilityRect);
    }

    return this.state;
  },

  render: function () {
    return React.createElement('div', {
      className: this.props.className,
      style: this.props.style
    }, [this.props.children]);
  }
});
<|endoftext|>


<commit_before>const exec    = require('child_process').exec;
const fs      = require('fs');
const path    = require('path');
const respawn = require('respawn');
const io      = require('socket.io-client');
const events  = require('events');

var defaults =
{
  port: 8099,
  wspath: "/geovideo"
};

var geomux = function geomux( name, deps )
{
  console.log('The geo-mux plugin.');
  var self      = this;

  this.deps     = deps;
  this.services = {};

  var emitter     = new events.EventEmitter();
  var global      = deps.globalEventLoop;
  var cockpit     = deps.cockpit;
  var videoServer = io.connect( 'http://localhost:' + defaults.port, { path: defaults.wspath, reconnection: true, reconnectionAttempts: Infinity, reconnectionDelay: 10 } );

  var cameras     = {};

  // Upon connecting to video server, set up listeners
  videoServer.on( "connect", function()
  {
    console.log( "Successfully connected to geo-video-server" );

    // ----------------------------
    // Register all other listeners

    cockpit.on( "plugin.geomuxp.command", function( camera, command, params )
    {
      // Forward to geo-video-server
      videoServer.emit( "geomux.command", camera, command, params );
    } );

    // Video endpoint announcement
    videoServer.on( "geomux.video.announcement", function( camera, channel, info )
    {
      console.log( "Announcement info: " + JSON.stringify( info ) );

      // Emit message on global event loop to register with the Video plugin
      self.deps.globalEventLoop.emit('CameraRegistration',
      {
        location:           info.txtRecord.cameraLocation,
        videoMimeType:      info.txtRecord.videoMimeType,
        resolution:         info.txtRecord.resolution,
        framerate:          info.txtRecord.framerate,
        wspath:             info.txtRecord.wspath,
        relativeServiceUrl: info.txtRecord.relativeServiceUrl,
        sourcePort:         info.port,
        sourceAddress:      info.addresses[0],
        connectionType:     'socket.io'
      });
    });

    // Channel settings
    videoServer.on( "geomux.channel.settings", function( camera, channel, settings )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".settings", settings );
    } );

    // Channel health
    videoServer.on( "geomux.channel.health", function( camera, channel, health )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".health", health );
    });

    // Channel api
    videoServer.on( "geomux.channel.api", function( camera, channel, api )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".api", api );
    });

    // Channel status
    videoServer.on( "geomux.channel.status", function( camera, channel, status )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".status", status );
    });

    // Channel error
    videoServer.on( "geomux.channel.error", function( camera, channel, error )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".error", error );
    });

    // Tell geo-video-server to start the daemons
    videoServer.emit( "geomux.ready" );
  });

  videoServer.on( "disconnect", function()
  {
    console.log( "Disconnected from video server." );
  });

  videoServer.on( "error", function( err )
  {
    console.log( "Video Server Connection Error: " + err );
  });

  // Connect to video server
  videoServer.on( "reconnect", function()
  {
    console.log( "Attempting to reconnect" );
  });

  function UpdateCameraInfo( camera, channel )
  {
    if( cameras[ camera ] === undefined )
    {
      // Create the camera
      cameras[ camera ] = {};

      // Add the channel
      cameras[ camera ][ channel ] = {};

      self.deps.cockpit.emit( "plugin.geomuxp.cameraInfo", cameras );
    }
    else if( cameras[ camera ][ channel ] === undefined )
    {
      // Add the channel
      cameras[ camera ][ channel ] = {};

      self.deps.cockpit.emit( "plugin.geomuxp.cameraInfo", cameras );
    }

    // No changes, no need to emit update
  }
}

var timeoutscale = .1;

// This gets called when plugins are started
geomux.prototype.start = function start()
{
  console.log('geo:start');

  var self=this;

  if (process.env.GEO_MOCK == 'true')
  {
    StartCameras( [ "0" ] );
  }
  else
  {
    BootCameras(function()
    {
      EnumerateCameras(function(results)
      {
        if (results.length==0)
        {
          setTimeout(self.start.bind(self),1000*120*timeoutscale);

          if (timeoutscale<1)
          {
            timeoutscale+=.1;
          }

          return;
        }

        self.deps.globalEventLoop.emit('video-deviceRegistration',results);

        sortedResults = results.sort( function(a,b){ return a.device.localeCompare(b.device) } );
        StartCameras( sortedResults );
      })
    });
  }
}

// -----------------------
// Helper functions

// Creates a list with all of the dectected video devices
function EnumerateCameras( callback )
{
  var results = [];
  var i = 0;

  fs.readdir('/dev', function (err, files)
  {
    if(err)
    {
      callback( results );
    }

    var f = files.filter( function(file)
    {
        return file.indexOf('video') == 0;
    });

    if (f.length==0)
    {
      callback(results);
      return;
    }

    f.forEach(function(file)
    {
      i++;
      exec('udevadm info --query=all --name=/dev/' + file + ' | grep "S: v4l/by-id/"', function(error, stdout, stderr)
      {
        if ((error == null) && (stdout.indexOf('GEO_Semi_Condor')>0))
        {
          var result =
          {
            // NOTE: Add another field for camera offset and change device back to "video0"?
            device:   file.slice( "video".length ),
            deviceid: stdout.slice("S: v4l/by-id/".length),
            format:   'MP4'
          }

          results.push( result );
        }

        i--;

        if( i == 0 )
        {
          callback(results)
        };
      });
    });
  });
}

function BootCameras( callback )
{
    exec('mxcam list | grep "Core: Condor"', function(error, stdout, stderr)
    {
      if (error == null)
      {
        exec(path.dirname(require.resolve('geo-video-server'))+'/platform/linux/bootcamera.sh', function(error, stdout, stderr)
        {
          // give the system a moment to stabalize after the bootcamera script
          setTimeout(function()
          {
            callback();
          },1000);
        } );
      }
      else
      {
        console.error('Error starting devices geo: ',JSON.stringify(error));
        callback();
      }
    });
}

function StartCameras( cameras )
{
  var geoprogram = '';
  var cameraArgs = [ "--c" ];

  if (process.env.GEO_MOCK == 'true')
  {
    geoprogram = require.resolve('geo-video-simulator');
    cameraArgs.push( "0" );
  }
  else
  {
    // Find the geo-video-server app
    try
    {
      geoprogram =require.resolve('geo-video-server');

      // Create list of cameras to start up
      for( var i = 0; i < cameras.length; i++ )
      {
          cameraArgs.push( cameras[ i ].device );
      }
    }
    catch (er)
    {
      console.log("geo-video-server not installed")
      return;
    }
  }

  // Create all launch options
  var launch_options =
  [
    "nice", "-1",
    "node", geoprogram,
    "--p", defaults.port,
    "--w", defaults.wspath,
    "--u", ( process.env.DEV_MODE === "true" ? ":8099" : "" )
  ].concat( cameraArgs );

  const infinite = -1;

  // Launch the video server with specified options. Attempt to restart every 1s.
  var monitor = respawn( launch_options,
  {
      name: 'geomux',
      env:
      {
        "DEBUG": "app*,camera*,channel*"
      },
      maxRestarts: infinite,
      sleep: 1000
  } );

  var self = this;

  monitor.on('crash',function()
  {
      console.log("crashed");
  });

  monitor.on('spawn',function(process)
  {
      console.log("spawned");
  });

  monitor.on('warn',function(error)
  {
      console.log("error: " + error);
  });

  monitor.on('exit',function(code, signal)
  {
      console.log("code: " + code + " signal: " + signal );
  });

  // Optional stdio logging
  monitor.on('stdout',function(data)
  {
      var msg = data.toString('utf-8');
      console.log(msg);
  });

  monitor.on('stderr',function(data)
  {
      var msg = data.toString('utf-8');
      console.log(msg);
  });

  console.log( "Starting geovideoserver" );
  monitor.start();
};

//Export provides the public interface
module.exports = function (name, deps)
{
  return new geomux(name,deps);
};
<commit_msg>Removing camera boot responsibilities from geomuxp index.js<commit_after>const exec    = require('child_process').exec;
const fs      = require('fs');
const path    = require('path');
const respawn = require('respawn');
const io      = require('socket.io-client');
const events  = require('events');

var defaults =
{
  port: 8099,
  wspath: "/geovideo"
};

var geomux = function geomux( name, deps )
{
  console.log('The geo-mux plugin.');
  var self      = this;

  this.deps     = deps;
  this.services = {};

  var emitter     = new events.EventEmitter();
  var global      = deps.globalEventLoop;
  var cockpit     = deps.cockpit;
  var videoServer = io.connect( 'http://localhost:' + defaults.port, { path: defaults.wspath, reconnection: true, reconnectionAttempts: Infinity, reconnectionDelay: 10 } );

  var cameras     = {};

  // Upon connecting to video server, set up listeners
  videoServer.on( "connect", function()
  {
    console.log( "Successfully connected to geo-video-server" );

    // ----------------------------
    // Register all other listeners

    cockpit.on( "plugin.geomuxp.command", function( camera, command, params )
    {
      // Forward to geo-video-server
      videoServer.emit( "geomux.command", camera, command, params );
    } );

    // Video endpoint announcement
    videoServer.on( "geomux.video.announcement", function( camera, channel, info )
    {
      console.log( "Announcement info: " + JSON.stringify( info ) );

      // Emit message on global event loop to register with the Video plugin
      self.deps.globalEventLoop.emit('CameraRegistration',
      {
        location:           info.txtRecord.cameraLocation,
        videoMimeType:      info.txtRecord.videoMimeType,
        resolution:         info.txtRecord.resolution,
        framerate:          info.txtRecord.framerate,
        wspath:             info.txtRecord.wspath,
        relativeServiceUrl: info.txtRecord.relativeServiceUrl,
        sourcePort:         info.port,
        sourceAddress:      info.addresses[0],
        connectionType:     'socket.io'
      });
    });

    // Channel settings
    videoServer.on( "geomux.channel.settings", function( camera, channel, settings )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".settings", settings );
    } );

    // Channel health
    videoServer.on( "geomux.channel.health", function( camera, channel, health )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".health", health );
    });

    // Channel api
    videoServer.on( "geomux.channel.api", function( camera, channel, api )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".api", api );
    });

    // Channel status
    videoServer.on( "geomux.channel.status", function( camera, channel, status )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".status", status );
    });

    // Channel error
    videoServer.on( "geomux.channel.error", function( camera, channel, error )
    {
      UpdateCameraInfo( camera, channel );
      self.deps.cockpit.emit("plugin.geomuxp." + camera + "_" + channel + ".error", error );
    });

    // Tell geo-video-server to start the daemons
    videoServer.emit( "geomux.ready" );
  });

  videoServer.on( "disconnect", function()
  {
    console.log( "Disconnected from video server." );
  });

  videoServer.on( "error", function( err )
  {
    console.log( "Video Server Connection Error: " + err );
  });

  // Connect to video server
  videoServer.on( "reconnect", function()
  {
    console.log( "Attempting to reconnect" );
  });

  function UpdateCameraInfo( camera, channel )
  {
    if( cameras[ camera ] === undefined )
    {
      // Create the camera
      cameras[ camera ] = {};

      // Add the channel
      cameras[ camera ][ channel ] = {};

      self.deps.cockpit.emit( "plugin.geomuxp.cameraInfo", cameras );
    }
    else if( cameras[ camera ][ channel ] === undefined )
    {
      // Add the channel
      cameras[ camera ][ channel ] = {};

      self.deps.cockpit.emit( "plugin.geomuxp.cameraInfo", cameras );
    }

    // No changes, no need to emit update
  }
}

// This gets called when plugins are started
geomux.prototype.start = function start()
{
  console.log('geo:start');

  var geoprogram = '';

  if (process.env.GEO_MOCK == 'true')
  {
    geoprogram = require.resolve('geo-video-simulator');
  }
  else
  {
    // Find the geo-video-server app
    try
    {
      geoprogram = require.resolve( 'geo-video-server' );
    }
    catch (er)
    {
      console.error( "geo-video-server not installed" );
      return;
    }
  }

  // Create all launch options
  var launch_options =
  [
    "nice", "-1",
    "node", geoprogram,
    "--p", defaults.port,
    "--w", defaults.wspath,
    "--u", ( process.env.DEV_MODE === "true" ? ":8099" : "" )
  ];

  const infinite = -1;

  // Launch the video server with specified options. Attempt to restart every 1s.
  var monitor = respawn( launch_options,
  {
      name: 'geomux',
      env:
      {
        "DEBUG": "app*,camera*,channel*"
      },
      maxRestarts: infinite,
      sleep: 1000
  } );

  var self = this;

  monitor.on('exit',function(code, signal)
  {
      console.log("code: " + code + " signal: " + signal );
  });

  // Optional stdio logging
  monitor.on('stdout',function(data)
  {
      var msg = data.toString('utf-8');
      console.log(msg);
  });

  monitor.on('stderr',function(data)
  {
      var msg = data.toString('utf-8');
      console.log(msg);
  });

  monitor.start();
}

// BootCameras(function()
//     {
//       EnumerateCameras(function(results)
//       {
//         if (results.length==0)
//         {
//           setTimeout(self.start.bind(self),1000*120*timeoutscale);

//           if (timeoutscale<1)
//           {
//             timeoutscale+=.1;
//           }

//           return;
//         }

//         self.deps.globalEventLoop.emit('video-deviceRegistration',results);

//         sortedResults = results.sort( function(a,b){ return a.device.localeCompare(b.device) } );
//         StartCameras( sortedResults );
//       })
//     });

// -----------------------
// Helper functions

// // Creates a list with all of the dectected video devices
// function EnumerateCameras( callback )
// {
//   var results = [];
//   var i = 0;

//   fs.readdir('/dev', function (err, files)
//   {
//     if(err)
//     {
//       callback( results );
//     }

//     var f = files.filter( function(file)
//     {
//         return file.indexOf('video') == 0;
//     });

//     if (f.length==0)
//     {
//       callback(results);
//       return;
//     }

//     f.forEach(function(file)
//     {
//       i++;
//       exec('udevadm info --query=all --name=/dev/' + file + ' | grep "S: v4l/by-id/"', function(error, stdout, stderr)
//       {
//         if ((error == null) && (stdout.indexOf('GEO_Semi_Condor')>0))
//         {
//           var result =
//           {
//             // NOTE: Add another field for camera offset and change device back to "video0"?
//             device:   file.slice( "video".length ),
//             deviceid: stdout.slice("S: v4l/by-id/".length),
//             format:   'MP4'
//           }

//           results.push( result );
//         }

//         i--;

//         if( i == 0 )
//         {
//           callback(results)
//         };
//       });
//     });
//   });
// }

// function BootCameras( callback )
// {
//     exec('mxcam list | grep "Core: Condor"', function(error, stdout, stderr)
//     {
//       if (error == null)
//       {
//         exec(path.dirname(require.resolve('geo-video-server'))+'/platform/linux/bootcamera.sh', function(error, stdout, stderr)
//         {
//           // give the system a moment to stabalize after the bootcamera script
//           setTimeout(function()
//           {
//             callback();
//           },1000);
//         } );
//       }
//       else
//       {
//         console.error('Error starting devices geo: ',JSON.stringify(error));
//         callback();
//       }
//     });
// }

//Export provides the public interface
module.exports = function (name, deps)
{
  return new geomux(name,deps);
};
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2013-2014 CNRS

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.
*/

/* The API controller for Corpus
   Exports 3 methods:
   * post - Creates a new corpus
   * listAll - Returns a list of corpus
   * listWithId - Returns a specific corpus of a given id
*/

// for the uri : app.get('/corpus',
/*
	- First: retrieves all corpus regardless of user/group's rights
	- Second: finds all groups belonging to the connected user
	- For each found corpus, check ACLs (the permission of the connected user and its groups)
*/

var async = require('async');

//create a corpus
exports.create = function(req, res){
	var error=null;
	async.waterfall([
		function(callback) {
			if (req.body.name == undefined) error="the name is not define";
			if (req.body.name == "") 		error="empty string for name is not allow";
			callback(error);
		},
		function(callback) {
			var new_corpus = {};
			new_corpus.name = req.body.name;
			new_corpus.description = req.body.description;
			new_corpus.history = []
			new_corpus.history.push({date:new Date(), id_user:req.session.user._id, modification:{"name":new_corpus.name, "description":new_corpus.description}});
			new_corpus.users_ACL = {};
			new_corpus.groups_ACL = {};
			new_corpus.users_ACL[req.session.user._id]='O';
			var corpus = new Corpus(new_corpus).save(function (error, newCorpus) {
				if (newCorpus) res.status(200).json(newCorpus);
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
};

// only print username, role and description
printRes = function(corpus, res) {
	var p = {
		"name":corpus.name,
		"description":corpus.description,
		"history":corpus.history
	};
	res.status(200).json(p);
}

//check if a id_user exists
exports.exist = function(req, res, next) {
	Corpus.findById(req.params.id_corpus, function(error, corpus){
		if (error) res.status(400).json(error);
		else if (!corpus) res.status(400).json({"message":"id_corpus don't exists"});
		else next();
	});
}

// check if user have the good right for corpus
checkRight = function (corpus, user, groups, list_right) {
	var userInAcl = false;
	if (user.username == "root") return true
	else {
		if (corpus.users_ACL) {
			if (user._id in corpus.users_ACL) {
				if (list_right.indexOf(corpus.users_ACL[user._id])!=-1) return true;
				userInAcl = true;
			}
		}
		if (!userInAcl && corpus.groups_ACL) {
			for(var i = 0; i < groups.length; i++)	{
				if (groups[i]._id in corpus.groups_ACL) {
					if (list_right.indexOf(corpus.groups_ACL[groups[i]._id])!=-1) return true;
				}
			}
		}
	}
	return false;
}

// check if req.session.user._id have the good right to see this req.params.id_corpus
exports.AllowUser = function (list_right){
	return function(req, res, next) {
		async.waterfall([
			function(callback) {
				User.findById(req.session.user._id, function(error, user){
					callback(error, user);
				});
			},
			function(user, callback) {
				Group.find({'users_list' : {$regex : new RegExp('^'+ req.session.user._id + '$', "i")}}, function(error, groups) {
					callback(error, user, groups);
				});
			},
			function(user, groups, callback) {
				Corpus.findById(req.params.id_corpus, function(error, corpus){
					if (checkRight(corpus, user, groups, list_right)) next();
					else error = "Acces denied";
					callback(error);
	    		});
			},
		], function (error, trueOrFalse) {
			if (error) res.status(400).json({"message":error});
		});
	}
}

// retrieve all corpus
exports.getAll = function (req, res) {
	async.waterfall([
		function(callback) {
			User.findById(req.session.user._id, function(error, user){
				callback(error, user);
			});
		},
		function(user, callback) {
			Group.find({'users_list' : {$regex : new RegExp('^'+ req.session.user._id + '$', "i")}}, function(error, groups) {
				callback(error, user, groups);
			});
		},
		function(user, groups, callback) {
			Corpus.find({}, function(error, l_corpus){
    			async.filter(l_corpus,
    			        	 function(corpus, callback) {
    			          		callback (checkRight(corpus, user, groups, ['O', 'W', 'R']));
    			        	 },
    			        	 function(results) { res.status(200).json(results); }
    			);
    			callback(error);
    		});
		},
	], function (error, trueOrFalse) {
		if (error) res.status(400).json({"message":error});
	});
}

//retrieve a particular user (with id)
exports.getInfo = function(req, res){
	Corpus.findById(req.params.id_corpus, 'name description history', function(error, corpus){
		if (error) res.status(400).json({error:"error", message:error});
    	else res.status(200).json(corpus);
	});
}

//update information of a corpus
exports.update = function(req, res){
	var update = {};
	if (req.body.name) {
		if (req.body.name == "") res.status(400).json({"message":"name can't be empty"});
		else update.name = req.body.name;
	}
	if (req.body.description) update.description = req.body.description;
	Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
		if (error) res.status(400).json(error);
		else res.status(200).json(corpus);
	});
}

// remove a given corpus
exports.remove = function (req, res) {

	// check if corpus is empty

	Corpus.remove({_id : req.params.id_corpus}, function (error, corpus) {
		if (!error && corpus == 1) res.status(200).json({message:"The corpus as been delete"});
		else res.status(400).json({"message":error});
	});
}

//retrieve a particular user (with id)
exports.getACL = function(req, res){
	Corpus.findById(req.params.id_corpus, 'users_ACL groups_ACL', function(error, corpus){
		if (error) res.status(400).json({error:"error", message:error});
    	else res.status(200).json(corpus);
	});
}

// update ACL of a user
exports.updateUserACL = function(req, res){
	var update = {};
	var error=null;
	async.waterfall([
		function(callback) {
			if (req.body.Right != 'O' && req.body.Right != 'W' && req.body.Right != 'R') error="Right must be 'O' or 'W' or 'R'";
			callback(error);
		},
		function(callback) {
			Corpus.findById(req.params.id_corpus, function(error, corpus){
				if (!error){
					update.users_ACL = corpus.users_ACL;
					if (!update.users_ACL) update.users_ACL = {};
					update.users_ACL[req.params.id_user]=req.body.Right;
				}
				callback(error, update);
			});
		},
		function(update, callback) {
			Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
				if (!error) printRes(corpus, res);
				else res.status(400).json({"message":error});
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
}

// update ACL of a group
exports.updateGroupACL = function(req, res){
	var update = {};
	var error=null;
	async.waterfall([
		function(callback) {
			if (req.body.Right != 'O' && req.body.Right != 'W' && req.body.Right != 'R') error="Right must be 'O' or 'W' or 'R'";
			callback(error);
		},
		function(callback) {
			Corpus.findById(req.params.id_corpus, function(error, corpus){
				if (!error){
					update.groups_ACL = corpus.groups_ACL;
					if (!update.groups_ACL) update.groups_ACL = {};
					update.groups_ACL[req.params.id_group]=req.body.Right;
				}
				callback(error, update);
			});
		},
		function(update, callback) {
			Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
				if (!error) printRes(corpus, res);
				else res.status(400).json({"message":error});
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
}

// remove a user from ACL
exports.removeUserFromACL = function(req, res){
	var update = {};
	var error=null;
	async.waterfall([
		function(callback) {
			Corpus.findById(req.params.id_corpus, function(error, corpus){
				if (!error){
					update.users_ACL = corpus.users_ACL;
					if (!update.users_ACL) error=req.params.id_user+" not in users_ACL";
					else {
						if (update.users_ACL[req.params.id_user]) {
							delete update.users_ACL[req.params.id_user];
							if (Object.getOwnPropertyNames(update.users_ACL).length === 0) update.users_ACL = undefined;
						}
						else error=req.params.id_user+" not in users_ACL";
					}
				}
				callback(error, update);
			});
		},
		function(update, callback) {
			Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
				if (!error) printRes(corpus, res);
				else res.status(400).json({"message":error});
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
}

// remove a group from ACL
exports.removeGroupFromACL = function(req, res){
	var update = {};
	var error=null;
	async.waterfall([
		function(callback) {
			Corpus.findById(req.params.id_corpus, function(error, corpus){
				if (!error){
					update.groups_ACL = corpus.groups_ACL;
					if (!update.groups_ACL) error=req.params.id_group+" not in groups_ACL";
					else {
						if (update.groups_ACL[req.params.id_group]) {
							delete update.groups_ACL[req.params.id_group];
							if (Object.getOwnPropertyNames(update.groups_ACL).length === 0) update.groups_ACL = undefined;
						}
						else error=req.params.id_group+" not in groups_ACL";
					}
				}
				callback(error, update);
			});
		},
		function(update, callback) {
			Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
				if (!error) printRes(corpus, res);
				else res.status(400).json({"message":error});
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
}

<commit_msg>ajout addMedia<commit_after>/*
The MIT License (MIT)

Copyright (c) 2013-2014 CNRS

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.
*/

/* The API controller for Corpus
   Exports 3 methods:
   * post - Creates a new corpus
   * listAll - Returns a list of corpus
   * listWithId - Returns a specific corpus of a given id
*/

// for the uri : app.get('/corpus',
/*
	- First: retrieves all corpus regardless of user/group's rights
	- Second: finds all groups belonging to the connected user
	- For each found corpus, check ACLs (the permission of the connected user and its groups)
*/

var async = require('async');

//create a corpus
exports.create = function(req, res){
	var error=null;
	async.waterfall([
		function(callback) {
			if (req.body.name == undefined) error="the name is not define";
			if (req.body.name == "") 		error="empty string for name is not allow";
			callback(error);
		},
		function(callback) {
			var new_corpus = {};
			new_corpus.name = req.body.name;
			new_corpus.description = req.body.description;
			new_corpus.history = []
			new_corpus.history.push({date:new Date(), id_user:req.session.user._id, modification:{"name":new_corpus.name, "description":new_corpus.description}});
			new_corpus.users_ACL = {};
			new_corpus.groups_ACL = {};
			new_corpus.users_ACL[req.session.user._id]='O';
			var corpus = new Corpus(new_corpus).save(function (error, newCorpus) {
				if (newCorpus) res.status(200).json(newCorpus);
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
};

// only print username, role and description
printRes = function(corpus, res) {
	var p = {
		"name":corpus.name,
		"description":corpus.description,
		"history":corpus.history
	};
	res.status(200).json(p);
}

//check if a id_user exists
exports.exist = function(req, res, next) {
	Corpus.findById(req.params.id_corpus, function(error, corpus){
		if (error) res.status(400).json(error);
		else if (!corpus) res.status(400).json({"message":"id_corpus don't exists"});
		else next();
	});
}

// check if user have the good right for corpus
checkRight = function (corpus, user, groups, list_right) {
	var userInAcl = false;
	if (user.username == "root") return true
	else {
		if (corpus.users_ACL) {
			if (user._id in corpus.users_ACL) {
				if (list_right.indexOf(corpus.users_ACL[user._id])!=-1) return true;
				userInAcl = true;
			}
		}
		if (!userInAcl && corpus.groups_ACL) {
			for(var i = 0; i < groups.length; i++)	{
				if (groups[i]._id in corpus.groups_ACL) {
					if (list_right.indexOf(corpus.groups_ACL[groups[i]._id])!=-1) return true;
				}
			}
		}
	}
	return false;
}

// check if req.session.user._id have the good right to see this req.params.id_corpus
exports.AllowUser = function (list_right){
	return function(req, res, next) {
		async.waterfall([
			function(callback) {
				User.findById(req.session.user._id, function(error, user){
					callback(error, user);
				});
			},
			function(user, callback) {
				Group.find({'users_list' : {$regex : new RegExp('^'+ req.session.user._id + '$', "i")}}, function(error, groups) {
					callback(error, user, groups);
				});
			},
			function(user, groups, callback) {
				Corpus.findById(req.params.id_corpus, function(error, corpus){
					if (checkRight(corpus, user, groups, list_right)) next();
					else error = "Acces denied";
					callback(error);
	    		});
			},
		], function (error, trueOrFalse) {
			if (error) res.status(400).json({"message":error});
		});
	}
}

// retrieve all corpus
exports.getAll = function (req, res) {
	async.waterfall([
		function(callback) {
			User.findById(req.session.user._id, function(error, user){
				callback(error, user);
			});
		},
		function(user, callback) {
			Group.find({'users_list' : {$regex : new RegExp('^'+ req.session.user._id + '$', "i")}}, function(error, groups) {
				callback(error, user, groups);
			});
		},
		function(user, groups, callback) {
			Corpus.find({}, function(error, l_corpus){
    			async.filter(l_corpus,
    			        	 function(corpus, callback) {
    			          		callback (checkRight(corpus, user, groups, ['O', 'W', 'R']));
    			        	 },
    			        	 function(results) { res.status(200).json(results); }
    			);
    			callback(error);
    		});
		},
	], function (error, trueOrFalse) {
		if (error) res.status(400).json({"message":error});
	});
}

//retrieve a particular user (with id)
exports.getInfo = function(req, res){
	Corpus.findById(req.params.id_corpus, 'name description history', function(error, corpus){
		if (error) res.status(400).json({error:"error", message:error});
    	else res.status(200).json(corpus);
	});
}

//update information of a corpus
exports.update = function(req, res){
	var update = {};
	if (req.body.name) {
		if (req.body.name == "") res.status(400).json({"message":"name can't be empty"});
		else update.name = req.body.name;
	}
	if (req.body.description) update.description = req.body.description;
	Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
		if (error) res.status(400).json(error);
		else res.status(200).json(corpus);
	});
}

// remove a given corpus
exports.remove = function (req, res) {

	// check if corpus is empty

	Corpus.remove({_id : req.params.id_corpus}, function (error, corpus) {
		if (!error && corpus == 1) res.status(200).json({message:"The corpus as been delete"});
		else res.status(400).json({"message":error});
	});
}

//retrieve a particular user (with id)
exports.getACL = function(req, res){
	Corpus.findById(req.params.id_corpus, 'users_ACL groups_ACL', function(error, corpus){
		if (error) res.status(400).json({error:"error", message:error});
    	else res.status(200).json(corpus);
	});
}

// update ACL of a user
exports.updateUserACL = function(req, res){
	var update = {};
	var error=null;
	async.waterfall([
		function(callback) {
			if (req.body.Right != 'O' && req.body.Right != 'W' && req.body.Right != 'R') error="Right must be 'O' or 'W' or 'R'";
			callback(error);
		},
		function(callback) {
			Corpus.findById(req.params.id_corpus, function(error, corpus){
				if (!error){
					update.users_ACL = corpus.users_ACL;
					if (!update.users_ACL) update.users_ACL = {};
					update.users_ACL[req.params.id_user]=req.body.Right;
				}
				callback(error, update);
			});
		},
		function(update, callback) {
			Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
				if (!error) printRes(corpus, res);
				else res.status(400).json({"message":error});
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
}

// update ACL of a group
exports.updateGroupACL = function(req, res){
	var update = {};
	var error=null;
	async.waterfall([
		function(callback) {
			if (req.body.Right != 'O' && req.body.Right != 'W' && req.body.Right != 'R') error="Right must be 'O' or 'W' or 'R'";
			callback(error);
		},
		function(callback) {
			Corpus.findById(req.params.id_corpus, function(error, corpus){
				if (!error){
					update.groups_ACL = corpus.groups_ACL;
					if (!update.groups_ACL) update.groups_ACL = {};
					update.groups_ACL[req.params.id_group]=req.body.Right;
				}
				callback(error, update);
			});
		},
		function(update, callback) {
			Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
				if (!error) printRes(corpus, res);
				else res.status(400).json({"message":error});
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
}

// remove a user from ACL
exports.removeUserFromACL = function(req, res){
	var update = {};
	var error=null;
	async.waterfall([
		function(callback) {
			Corpus.findById(req.params.id_corpus, function(error, corpus){
				if (!error){
					update.users_ACL = corpus.users_ACL;
					if (!update.users_ACL) error=req.params.id_user+" not in users_ACL";
					else {
						if (update.users_ACL[req.params.id_user]) {
							delete update.users_ACL[req.params.id_user];
							if (Object.getOwnPropertyNames(update.users_ACL).length === 0) update.users_ACL = undefined;
						}
						else error=req.params.id_user+" not in users_ACL";
					}
				}
				callback(error, update);
			});
		},
		function(update, callback) {
			Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
				if (!error) printRes(corpus, res);
				else res.status(400).json({"message":error});
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
}

// remove a group from ACL
exports.removeGroupFromACL = function(req, res){
	var update = {};
	var error=null;
	async.waterfall([
		function(callback) {
			Corpus.findById(req.params.id_corpus, function(error, corpus){
				if (!error){
					update.groups_ACL = corpus.groups_ACL;
					if (!update.groups_ACL) error=req.params.id_group+" not in groups_ACL";
					else {
						if (update.groups_ACL[req.params.id_group]) {
							delete update.groups_ACL[req.params.id_group];
							if (Object.getOwnPropertyNames(update.groups_ACL).length === 0) update.groups_ACL = undefined;
						}
						else error=req.params.id_group+" not in groups_ACL";
					}
				}
				callback(error, update);
			});
		},
		function(update, callback) {
			Corpus.findByIdAndUpdate(req.params.id_corpus, update, function (error, corpus) {
				if (!error) printRes(corpus, res);
				else res.status(400).json({"message":error});
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
}

//add a media
exports.addMedia = function(req, res){
	var error=null;
	async.waterfall([
		function(callback) {
			if (req.body.name == undefined) error="the name is not define";
			if (req.body.name == "") 		error="empty string for name is not allow";
			callback(error);
		},
		function(callback) {
			var new_media = {};
			new_media.name = req.body.name;
			new_media.description = req.body.description;
			new_media.url = req.body.url;
			new_media.id_corpus = req.params.id_corpus;
			new_media.history = []
			new_media.history.push({date:new Date(), id_user:req.session.user._id, modification:{"name":new_media.name, "description":new_media.description, "url":new_media.url}});
			var media = new Media(new_media).save(function (error, newMedia) {
				if (newMedia) res.status(200).json(newMedia);
				callback(error);
			});
		}
	], function (error) {
		if (error) res.status(400).json({"message":error});
	});
};

<|endoftext|>