<commit_before>import React, {Component, PropTypes} from 'react'

import _ from 'lodash'
import uuid from 'node-uuid'

import ResizeContainer from 'shared/components/ResizeContainer'
import QueryMaker from 'src/data_explorer/components/QueryMaker'
import Visualization from 'src/data_explorer/components/Visualization'
import OverlayControls from 'src/dashboards/components/OverlayControls'
import DisplayOptions from 'src/dashboards/components/DisplayOptions'
import * as queryModifiers from 'src/utils/queryTransitions'

import defaultQueryConfig from 'src/utils/defaultQueryConfig'
import buildInfluxQLQuery from 'utils/influxql'
import {getQueryConfig} from 'shared/apis'

import {removeUnselectedTemplateValues} from 'src/dashboards/constants'
import {OVERLAY_TECHNOLOGY} from 'shared/constants/classNames'
import {MINIMUM_HEIGHTS, INITIAL_HEIGHTS} from 'src/data_explorer/constants'

class CellEditorOverlay extends Component {
  constructor(props) {
    super(props)

    this.queryStateReducer = ::this.queryStateReducer

    this.handleAddQuery = ::this.handleAddQuery
    this.handleDeleteQuery = ::this.handleDeleteQuery

    this.handleSaveCell = ::this.handleSaveCell

    this.handleSelectGraphType = ::this.handleSelectGraphType
    this.handleSelectDisplayOptions = ::this.handleSelectDisplayOptions
    this.handleSetActiveQueryIndex = ::this.handleSetActiveQueryIndex
    this.handleEditRawText = ::this.handleEditRawText
    this.handleSetRange = ::this.handleSetRange
    this.normalizeAxes = ::this.normalizeAxes

    const {cell: {name, type, queries, axes}} = props

    const queriesWorkingDraft = _.cloneDeep(
      queries.map(({queryConfig}) => ({...queryConfig, id: uuid.v4()}))
    )

    this.state = {
      cellWorkingName: name,
      cellWorkingType: type,
      queriesWorkingDraft,
      activeQueryIndex: 0,
      isDisplayOptionsTabOpen: false,
      axes,
    }
  }

  componentWillReceiveProps(nextProps) {
    const {status, queryID} = this.props.queryStatus
    const nextStatus = nextProps.queryStatus
    if (nextStatus.status && nextStatus.queryID) {
      if (nextStatus.queryID !== queryID || nextStatus.status !== status) {
        const nextQueries = this.state.queriesWorkingDraft.map(
          q => (q.id === queryID ? {...q, status: nextStatus.status} : q)
        )
        this.setState({queriesWorkingDraft: nextQueries})
      }
    }
  }

  queryStateReducer(queryModifier) {
    return (queryID, payload) => {
      const {queriesWorkingDraft} = this.state
      const query = queriesWorkingDraft.find(q => q.id === queryID)

      const nextQuery = queryModifier(query, payload)

      const nextQueries = queriesWorkingDraft.map(
        q => (q.id === query.id ? nextQuery : q)
      )
      this.setState({queriesWorkingDraft: nextQueries})
    }
  }

  handleSetRange(e) {
    const {min, max} = e.target.form

    // TODO: handle "" for min and max value
    this.setState({
      axes: {
        y: {
          bounds: [min.value, max.value],
        },
      },
    })
    e.preventDefault()
  }

  handleAddQuery(options) {
    const newQuery = Object.assign({}, defaultQueryConfig(uuid.v4()), options)
    const nextQueries = this.state.queriesWorkingDraft.concat(newQuery)
    this.setState({queriesWorkingDraft: nextQueries})
  }

  handleDeleteQuery(index) {
    const nextQueries = this.state.queriesWorkingDraft.filter(
      (__, i) => i !== index
    )
    this.setState({queriesWorkingDraft: nextQueries})
  }

  handleSaveCell() {
    const {
      queriesWorkingDraft,
      cellWorkingType: type,
      cellWorkingName: name,
    } = this.state

    const {cell} = this.props
    const axes = this.normalizeAxes()

    const queries = queriesWorkingDraft.map(q => {
      const timeRange = q.range || {upper: null, lower: ':dashboardTime:'}
      const query = q.rawText || buildInfluxQLQuery(timeRange, q)
      const label = q.rawText ? '' : `${q.measurement}.${q.fields[0].field}`

      return {
        queryConfig: q,
        query,
        label,
      }
    })

    this.props.onSave({
      ...cell,
      name,
      type,
      queries,
      axes,
    })
  }

  normalizeAxes() {
    const axes = this.state.axes
    const bounds = _.get(axes, ['y', 'bounds'], false)
    if (!bounds && !bounds.length) {
      return {...axes, y: {bounds: []}}
    }

    const [min, max] = bounds
    if (min === '' || max === '') {
      // TODO: throw requirement error
      return
    }

    return {...axes, y: {bounds: [+min, +max]}}
  }

  handleSelectGraphType(graphType) {
    this.setState({cellWorkingType: graphType})
  }

  handleSelectDisplayOptions(isDisplayOptionsTabOpen) {
    return () => {
      this.setState({isDisplayOptionsTabOpen})
    }
  }

  handleSetActiveQueryIndex(activeQueryIndex) {
    this.setState({activeQueryIndex})
  }

  async handleEditRawText(url, id, text) {
    const templates = removeUnselectedTemplateValues(this.props.templates)

    // use this as the handler passed into fetchTimeSeries to update a query status
    try {
      const {data} = await getQueryConfig(url, [{query: text, id}], templates)
      const config = data.queries.find(q => q.id === id)
      const nextQueries = this.state.queriesWorkingDraft.map(
        q => (q.id === id ? config.queryConfig : q)
      )
      this.setState({queriesWorkingDraft: nextQueries})
    } catch (error) {
      console.error(error)
    }
  }

  render() {
    const {
      source,
      onCancel,
      templates,
      timeRange,
      autoRefresh,
      editQueryStatus,
    } = this.props

    const {
      activeQueryIndex,
      cellWorkingName,
      cellWorkingType,
      isDisplayOptionsTabOpen,
      queriesWorkingDraft,
      axes,
    } = this.state

    const queryActions = {
      addQuery: this.handleAddQuery,
      editRawTextAsync: this.handleEditRawText,
      ..._.mapValues(queryModifiers, qm => this.queryStateReducer(qm)),
    }

    const isQuerySavable = query =>
      (!!query.measurement && !!query.database && !!query.fields.length) ||
      !!query.rawText

    return (

        <ResizeContainer
          containerClass="resizer--full-size"
          minTopHeight={MINIMUM_HEIGHTS.visualization}
          minBottomHeight={MINIMUM_HEIGHTS.queryMaker}
          initialTopHeight={INITIAL_HEIGHTS.visualization}
          initialBottomHeight={INITIAL_HEIGHTS.queryMaker}
        >
          <Visualization
            autoRefresh={autoRefresh}
            timeRange={timeRange}
            templates={templates}
            queryConfigs={queriesWorkingDraft}
            activeQueryIndex={0}
            cellType={cellWorkingType}
            cellName={cellWorkingName}
            editQueryStatus={editQueryStatus}
            axes={axes}
            views={[]}
          />

            <OverlayControls
              isDisplayOptionsTabOpen={isDisplayOptionsTabOpen}
              onSelectDisplayOptions={this.handleSelectDisplayOptions}
              onCancel={onCancel}
              onSave={this.handleSaveCell}
              isSavable={queriesWorkingDraft.every(isQuerySavable)}
            />
            {isDisplayOptionsTabOpen
              ? <DisplayOptions
                  selectedGraphType={cellWorkingType}
                  onSelectGraphType={this.handleSelectGraphType}
                  onSetRange={this.handleSetRange}
                  axes={axes}
                />
              : <QueryMaker
                  source={source}
                  templates={templates}
                  queries={queriesWorkingDraft}
                  actions={queryActions}
                  autoRefresh={autoRefresh}
                  timeRange={timeRange}
                  setActiveQueryIndex={this.handleSetActiveQueryIndex}
                  onDeleteQuery={this.handleDeleteQuery}
                  activeQueryIndex={activeQueryIndex}
                />}

        </ResizeContainer>

    )
  }
}

const {arrayOf, func, number, shape, string} = PropTypes

CellEditorOverlay.propTypes = {
  onCancel: func.isRequired,
  onSave: func.isRequired,
  cell: shape({}).isRequired,
  templates: arrayOf(
    shape({
      tempVar: string.isRequired,
    })
  ).isRequired,
  timeRange: shape({
    upper: string,
    lower: string,
  }).isRequired,
  autoRefresh: number.isRequired,
  source: shape({
    links: shape({
      proxy: string.isRequired,
      queries: string.isRequired,
    }).isRequired,
  }).isRequired,
  editQueryStatus: func.isRequired,
  queryStatus: shape({
    queryID: string,
    status: shape({}),
  }).isRequired,
  dashboardID: string.isRequired,
}

export default CellEditorOverlay
<commit_msg>Remove axes normalizer<commit_after>import React, {Component, PropTypes} from 'react'

import _ from 'lodash'
import uuid from 'node-uuid'

import ResizeContainer from 'shared/components/ResizeContainer'
import QueryMaker from 'src/data_explorer/components/QueryMaker'
import Visualization from 'src/data_explorer/components/Visualization'
import OverlayControls from 'src/dashboards/components/OverlayControls'
import DisplayOptions from 'src/dashboards/components/DisplayOptions'
import * as queryModifiers from 'src/utils/queryTransitions'

import defaultQueryConfig from 'src/utils/defaultQueryConfig'
import buildInfluxQLQuery from 'utils/influxql'
import {getQueryConfig} from 'shared/apis'

import {removeUnselectedTemplateValues} from 'src/dashboards/constants'
import {OVERLAY_TECHNOLOGY} from 'shared/constants/classNames'
import {MINIMUM_HEIGHTS, INITIAL_HEIGHTS} from 'src/data_explorer/constants'

class CellEditorOverlay extends Component {
  constructor(props) {
    super(props)

    this.queryStateReducer = ::this.queryStateReducer

    this.handleAddQuery = ::this.handleAddQuery
    this.handleDeleteQuery = ::this.handleDeleteQuery

    this.handleSaveCell = ::this.handleSaveCell

    this.handleSelectGraphType = ::this.handleSelectGraphType
    this.handleSelectDisplayOptions = ::this.handleSelectDisplayOptions
    this.handleSetActiveQueryIndex = ::this.handleSetActiveQueryIndex
    this.handleEditRawText = ::this.handleEditRawText
    this.handleSetRange = ::this.handleSetRange

    const {cell: {name, type, queries, axes}} = props

    const queriesWorkingDraft = _.cloneDeep(
      queries.map(({queryConfig}) => ({...queryConfig, id: uuid.v4()}))
    )

    this.state = {
      cellWorkingName: name,
      cellWorkingType: type,
      queriesWorkingDraft,
      activeQueryIndex: 0,
      isDisplayOptionsTabOpen: false,
      axes,
    }
  }

  componentWillReceiveProps(nextProps) {
    const {status, queryID} = this.props.queryStatus
    const nextStatus = nextProps.queryStatus
    if (nextStatus.status && nextStatus.queryID) {
      if (nextStatus.queryID !== queryID || nextStatus.status !== status) {
        const nextQueries = this.state.queriesWorkingDraft.map(
          q => (q.id === queryID ? {...q, status: nextStatus.status} : q)
        )
        this.setState({queriesWorkingDraft: nextQueries})
      }
    }
  }

  queryStateReducer(queryModifier) {
    return (queryID, payload) => {
      const {queriesWorkingDraft} = this.state
      const query = queriesWorkingDraft.find(q => q.id === queryID)

      const nextQuery = queryModifier(query, payload)

      const nextQueries = queriesWorkingDraft.map(
        q => (q.id === query.id ? nextQuery : q)
      )
      this.setState({queriesWorkingDraft: nextQueries})
    }
  }

  handleSetRange(e) {
    const {min, max} = e.target.form

    this.setState({
      axes: {
        y: {
          bounds: [min.value, max.value],
        },
      },
    })
    e.preventDefault()
  }

  handleAddQuery(options) {
    const newQuery = Object.assign({}, defaultQueryConfig(uuid.v4()), options)
    const nextQueries = this.state.queriesWorkingDraft.concat(newQuery)
    this.setState({queriesWorkingDraft: nextQueries})
  }

  handleDeleteQuery(index) {
    const nextQueries = this.state.queriesWorkingDraft.filter(
      (__, i) => i !== index
    )
    this.setState({queriesWorkingDraft: nextQueries})
  }

  handleSaveCell() {
    const {
      queriesWorkingDraft,
      cellWorkingType: type,
      cellWorkingName: name,
      axes,
    } = this.state

    const {cell} = this.props

    const queries = queriesWorkingDraft.map(q => {
      const timeRange = q.range || {upper: null, lower: ':dashboardTime:'}
      const query = q.rawText || buildInfluxQLQuery(timeRange, q)
      const label = q.rawText ? '' : `${q.measurement}.${q.fields[0].field}`

      return {
        queryConfig: q,
        query,
        label,
      }
    })

    this.props.onSave({
      ...cell,
      name,
      type,
      queries,
      axes,
    })
  }

  handleSelectGraphType(graphType) {
    this.setState({cellWorkingType: graphType})
  }

  handleSelectDisplayOptions(isDisplayOptionsTabOpen) {
    return () => {
      this.setState({isDisplayOptionsTabOpen})
    }
  }

  handleSetActiveQueryIndex(activeQueryIndex) {
    this.setState({activeQueryIndex})
  }

  async handleEditRawText(url, id, text) {
    const templates = removeUnselectedTemplateValues(this.props.templates)

    // use this as the handler passed into fetchTimeSeries to update a query status
    try {
      const {data} = await getQueryConfig(url, [{query: text, id}], templates)
      const config = data.queries.find(q => q.id === id)
      const nextQueries = this.state.queriesWorkingDraft.map(
        q => (q.id === id ? config.queryConfig : q)
      )
      this.setState({queriesWorkingDraft: nextQueries})
    } catch (error) {
      console.error(error)
    }
  }

  render() {
    const {
      source,
      onCancel,
      templates,
      timeRange,
      autoRefresh,
      editQueryStatus,
    } = this.props

    const {
      activeQueryIndex,
      cellWorkingName,
      cellWorkingType,
      isDisplayOptionsTabOpen,
      queriesWorkingDraft,
      axes,
    } = this.state

    const queryActions = {
      addQuery: this.handleAddQuery,
      editRawTextAsync: this.handleEditRawText,
      ..._.mapValues(queryModifiers, qm => this.queryStateReducer(qm)),
    }

    const isQuerySavable = query =>
      (!!query.measurement && !!query.database && !!query.fields.length) ||
      !!query.rawText

    return (

        <ResizeContainer
          containerClass="resizer--full-size"
          minTopHeight={MINIMUM_HEIGHTS.visualization}
          minBottomHeight={MINIMUM_HEIGHTS.queryMaker}
          initialTopHeight={INITIAL_HEIGHTS.visualization}
          initialBottomHeight={INITIAL_HEIGHTS.queryMaker}
        >
          <Visualization
            autoRefresh={autoRefresh}
            timeRange={timeRange}
            templates={templates}
            queryConfigs={queriesWorkingDraft}
            activeQueryIndex={0}
            cellType={cellWorkingType}
            cellName={cellWorkingName}
            editQueryStatus={editQueryStatus}
            axes={axes}
            views={[]}
          />

            <OverlayControls
              isDisplayOptionsTabOpen={isDisplayOptionsTabOpen}
              onSelectDisplayOptions={this.handleSelectDisplayOptions}
              onCancel={onCancel}
              onSave={this.handleSaveCell}
              isSavable={queriesWorkingDraft.every(isQuerySavable)}
            />
            {isDisplayOptionsTabOpen
              ? <DisplayOptions
                  selectedGraphType={cellWorkingType}
                  onSelectGraphType={this.handleSelectGraphType}
                  onSetRange={this.handleSetRange}
                  axes={axes}
                />
              : <QueryMaker
                  source={source}
                  templates={templates}
                  queries={queriesWorkingDraft}
                  actions={queryActions}
                  autoRefresh={autoRefresh}
                  timeRange={timeRange}
                  setActiveQueryIndex={this.handleSetActiveQueryIndex}
                  onDeleteQuery={this.handleDeleteQuery}
                  activeQueryIndex={activeQueryIndex}
                />}

        </ResizeContainer>

    )
  }
}

const {arrayOf, func, number, shape, string} = PropTypes

CellEditorOverlay.propTypes = {
  onCancel: func.isRequired,
  onSave: func.isRequired,
  cell: shape({}).isRequired,
  templates: arrayOf(
    shape({
      tempVar: string.isRequired,
    })
  ).isRequired,
  timeRange: shape({
    upper: string,
    lower: string,
  }).isRequired,
  autoRefresh: number.isRequired,
  source: shape({
    links: shape({
      proxy: string.isRequired,
      queries: string.isRequired,
    }).isRequired,
  }).isRequired,
  editQueryStatus: func.isRequired,
  queryStatus: shape({
    queryID: string,
    status: shape({}),
  }).isRequired,
  dashboardID: string.isRequired,
}

export default CellEditorOverlay
<|endoftext|>


<commit_before>/**
 *	Copyright (C) 2015 3D Repo Ltd
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU Affero General Public License as
 *	published by the Free Software Foundation, either version 3 of the
 *	License, or (at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU Affero General Public License for more details.
 *
 *	You should have received a copy of the GNU Affero General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/***************************************************************************
*  @file Contains functionality to dispatch work to the
 *       queue via amqp protocol. A compute node with a worker must be running
 *       to fulfil the tasks in order for the work to be done.
****************************************************************************/

var amqp = require('amqplib');
var fs = require('fs.extra');
var uuid = require('node-uuid');

function ImportQueue() {}

/*******************************************************************************
 * Create a connection and a channel in ampq and init variables
 * @param {url} url - ampq connection string
 * @param {options} options - defines sharedSpacePath, logger, callbackQName and workerQName
 *******************************************************************************/
ImportQueue.prototype.connect = function(url, options) {
    'use strict';

    if(this.conn){
        return Promise.resolve();
    }

    if(!options.sharedSpacePath){
        return Promise.reject({ message: 'Please define sharedSpacePath in options'});
    } else if(!options.logger){
        return Promise.reject({ message: 'Please define logger in options'});
    } else if(!options.callbackQName){
        return Promise.reject({ message: 'Please define callbackQName in options'});
    } else if(!options.workerQName){
        return Promise.reject({ message: 'Please define workerQName in options'});
    }

    return amqp.connect(url).then( conn => {

        this.conn = conn;

        conn.on('close', () => {
            this.conn = null;
        });

        return conn.createChannel();

    }).then(channel => {

        this.channel = channel;
        this.sharedSpacePath = options.sharedSpacePath;
        this.logger = options.logger;
        this.callbackQName = options.callbackQName;
        this.workerQName = options.workerQName;
        this.deferedObjs = {};

        return this._consumeCallbackQueue();

    }).catch( err => {
        return Promise.reject(err);
    });
};

/*******************************************************************************
 * Dispatch work to queue to import a model via a file uploaded by User
 * @param {filePath} filePath - Path to uploaded file
 * @param {orgFileName} orgFileName - Original file name of the file
 * @param {databaseName} databaseName - name of database to commit to
 * @param {projectName} projectName - name of project to commit to
 * @param {userName} userName - name of user
 *******************************************************************************/
ImportQueue.prototype.importFile = function(filePath, orgFileName, databaseName, projectName, userName, copy){
    'use strict';

    let corID = uuid.v1();

    //console.log(filePath);
    //console.log(orgFileName);

    return this._moveFileToSharedSpace(corID, filePath, orgFileName, copy).then(newPath => {

        let msg = 'import ' + newPath + ' ' + databaseName + ' ' + projectName + ' ' + userName;
        return this._dispatchWork(corID, msg);

    }).then(() => {

        return new Promise((resolve, reject) => {

            this.deferedObjs[corID] = {
                resolve: () => resolve(corID),
                reject: errCode => reject({corID, errCode})
            };

        });
    });
};

/*******************************************************************************
 * Dispatch work to queue to create a federated project
 * @param {account} account - username
 * @param {defObj} defObj - object to describe the federated project like subprojects and transformation
 *******************************************************************************/
ImportQueue.prototype.createFederatedProject = function(account, defObj){
    'use strict';

    let corID = uuid.v1();
    let newFileDir = this.sharedSpacePath + "/" + corID;
    let filename = `${newFileDir}/obj.json`;

    return new Promise((resolve, reject) => {

        fs.mkdir(this.sharedSpacePath, function(err){

            if(!err || err && err.code == 'EEXIST'){
                resolve();
            } else {
                reject(err);
            }

        });

    }).then(() => {

        return new Promise((resolve, reject) => {

            fs.mkdir(newFileDir, function (err){
                if (err) {
                    reject(err);
                } else {
                    resolve();
                }
            });

        });

    }).then(() => {

        return new Promise((resolve, reject) => {
            fs.writeFile(filename, JSON.stringify(defObj), { flag: 'a+'}, err => {
                if(err){
                    reject(err);
                } else {
                    resolve();
                }
            });
        });

    }).then(() => {

        let msg = `genFed ${filename} ${account}`;
        return this._dispatchWork(corID, msg);

    }).then(() => {

        return new Promise((resolve, reject) => {
            this.deferedObjs[corID] = {
                resolve: () => resolve(corID),
                reject: errCode => reject({corID, errCode})
            };
        });

    });

};

/*******************************************************************************
 * Move a specified file to shared storage (area shared by queue workers)
 * move the file to shared storage space, put it in a corID/newFileName
 * note: using move(in fs.extra) instead of rename(in fs) as rename doesn't allow cross device
 * @param {corID} corID - Correlation ID
 * @param {orgFilePath} orgFilePath - Path to where the file is currently
 * @param {newFileName} newFileName - New file name to rename to
 *******************************************************************************/
ImportQueue.prototype._moveFileToSharedSpace = function(corID, orgFilePath, newFileName, copy) {
    'use strict';

    let newFileDir = this.sharedSpacePath + "/" + corID + "/";
    let filePath = newFileDir + newFileName;

    return new Promise((resolve, reject) => {
        fs.mkdir(newFileDir, function (err){
            if (err) {
                reject(err);
            } else {

                let move = copy ? fs.copy : fs.move;

                move(orgFilePath, filePath, function (err) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(filePath);
                    }
                });
            }

        });
    });

};

/*******************************************************************************
 * Insert a job item in worker queue
 *
 * @param {corID} corID - Correlation ID
 * @param {msg} orgFilePath - Path to where the file is currently
 *******************************************************************************/
ImportQueue.prototype._dispatchWork = function(corID, msg){
    'use strict';

    let info;
    return this.channel.assertQueue(this.workerQName, { durable: true }).then( _info => {

        info = _info;

        return this.channel.sendToQueue(this.workerQName,
            new Buffer(msg),
            {
                correlationId: corID,
                replyTo: this.callbackQName,
                persistent: true
            }
        );

    }).then( () => {

        this.logger.logInfo(
            'Sent work to queue: ' + msg.toString() + ' with corr id: ' + corID.toString() + ' reply queue: ' + this.callbackQName,
            {
                corID: corID.toString()
            }
        );

        if(info.consumerCount <= 0){
            this.logger.logError(
                `No consumer found in the queue`,
                {
                    corID: corID.toString()
                }
            );
        }

        return Promise.resolve(() => {});
    });

};

// ImportQueue.prototype.assertQueue = function(){
//     return this.channel.assertQueue(this.workerQName, { durable: true });
// }

/*******************************************************************************
 * Listen to callback queue, resolve promise when job done
 * Should be called once only, presumably in constructor
 *******************************************************************************/
ImportQueue.prototype._consumeCallbackQueue = function(){
    'use strict';

    let self = this;

    return this.channel.assertQueue(this.callbackQName, { durable: true }).then(() => {
        return this.channel.consume(this.callbackQName, function(rep) {
            self.logger.logInfo('Job request id ' + rep.properties.correlationId + ' returned with: ' + rep.content);

            let defer = self.deferedObjs[rep.properties.correlationId];

            let resErrorCode = parseInt(JSON.parse(rep.content).value);

            if(defer && resErrorCode === 0){
                defer.resolve();
            } else if (defer) {
                defer.reject(resErrorCode);
            } else {
                self.logger.logError('Job done but cannot find corresponding defer object with cor id ' + rep.properties.correlationId);
            }

            defer && delete self.deferedObjs[rep.properties.correlationId];

        }, { noAck: true });
    });
};

module.exports = new ImportQueue();
<commit_msg>#234 jslint<commit_after>/**
 *	Copyright (C) 2015 3D Repo Ltd
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU Affero General Public License as
 *	published by the Free Software Foundation, either version 3 of the
 *	License, or (at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU Affero General Public License for more details.
 *
 *	You should have received a copy of the GNU Affero General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/***************************************************************************
*  @file Contains functionality to dispatch work to the
 *       queue via amqp protocol. A compute node with a worker must be running
 *       to fulfil the tasks in order for the work to be done.
****************************************************************************/

var amqp = require('amqplib');
var fs = require('fs.extra');
var uuid = require('node-uuid');

function ImportQueue() {}

/*******************************************************************************
 * Create a connection and a channel in ampq and init variables
 * @param {url} url - ampq connection string
 * @param {options} options - defines sharedSpacePath, logger, callbackQName and workerQName
 *******************************************************************************/
ImportQueue.prototype.connect = function(url, options) {
    'use strict';

    if(this.conn){
        return Promise.resolve();
    }

    if(!options.sharedSpacePath){
        return Promise.reject({ message: 'Please define sharedSpacePath in options'});
    } else if(!options.logger){
        return Promise.reject({ message: 'Please define logger in options'});
    } else if(!options.callbackQName){
        return Promise.reject({ message: 'Please define callbackQName in options'});
    } else if(!options.workerQName){
        return Promise.reject({ message: 'Please define workerQName in options'});
    }

    return amqp.connect(url).then( conn => {

        this.conn = conn;

        conn.on('close', () => {
            this.conn = null;
        });

        return conn.createChannel();

    }).then(channel => {

        this.channel = channel;
        this.sharedSpacePath = options.sharedSpacePath;
        this.logger = options.logger;
        this.callbackQName = options.callbackQName;
        this.workerQName = options.workerQName;
        this.deferedObjs = {};

        return this._consumeCallbackQueue();

    }).catch( err => {
        return Promise.reject(err);
    });
};

/*******************************************************************************
 * Dispatch work to queue to import a model via a file uploaded by User
 * @param {filePath} filePath - Path to uploaded file
 * @param {orgFileName} orgFileName - Original file name of the file
 * @param {databaseName} databaseName - name of database to commit to
 * @param {projectName} projectName - name of project to commit to
 * @param {userName} userName - name of user
 *******************************************************************************/
ImportQueue.prototype.importFile = function(filePath, orgFileName, databaseName, projectName, userName, copy){
    'use strict';

    let corID = uuid.v1();

    //console.log(filePath);
    //console.log(orgFileName);

    return this._moveFileToSharedSpace(corID, filePath, orgFileName, copy).then(newPath => {

        let msg = 'import ' + newPath + ' ' + databaseName + ' ' + projectName + ' ' + userName;
        return this._dispatchWork(corID, msg);

    }).then(() => {

        return new Promise((resolve, reject) => {

            this.deferedObjs[corID] = {
                resolve: () => resolve(corID),
                reject: errCode => reject({corID, errCode})
            };

        });
    });
};

/*******************************************************************************
 * Dispatch work to queue to create a federated project
 * @param {account} account - username
 * @param {defObj} defObj - object to describe the federated project like subprojects and transformation
 *******************************************************************************/
ImportQueue.prototype.createFederatedProject = function(account, defObj){
    'use strict';

    let corID = uuid.v1();
    let newFileDir = this.sharedSpacePath + "/" + corID;
    let filename = `${newFileDir}/obj.json`;

    return new Promise((resolve, reject) => {

        fs.mkdir(this.sharedSpacePath, function(err){

            if(!err || err && err.code === 'EEXIST'){
                resolve();
            } else {
                reject(err);
            }

        });

    }).then(() => {

        return new Promise((resolve, reject) => {

            fs.mkdir(newFileDir, function (err){
                if (err) {
                    reject(err);
                } else {
                    resolve();
                }
            });

        });

    }).then(() => {

        return new Promise((resolve, reject) => {
            fs.writeFile(filename, JSON.stringify(defObj), { flag: 'a+'}, err => {
                if(err){
                    reject(err);
                } else {
                    resolve();
                }
            });
        });

    }).then(() => {

        let msg = `genFed ${filename} ${account}`;
        return this._dispatchWork(corID, msg);

    }).then(() => {

        return new Promise((resolve, reject) => {
            this.deferedObjs[corID] = {
                resolve: () => resolve(corID),
                reject: errCode => reject({corID, errCode})
            };
        });

    });

};

/*******************************************************************************
 * Move a specified file to shared storage (area shared by queue workers)
 * move the file to shared storage space, put it in a corID/newFileName
 * note: using move(in fs.extra) instead of rename(in fs) as rename doesn't allow cross device
 * @param {corID} corID - Correlation ID
 * @param {orgFilePath} orgFilePath - Path to where the file is currently
 * @param {newFileName} newFileName - New file name to rename to
 *******************************************************************************/
ImportQueue.prototype._moveFileToSharedSpace = function(corID, orgFilePath, newFileName, copy) {
    'use strict';

    let newFileDir = this.sharedSpacePath + "/" + corID + "/";
    let filePath = newFileDir + newFileName;

    return new Promise((resolve, reject) => {
        fs.mkdir(newFileDir, function (err){
            if (err) {
                reject(err);
            } else {

                let move = copy ? fs.copy : fs.move;

                move(orgFilePath, filePath, function (err) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(filePath);
                    }
                });
            }

        });
    });

};

/*******************************************************************************
 * Insert a job item in worker queue
 *
 * @param {corID} corID - Correlation ID
 * @param {msg} orgFilePath - Path to where the file is currently
 *******************************************************************************/
ImportQueue.prototype._dispatchWork = function(corID, msg){
    'use strict';

    let info;
    return this.channel.assertQueue(this.workerQName, { durable: true }).then( _info => {

        info = _info;

        return this.channel.sendToQueue(this.workerQName,
            new Buffer(msg),
            {
                correlationId: corID,
                replyTo: this.callbackQName,
                persistent: true
            }
        );

    }).then( () => {

        this.logger.logInfo(
            'Sent work to queue: ' + msg.toString() + ' with corr id: ' + corID.toString() + ' reply queue: ' + this.callbackQName,
            {
                corID: corID.toString()
            }
        );

        if(info.consumerCount <= 0){
            this.logger.logError(
                `No consumer found in the queue`,
                {
                    corID: corID.toString()
                }
            );
        }

        return Promise.resolve(() => {});
    });

};

// ImportQueue.prototype.assertQueue = function(){
//     return this.channel.assertQueue(this.workerQName, { durable: true });
// }

/*******************************************************************************
 * Listen to callback queue, resolve promise when job done
 * Should be called once only, presumably in constructor
 *******************************************************************************/
ImportQueue.prototype._consumeCallbackQueue = function(){
    'use strict';

    let self = this;

    return this.channel.assertQueue(this.callbackQName, { durable: true }).then(() => {
        return this.channel.consume(this.callbackQName, function(rep) {
            self.logger.logInfo('Job request id ' + rep.properties.correlationId + ' returned with: ' + rep.content);

            let defer = self.deferedObjs[rep.properties.correlationId];

            let resErrorCode = parseInt(JSON.parse(rep.content).value);

            if(defer && resErrorCode === 0){
                defer.resolve();
            } else if (defer) {
                defer.reject(resErrorCode);
            } else {
                self.logger.logError('Job done but cannot find corresponding defer object with cor id ' + rep.properties.correlationId);
            }

            defer && delete self.deferedObjs[rep.properties.correlationId];

        }, { noAck: true });
    });
};

module.exports = new ImportQueue();
<|endoftext|>


<commit_before>/**
 * @namespace hs
 */

/**
 * @namespace hs.core
 * @memberOf hs
 */
require.config({
    paths: {
        angular: hsl_path + 'bower_components/angular/angular',
        ngcookies: hsl_path + 'bower_components/angular-cookies/angular-cookies',
        bootstrap: hsl_path + 'bower_components/bootstrap/dist/js/bootstrap',
        ol: requirejs.s.contexts._.config.paths.ol || hsl_path + 'node_modules/openlayers/dist/ol',
        drag: hsl_path + 'components/drag/drag',
        map: hsl_path + 'components/map/map',
        styles: hsl_path + 'components/styles/styles',
        'angular-sanitize': hsl_path + 'bower_components/angular-sanitize/angular-sanitize',
        'angular-gettext': hsl_path + 'bower_components/angular-gettext/dist/angular-gettext',
        compositions: hsl_path + 'components/compositions/compositions',
        permalink: requirejs.s.contexts._.config.paths.permalink || hsl_path + 'components/permalink/permalink',
        utils: hsl_path + 'components/utils',
        status_creator: hsl_path + 'components/status_creator/status_creator',
        xml2json: requirejs.s.contexts._.config.paths.xml2json || hsl_path + 'bower_components/xml2json/xml2json.min',
        customhtml: requirejs.s.contexts._.config.paths.customhtml || hsl_path + 'components/customhtml/customhtml',
        d3: requirejs.s.contexts._.config.paths.d3 || hsl_path + 'bower_components/d3/d3.min',
        proj4: requirejs.s.contexts._.config.paths.proj4 || hsl_path + 'bower_components/proj4/dist/proj4',
        crossfilter: requirejs.s.contexts._.config.paths.crossfilter || hsl_path + 'bower_components/crossfilter/crossfilter.min',
        dc: requirejs.s.contexts._.config.paths.dc || '//cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc',
        api: requirejs.s.contexts._.config.paths.api || hsl_path + 'components/api/api',
        translations: requirejs.s.contexts._.config.paths.translations || hsl_path + 'components/translations/js/translations',
        sidebar: requirejs.s.contexts._.config.paths.sidebar || hsl_path + 'components/sidebar/sidebar',
        geojson: requirejs.s.contexts._.config.paths.geojson || hsl_path + 'components/layers/hs.source.GeoJSON',
        mobile_toolbar: requirejs.s.contexts._.config.paths.mobile_toolbar || hsl_path + 'components/mobile_toolbar/mobile_toolbar',
        SparqlJson: requirejs.s.contexts._.config.paths.SparqlJson || hsl_path + 'components/layers/hs.source.SparqlJson',
        WFSCapabilities: requirejs.s.contexts._.config.paths.WFSCapabilities || hsl_path + 'components/format/hs.format.WFSCapabilities',
        WfsSource: requirejs.s.contexts._.config.paths.WfsSource || hsl_path + 'components/layers/hs.source.Wfs'
    },
    shim: {
        'angular': {
            'exports': 'angular'
        },
        'angular-sanitize': {
            deps: ['angular'],
        },
        'angular-gettext': {
            deps: ['angular'],
        },
        ngcookies: {
            deps: ['angular'],
        },
        translations: {
            deps: ['angular-gettext'],
        }
    },
    priority: [
        "angular"
    ]
});

define(['angular', 'angular-gettext', 'translations', 'ol', 'map', 'drag', 'api', 'proj4'],
    function(angular, proj4) {
        angular.module('hs.core', ['hs.map', 'gettext', 'gettext', 'hs.drag', 'hs.api'])
            .service("Core", ['$rootScope', '$controller', '$window', 'hs.map.service', 'gettextCatalog', 'config', '$templateCache',
                function($rootScope, $controller, $window, OlMap, gettextCatalog, config, $templateCache) {
                    var me = {
                        config: config,
                        scopes_registered: [],
                        mainpanel: "",
                        defaultPanel: "",
                        sidebarExpanded: false,
                        sidebarRight: true,
                        sidebarLabels: true,
                        sidebarToggleable: true,
                        sidebarButtons: true,
                        singleDatasources: false,
                        embededEnabled: true,
                        panel_statuses: {},
                        _exist_cache: {},
                        setMainPanel: function(which, by_gui) {
                            if (which == me.mainpanel && by_gui) {
                                which = "";
                                if (me.sidebarExpanded == true) {
                                    me.sidebarLabels = true;
                                }
                            } else {
                                me.sidebarExpanded = true;
                                me.sidebarLabels = false;
                            }
                            me.mainpanel = which;
                            if (!$rootScope.$$phase) $rootScope.$digest();
                            $rootScope.$broadcast('core.mainpanel_changed');
                        },
                        setDefaultPanel: function(which) {
                            me.defaultPanel = which;
                            me.setMainPanel(which);
                        },
                        updateMapSize: function(open) {
                            var w = angular.element($window);
                            var map = $("#map");
                            var sidebarElem = $('.panelspace');
                            if (w.width() != sidebarElem.width()) {
                                map.width(w.width() - sidebarElem.width());
                            } else {
                                map.width(w.width());
                            }
                            OlMap.map.updateSize();
                        },

                        panelVisible: function(which, scope) {
                            if (angular.isDefined(scope))
                                if (angular.isUndefined(scope.panel_name)) scope.panel_name = which;
                            if (angular.isDefined(me.panel_statuses[which])) {
                                return me.panel_statuses[which];
                            }
                            return me.mainpanel == which || (angular.isDefined(scope) && scope.unpinned);
                        },
                        hidePanels: function() {
                            me.mainpanel = '';
                            me.sidebarLabels = true;
                            if (!me.exists('hs.sidebar.controller')) {
                                me.sidebarExpanded = false
                            }
                            if (!$rootScope.$$phase) $rootScope.$digest();
                            $rootScope.$broadcast('core.mainpanel_changed');
                        },
                        closePanel: function(which) {
                            if (which.unpinned) {
                                which.drag_panel.appendTo($(which.original_container));
                                which.drag_panel.css({
                                    top: 'auto',
                                    left: 'auto',
                                    position: 'relative'
                                });
                            }
                            which.unpinned = false;
                            if (which.panel_name == me.mainpanel) {
                                if (me.defaultPanel != '') {
                                    me.setMainPanel(me.defaultPanel)
                                } else {
                                    me.mainpanel = '';
                                    me.sidebarLabels = true;
                                }
                                if (!me.exists('hs.sidebar.controller')) {
                                    me.sidebarExpanded = false
                                }

                            }

                            $rootScope.$broadcast('core.mainpanel_changed');
                        },
                        exists: function(controllerName) {
                            if (angular.isDefined(me._exist_cache[controllerName])) return true;
                            if (typeof window[controllerName] == 'function') {
                                return true;
                            }
                            try {
                                $controller(controllerName);
                                me._exist_cache[controllerName] = true;
                                return true;
                            } catch (error) {
                                var t = !(error instanceof TypeError);
                                if (t) me._exist_cache[controllerName] = true;
                                return t;
                            }
                        },
                        fullScreenMap: function(element) {
                            var w = angular.element($window);
                            w.bind('resize', function() {
                                $("html").css('overflow', 'hidden');
                                $("html").css('height', '100%');
                                $('body').css('height', '100%');
                                element[0].style.height = w.height() + "px";
                                element[0].style.width = w.width() + "px";
                                $("#map").height(w.height());
                                me.updateMapSize();
                                OlMap.map.updateSize();
                            });
                            w.resize();
                        },
                        setLanguage: function(lang) {
                            switch (lang) {
                                case "cs_CZ":
                                    lang = 'cs';
                                    break;
                                case "nl_BE":
                                    lang = 'nl';
                                    break;
                            }
                            gettextCatalog.setCurrentLanguage(lang);
                        },
                        getAllScopes: function() {
                            var getScopes = function(root) {
                                var scopes = [];

                                function visit(scope) {
                                    scopes.push(scope);
                                }

                                function traverse(scope) {
                                    visit(scope);
                                    if (scope.$$nextSibling)
                                        traverse(scope.$$nextSibling);
                                    if (scope.$$childHead)
                                        traverse(scope.$$childHead);
                                }

                                traverse(root);
                                return scopes;
                            }
                            return getScopes($rootScope);
                        },
                        openStatusCreator: function() {
                            //me.panel_statuses.status_creator = true;
                            hslayers_api.gui.StatusCreator.open();
                        },
                        searchVisible: function(is) {
                            if (arguments.length > 0) {
                                me.panel_statuses['search'] = is;
                            }
                            return me.panel_statuses['search']
                        },
                        isAuthorized: function() {
                            if (angular.isDefined(window.getLRUser) && window.getLRUser() != 'guest') {
                                return true;
                            }
                            return false;
                        },
                        resetMap: function() {
                            OlMap.reset();
                            $rootScope.$broadcast('core.map_reset', {});
                        },
                        isMobile: function() {
                            if (screen.width < 800) {
                                return "mobile";
                            } else {
                                return "";
                            }
                        }
                    };

                    $templateCache.removeAll();

                    if (me.exists('hs.sidebar.controller')) {
                        me.sidebarExpanded = true;
                    }

                    if (me.defaultPanel != '') {
                        me.setMainPanel(me.defaultPanel);
                    }

                    /* HACK: https://github.com/openlayers/ol3/issues/3990 */
                    try {
                        if (typeof require('proj4') != undefined) {
                            require(['proj4'], function() {
                                window.proj4 = proj4
                            });
                        }
                    } catch (ex) {
                        require(['proj4'], function() {
                            window.proj4 = proj4
                        });
                    }

                    return me;
                },

            ]);

    })
<commit_msg>ows.wfs path config in Core<commit_after>/**
 * @namespace hs
 */

/**
 * @namespace hs.core
 * @memberOf hs
 */
require.config({
    paths: {
        angular: hsl_path + 'bower_components/angular/angular',
        ngcookies: hsl_path + 'bower_components/angular-cookies/angular-cookies',
        bootstrap: hsl_path + 'bower_components/bootstrap/dist/js/bootstrap',
        ol: requirejs.s.contexts._.config.paths.ol || hsl_path + 'node_modules/openlayers/dist/ol',
        drag: hsl_path + 'components/drag/drag',
        map: hsl_path + 'components/map/map',
        styles: hsl_path + 'components/styles/styles',
        'angular-sanitize': hsl_path + 'bower_components/angular-sanitize/angular-sanitize',
        'angular-gettext': hsl_path + 'bower_components/angular-gettext/dist/angular-gettext',
        compositions: hsl_path + 'components/compositions/compositions',
        permalink: requirejs.s.contexts._.config.paths.permalink || hsl_path + 'components/permalink/permalink',
        utils: hsl_path + 'components/utils',
        status_creator: hsl_path + 'components/status_creator/status_creator',
        xml2json: requirejs.s.contexts._.config.paths.xml2json || hsl_path + 'bower_components/xml2json/xml2json.min',
        customhtml: requirejs.s.contexts._.config.paths.customhtml || hsl_path + 'components/customhtml/customhtml',
        d3: requirejs.s.contexts._.config.paths.d3 || hsl_path + 'bower_components/d3/d3.min',
        proj4: requirejs.s.contexts._.config.paths.proj4 || hsl_path + 'bower_components/proj4/dist/proj4',
        crossfilter: requirejs.s.contexts._.config.paths.crossfilter || hsl_path + 'bower_components/crossfilter/crossfilter.min',
        dc: requirejs.s.contexts._.config.paths.dc || '//cdnjs.cloudflare.com/ajax/libs/dc/1.7.0/dc',
        api: requirejs.s.contexts._.config.paths.api || hsl_path + 'components/api/api',
        translations: requirejs.s.contexts._.config.paths.translations || hsl_path + 'components/translations/js/translations',
        sidebar: requirejs.s.contexts._.config.paths.sidebar || hsl_path + 'components/sidebar/sidebar',
        geojson: requirejs.s.contexts._.config.paths.geojson || hsl_path + 'components/layers/hs.source.GeoJSON',
        mobile_toolbar: requirejs.s.contexts._.config.paths.mobile_toolbar || hsl_path + 'components/mobile_toolbar/mobile_toolbar',
        SparqlJson: requirejs.s.contexts._.config.paths.SparqlJson || hsl_path + 'components/layers/hs.source.SparqlJson',
        WFSCapabilities: requirejs.s.contexts._.config.paths.WFSCapabilities || hsl_path + 'components/format/hs.format.WFSCapabilities',
        WfsSource: requirejs.s.contexts._.config.paths.WfsSource || hsl_path + 'components/layers/hs.source.Wfs',
        'ows.wfs': requirejs.s.contexts._.config.paths.['ows.wfs']|| hsl_path + 'components/ows/ows_wfs',
    },
    shim: {
        'angular': {
            'exports': 'angular'
        },
        'angular-sanitize': {
            deps: ['angular'],
        },
        'angular-gettext': {
            deps: ['angular'],
        },
        ngcookies: {
            deps: ['angular'],
        },
        translations: {
            deps: ['angular-gettext'],
        }
    },
    priority: [
        "angular"
    ]
});

define(['angular', 'angular-gettext', 'translations', 'ol', 'map', 'drag', 'api', 'proj4'],
    function(angular, proj4) {
        angular.module('hs.core', ['hs.map', 'gettext', 'gettext', 'hs.drag', 'hs.api'])
            .service("Core", ['$rootScope', '$controller', '$window', 'hs.map.service', 'gettextCatalog', 'config', '$templateCache',
                function($rootScope, $controller, $window, OlMap, gettextCatalog, config, $templateCache) {
                    var me = {
                        config: config,
                        scopes_registered: [],
                        mainpanel: "",
                        defaultPanel: "",
                        sidebarExpanded: false,
                        sidebarRight: true,
                        sidebarLabels: true,
                        sidebarToggleable: true,
                        sidebarButtons: true,
                        singleDatasources: false,
                        embededEnabled: true,
                        panel_statuses: {},
                        _exist_cache: {},
                        setMainPanel: function(which, by_gui) {
                            if (which == me.mainpanel && by_gui) {
                                which = "";
                                if (me.sidebarExpanded == true) {
                                    me.sidebarLabels = true;
                                }
                            } else {
                                me.sidebarExpanded = true;
                                me.sidebarLabels = false;
                            }
                            me.mainpanel = which;
                            if (!$rootScope.$$phase) $rootScope.$digest();
                            $rootScope.$broadcast('core.mainpanel_changed');
                        },
                        setDefaultPanel: function(which) {
                            me.defaultPanel = which;
                            me.setMainPanel(which);
                        },
                        updateMapSize: function(open) {
                            var w = angular.element($window);
                            var map = $("#map");
                            var sidebarElem = $('.panelspace');
                            if (w.width() != sidebarElem.width()) {
                                map.width(w.width() - sidebarElem.width());
                            } else {
                                map.width(w.width());
                            }
                            OlMap.map.updateSize();
                        },

                        panelVisible: function(which, scope) {
                            if (angular.isDefined(scope))
                                if (angular.isUndefined(scope.panel_name)) scope.panel_name = which;
                            if (angular.isDefined(me.panel_statuses[which])) {
                                return me.panel_statuses[which];
                            }
                            return me.mainpanel == which || (angular.isDefined(scope) && scope.unpinned);
                        },
                        hidePanels: function() {
                            me.mainpanel = '';
                            me.sidebarLabels = true;
                            if (!me.exists('hs.sidebar.controller')) {
                                me.sidebarExpanded = false
                            }
                            if (!$rootScope.$$phase) $rootScope.$digest();
                            $rootScope.$broadcast('core.mainpanel_changed');
                        },
                        closePanel: function(which) {
                            if (which.unpinned) {
                                which.drag_panel.appendTo($(which.original_container));
                                which.drag_panel.css({
                                    top: 'auto',
                                    left: 'auto',
                                    position: 'relative'
                                });
                            }
                            which.unpinned = false;
                            if (which.panel_name == me.mainpanel) {
                                if (me.defaultPanel != '') {
                                    me.setMainPanel(me.defaultPanel)
                                } else {
                                    me.mainpanel = '';
                                    me.sidebarLabels = true;
                                }
                                if (!me.exists('hs.sidebar.controller')) {
                                    me.sidebarExpanded = false
                                }

                            }

                            $rootScope.$broadcast('core.mainpanel_changed');
                        },
                        exists: function(controllerName) {
                            if (angular.isDefined(me._exist_cache[controllerName])) return true;
                            if (typeof window[controllerName] == 'function') {
                                return true;
                            }
                            try {
                                $controller(controllerName);
                                me._exist_cache[controllerName] = true;
                                return true;
                            } catch (error) {
                                var t = !(error instanceof TypeError);
                                if (t) me._exist_cache[controllerName] = true;
                                return t;
                            }
                        },
                        fullScreenMap: function(element) {
                            var w = angular.element($window);
                            w.bind('resize', function() {
                                $("html").css('overflow', 'hidden');
                                $("html").css('height', '100%');
                                $('body').css('height', '100%');
                                element[0].style.height = w.height() + "px";
                                element[0].style.width = w.width() + "px";
                                $("#map").height(w.height());
                                me.updateMapSize();
                                OlMap.map.updateSize();
                            });
                            w.resize();
                        },
                        setLanguage: function(lang) {
                            switch (lang) {
                                case "cs_CZ":
                                    lang = 'cs';
                                    break;
                                case "nl_BE":
                                    lang = 'nl';
                                    break;
                            }
                            gettextCatalog.setCurrentLanguage(lang);
                        },
                        getAllScopes: function() {
                            var getScopes = function(root) {
                                var scopes = [];

                                function visit(scope) {
                                    scopes.push(scope);
                                }

                                function traverse(scope) {
                                    visit(scope);
                                    if (scope.$$nextSibling)
                                        traverse(scope.$$nextSibling);
                                    if (scope.$$childHead)
                                        traverse(scope.$$childHead);
                                }

                                traverse(root);
                                return scopes;
                            }
                            return getScopes($rootScope);
                        },
                        openStatusCreator: function() {
                            //me.panel_statuses.status_creator = true;
                            hslayers_api.gui.StatusCreator.open();
                        },
                        searchVisible: function(is) {
                            if (arguments.length > 0) {
                                me.panel_statuses['search'] = is;
                            }
                            return me.panel_statuses['search']
                        },
                        isAuthorized: function() {
                            if (angular.isDefined(window.getLRUser) && window.getLRUser() != 'guest') {
                                return true;
                            }
                            return false;
                        },
                        resetMap: function() {
                            OlMap.reset();
                            $rootScope.$broadcast('core.map_reset', {});
                        },
                        isMobile: function() {
                            if (screen.width < 800) {
                                return "mobile";
                            } else {
                                return "";
                            }
                        }
                    };

                    $templateCache.removeAll();

                    if (me.exists('hs.sidebar.controller')) {
                        me.sidebarExpanded = true;
                    }

                    if (me.defaultPanel != '') {
                        me.setMainPanel(me.defaultPanel);
                    }

                    /* HACK: https://github.com/openlayers/ol3/issues/3990 */
                    try {
                        if (typeof require('proj4') != undefined) {
                            require(['proj4'], function() {
                                window.proj4 = proj4
                            });
                        }
                    } catch (ex) {
                        require(['proj4'], function() {
                            window.proj4 = proj4
                        });
                    }

                    return me;
                },

            ]);

    })
<|endoftext|>


<commit_before>if (!window['django_select2']) {
    // This JS file can be included multiple times. So, as not to overwrite previous states, we run this only once.

    (function ($) {
        window.django_select2 = {
                MULTISEPARATOR: String.fromCharCode(31), // We use this unprintable char as separator,
                // since this can't be entered by user.
                get_url_params: function (term, page, context) {
                    var field_id = $(this).data('field_id'),
                        res = {
                            'term': term,
                            'page': page,
                            'context': context
                        };
                    if (field_id) {
                        res['field_id'] = field_id;
                    }
                    return res;
                },
                process_results: function (data, page, context) {
                    var results;
                    if (data.err && data.err.toLowerCase() === 'nil') {
                        results = {
                            'results': data.results
                        };
                        if (context) {
                            results['context'] = context;
                        }
                        if (data.more === true || data.more === false) {
                            results['more'] = data.more;
                        }
                    } else {
                        results = {'results': []};
                    }
                    if (results.results) {
                        $(this).data('results', results.results);
                    } else {
                        $(this).removeData('results');
                    }
                    return results;
                },
                onValChange: function () {
                    django_select2.updateText($(this));
                },
                prepareValText: function (vals, txts, isMultiple) {
                    var data = [];
                    $(vals).each(function (index) {
                        data.push({id: this, text: txts[index]});
                    });
                    if (isMultiple) {
                        return data;
                    } else {
                        if (data.length > 0) {
                            return data[0];
                        } else {
                            return null;
                        }
                    }
                },
                updateText: function ($e) {
                    var val = $e.select2('val'), data = $e.select2('data'), txt = $e.txt(), isMultiple = !!$e.attr('multiple'),
                        diff;

                    if (val || val === 0) { // Means value is set. A numerical 0 is also a valid value.
                        if (isMultiple) {
                            if (val.length !== txt.length) {
                                txt = [];
                                $(val).each(function (idx) {
                                    var i, value = this, id;

                                    for (i in data) {
                                        id = data [i].id;
                                        if (id instanceof String) {
                                            id = id.valueOf();
                                        }
                                        if (id == value) {
                                            txt.push(data[i].text);
                                        }
                                    }
                                });
                            }
                        } else {
                            txt = data.text;
                        }
                        $e.txt(txt);
                    } else {
                        $e.txt('');
                    }
                },
                getValText: function ($e) {
                    var val = $e.select2('val'), res = $e.data('results'), txt = $e.txt(), isMultiple = !!$e.attr('multiple'),
                        f, id = $e.attr('id');
                    if (val || val === 0) { // Means value is set. A numerical 0 is also a valid value.

                        if (!isMultiple) {
                            val = [val];
                            if (txt || txt === 0) {
                                txt = [txt];
                            }
                        }

                        if (txt === 0 || (txt && val.length === txt.length)) {
                            return [val, txt];
                        }

                        f = $e.data('userGetValText');
                        if (f) {
                            txt = f($e, val, isMultiple);
                            if (txt || txt === 0) {
                                return [val, txt];
                            }
                        }

                        if (res) {
                            txt = [];
                            $(val).each(function (idx) {
                                var i, value = this;

                                for (i in res) {
                                    if (res[i].id == value) {
                                        val[idx] = res[i].id; // To set it to correct data type.
                                        txt.push(res[i].text);
                                    }
                                }
                            });
                            if (txt || txt === 0) {
                                return [val, txt];
                            }
                        }
                    }
                    return null;
                },
                onInit: function (e, callback) {
                    e = $(e);
                    var id = e.attr('id'), data = null, val = e.select2('val');

                    if (!val && val !== 0) {
                        val = e.data('initVal');
                    }

                    if (val || val === 0) {
                        // Value is set so need to get the text.
                        data = django_select2.getValText(e);
                        if (data && data[0]) {
                            data = django_select2.prepareValText(data[0], data[1], !!e.attr('multiple'));
                        }
                    }
                    if (!data) {
                        e.val(null); // Nulling out set value so as not to confuse users.
                    }
                    callback(data); // Change for 2.3.x
                    django_select2.updateText(e);
                },
                createSearchChoice: function (term, data) {
                    if (!data || $(data).filter(function () {
                            return this.text.localeCompare(term) === 0;
                        }).length === 0) {
                        return {
                            id: term,
                            text: term
                        };
                    }
                },
                onMultipleHiddenChange: function () {
                    var $e = $(this), valContainer = $e.data('valContainer'), name = $e.data('name'), vals = $e.val();
                    valContainer.empty();
                    if (vals) {
                        vals = vals.split(django_select2.MULTISEPARATOR);
                        $(vals).each(function () {
                            var inp = $('<input type="hidden">').appendTo(valContainer);
                            inp.attr('name', name);
                            inp.val(this);
                        });
                    }
                },
                initMultipleHidden: function ($e) {
                    var valContainer;

                    $e.data('name', $e.attr('name'));
                    $e.attr('name', '');

                    valContainer = $('<div>').insertAfter($e).css({'display': 'none'});
                    $e.data('valContainer', valContainer);

                    $e.change(django_select2.onMultipleHiddenChange);
                    if ($e.val()) {
                        $e.change();
                    }
                },
                convertArrToStr: function (arr) {
                    return arr.join(django_select2.MULTISEPARATOR);
                },
                runInContextHelper: function (f, id) {
                    return function () {
                        var args = Array.prototype.slice.call(arguments, 0);
                        return f.apply($('#' + id).get(0), args);
                    }
                },
                logErr: function () {
                    if (console && console.error) {
                        args = Array.prototype.slice.call(arguments);
                        console.error.apply(console, args);
                    }
                }
            };

        (function (isDebug) { // Only used for debugging.
            if (isDebug) {
                for (var i in django_select2) {
                    var f = django_select2[i];
                    if (typeof(f) == "function") {
                        django_select2[i] = (function (i, f) {
                            return function () {
                                console.log('Function ' + i + ' called for object: ', this);
                                return f.apply(this, arguments);
                            };
                        }(i, f));
                    }
                }
            }
        }(false));

        // This sets or gets the text lables for an element. It merely takes care returing array or single
        // value, based on if element is multiple type.
        $.fn.txt = function (val) {
            if (typeof(val) !== 'undefined') {
                if (val) {
                    if (val instanceof Array) {
                        if (this.attr('multiple')) {
                            val = django_select2.convertArrToStr(val);
                        } else {
                            val = val[0]
                        }
                    }
                    this.attr('txt', val);
                } else {
                    this.removeAttr('txt');
                }
                return this;
            } else {
                val = this.attr('txt');
                if (this.attr('multiple')) {
                    if (val) {
                        val = val.split(django_select2.MULTISEPARATOR);
                    } else {
                        val = [];
                    }
                }
                return val;
            }
        };
    })(jQuery);
}
<commit_msg>Use jquery10 or jquery<commit_after>if (!window['django_select2']) {
    // This JS file can be included multiple times. So, as not to overwrite previous states, we run this only once.

    (function ($) {
        window.django_select2 = {
                MULTISEPARATOR: String.fromCharCode(31), // We use this unprintable char as separator,
                // since this can't be entered by user.
                get_url_params: function (term, page, context) {
                    var field_id = $(this).data('field_id'),
                        res = {
                            'term': term,
                            'page': page,
                            'context': context
                        };
                    if (field_id) {
                        res['field_id'] = field_id;
                    }
                    return res;
                },
                process_results: function (data, page, context) {
                    var results;
                    if (data.err && data.err.toLowerCase() === 'nil') {
                        results = {
                            'results': data.results
                        };
                        if (context) {
                            results['context'] = context;
                        }
                        if (data.more === true || data.more === false) {
                            results['more'] = data.more;
                        }
                    } else {
                        results = {'results': []};
                    }
                    if (results.results) {
                        $(this).data('results', results.results);
                    } else {
                        $(this).removeData('results');
                    }
                    return results;
                },
                onValChange: function () {
                    django_select2.updateText($(this));
                },
                prepareValText: function (vals, txts, isMultiple) {
                    var data = [];
                    $(vals).each(function (index) {
                        data.push({id: this, text: txts[index]});
                    });
                    if (isMultiple) {
                        return data;
                    } else {
                        if (data.length > 0) {
                            return data[0];
                        } else {
                            return null;
                        }
                    }
                },
                updateText: function ($e) {
                    var val = $e.select2('val'), data = $e.select2('data'), txt = $e.txt(), isMultiple = !!$e.attr('multiple'),
                        diff;

                    if (val || val === 0) { // Means value is set. A numerical 0 is also a valid value.
                        if (isMultiple) {
                            if (val.length !== txt.length) {
                                txt = [];
                                $(val).each(function (idx) {
                                    var i, value = this, id;

                                    for (i in data) {
                                        id = data [i].id;
                                        if (id instanceof String) {
                                            id = id.valueOf();
                                        }
                                        if (id == value) {
                                            txt.push(data[i].text);
                                        }
                                    }
                                });
                            }
                        } else {
                            txt = data.text;
                        }
                        $e.txt(txt);
                    } else {
                        $e.txt('');
                    }
                },
                getValText: function ($e) {
                    var val = $e.select2('val'), res = $e.data('results'), txt = $e.txt(), isMultiple = !!$e.attr('multiple'),
                        f, id = $e.attr('id');
                    if (val || val === 0) { // Means value is set. A numerical 0 is also a valid value.

                        if (!isMultiple) {
                            val = [val];
                            if (txt || txt === 0) {
                                txt = [txt];
                            }
                        }

                        if (txt === 0 || (txt && val.length === txt.length)) {
                            return [val, txt];
                        }

                        f = $e.data('userGetValText');
                        if (f) {
                            txt = f($e, val, isMultiple);
                            if (txt || txt === 0) {
                                return [val, txt];
                            }
                        }

                        if (res) {
                            txt = [];
                            $(val).each(function (idx) {
                                var i, value = this;

                                for (i in res) {
                                    if (res[i].id == value) {
                                        val[idx] = res[i].id; // To set it to correct data type.
                                        txt.push(res[i].text);
                                    }
                                }
                            });
                            if (txt || txt === 0) {
                                return [val, txt];
                            }
                        }
                    }
                    return null;
                },
                onInit: function (e, callback) {
                    e = $(e);
                    var id = e.attr('id'), data = null, val = e.select2('val');

                    if (!val && val !== 0) {
                        val = e.data('initVal');
                    }

                    if (val || val === 0) {
                        // Value is set so need to get the text.
                        data = django_select2.getValText(e);
                        if (data && data[0]) {
                            data = django_select2.prepareValText(data[0], data[1], !!e.attr('multiple'));
                        }
                    }
                    if (!data) {
                        e.val(null); // Nulling out set value so as not to confuse users.
                    }
                    callback(data); // Change for 2.3.x
                    django_select2.updateText(e);
                },
                createSearchChoice: function (term, data) {
                    if (!data || $(data).filter(function () {
                            return this.text.localeCompare(term) === 0;
                        }).length === 0) {
                        return {
                            id: term,
                            text: term
                        };
                    }
                },
                onMultipleHiddenChange: function () {
                    var $e = $(this), valContainer = $e.data('valContainer'), name = $e.data('name'), vals = $e.val();
                    valContainer.empty();
                    if (vals) {
                        vals = vals.split(django_select2.MULTISEPARATOR);
                        $(vals).each(function () {
                            var inp = $('<input type="hidden">').appendTo(valContainer);
                            inp.attr('name', name);
                            inp.val(this);
                        });
                    }
                },
                initMultipleHidden: function ($e) {
                    var valContainer;

                    $e.data('name', $e.attr('name'));
                    $e.attr('name', '');

                    valContainer = $('<div>').insertAfter($e).css({'display': 'none'});
                    $e.data('valContainer', valContainer);

                    $e.change(django_select2.onMultipleHiddenChange);
                    if ($e.val()) {
                        $e.change();
                    }
                },
                convertArrToStr: function (arr) {
                    return arr.join(django_select2.MULTISEPARATOR);
                },
                runInContextHelper: function (f, id) {
                    return function () {
                        var args = Array.prototype.slice.call(arguments, 0);
                        return f.apply($('#' + id).get(0), args);
                    }
                },
                logErr: function () {
                    if (console && console.error) {
                        args = Array.prototype.slice.call(arguments);
                        console.error.apply(console, args);
                    }
                }
            };

        (function (isDebug) { // Only used for debugging.
            if (isDebug) {
                for (var i in django_select2) {
                    var f = django_select2[i];
                    if (typeof(f) == "function") {
                        django_select2[i] = (function (i, f) {
                            return function () {
                                console.log('Function ' + i + ' called for object: ', this);
                                return f.apply(this, arguments);
                            };
                        }(i, f));
                    }
                }
            }
        }(false));

        // This sets or gets the text lables for an element. It merely takes care returing array or single
        // value, based on if element is multiple type.
        $.fn.txt = function (val) {
            if (typeof(val) !== 'undefined') {
                if (val) {
                    if (val instanceof Array) {
                        if (this.attr('multiple')) {
                            val = django_select2.convertArrToStr(val);
                        } else {
                            val = val[0]
                        }
                    }
                    this.attr('txt', val);
                } else {
                    this.removeAttr('txt');
                }
                return this;
            } else {
                val = this.attr('txt');
                if (this.attr('multiple')) {
                    if (val) {
                        val = val.split(django_select2.MULTISEPARATOR);
                    } else {
                        val = [];
                    }
                }
                return val;
            }
        };
    })(jQuery10 || jQuery);
}
<|endoftext|>


<commit_before>(function (requestAnimationFrame, active) {
    // create a sprite svg element and hide it somewhere
    var createSpriteElement = function (url, svgText) {
        var wrap            = document.createElement('span');
        wrap.innerHTML      = svgText;
        wrap.style.display  = 'none';

        // append
        document.body.appendChild(wrap);
        return;
    };

    // load sprite svg using AJAX
    var loadSprite = function (file, cb) {
        var x = new (XMLHttpRequest || ActiveXObject)('MSXML2.XMLHTTP.3.0');
        x.open('GET', file, 1);
        //
        x.onreadystatechange = function () {
            if (x.readyState > 3) {
                createSpriteElement(file, x.responseText);
                cb();
            }
            return;
        };
        x.send();
        return file;
    };

    var modifyElement = function (e, uri) {
        return (function (symbol) {
            if (!symbol) {
                return void(0);
            } else {
                e.parentNode.setAttribute('viewBox', symbol.getAttribute('viewBox'));
                e.parentNode.replaceChild((function (nodes, frag) {
                    Array.prototype.forEach.call(nodes, function (n) {
                        frag.appendChild(n.cloneNode(true));
                    });
                    return frag;
                })(symbol.childNodes, document.createDocumentFragment()), e);
                return void(0);
            }
        })(document.getElementById(uri));
    };

    var createScanner = function (loaded) {
        return function () {
            (function scanEle(n, l, counter) {
                return counter >= n.length      ?

                    (function () {
                        // setup next scanner
                        requestAnimationFrame(createScanner(l));
                        return void(0);
                    })()                        :

                    (function (href) {
                        return (href[0] == '#')                             ?
                            modifyElement(n[counter], href.substring(1))    :
                            (function (parts) {
                                return (function (uri, hash) {
                                    // if the file hasn't been loaded before,
                                    // load it into DOM
                                    scanEle(n                               ,
                                        l.indexOf(uri) > -1                 ?
                                        (function () {
                                            modifyElement(n[counter], hash);
                                            return l;
                                        })()                                :
                                        (function (e) {
                                            return l.concat([
                                                loadSprite(uri, function () {
                                                    // now modify the e element
                                                    return modifyElement(e, hash);
                                                })
                                            ]);
                                        })(n[counter])                      ,
                                        (counter + 1)
                                    );
                                    return void(0);
                                })(parts[0], parts[1]);

                            })(href.split('#'));

                    })(n[counter].getAttribute('xlink:href'));

            })(document.getElementsByTagName('use'), loaded, 0);
        };
    };

    return active ? createScanner([])() : void(0);
})(
    (window.requestAnimationFrame || function (fn) {
            window.setTimeout(fn, 300);
        }),
    (
        /MSIE\b/.test(navigator.userAgent)       ||
	    /Trident\b/.test(navigator.userAgent)    ||
        /AppleWebKit\/(\d+)/.test(navigator.userAgent)
    )
);
<commit_msg>Prepend svg to body instead of append<commit_after>(function (requestAnimationFrame, active) {
    // create a sprite svg element and hide it somewhere
    var createSpriteElement = function (url, svgText) {
        var wrap            = document.createElement('span');
        wrap.innerHTML      = svgText;
        wrap.style.display  = 'none';

        // append
        document.body.insertBefore(wrap, document.body.firstChild);
        return;
    };

    // load sprite svg using AJAX
    var loadSprite = function (file, cb) {
        var x = new (XMLHttpRequest || ActiveXObject)('MSXML2.XMLHTTP.3.0');
        x.open('GET', file, 1);
        //
        x.onreadystatechange = function () {
            if (x.readyState > 3) {
                createSpriteElement(file, x.responseText);
                cb();
            }
            return;
        };
        x.send();
        return file;
    };

    var modifyElement = function (e, uri) {
        return (function (symbol) {
            if (!symbol) {
                return void(0);
            } else {
                e.parentNode.setAttribute('viewBox', symbol.getAttribute('viewBox'));
                e.parentNode.replaceChild((function (nodes, frag) {
                    Array.prototype.forEach.call(nodes, function (n) {
                        frag.appendChild(n.cloneNode(true));
                    });
                    return frag;
                })(symbol.childNodes, document.createDocumentFragment()), e);
                return void(0);
            }
        })(document.getElementById(uri));
    };

    var createScanner = function (loaded) {
        return function () {
            (function scanEle(n, l, counter) {
                return counter >= n.length      ?

                    (function () {
                        // setup next scanner
                        requestAnimationFrame(createScanner(l));
                        return void(0);
                    })()                        :

                    (function (href) {
                        return (href[0] == '#')                             ?
                            modifyElement(n[counter], href.substring(1))    :
                            (function (parts) {
                                return (function (uri, hash) {
                                    // if the file hasn't been loaded before,
                                    // load it into DOM
                                    scanEle(n                               ,
                                        l.indexOf(uri) > -1                 ?
                                        (function () {
                                            modifyElement(n[counter], hash);
                                            return l;
                                        })()                                :
                                        (function (e) {
                                            return l.concat([
                                                loadSprite(uri, function () {
                                                    // now modify the e element
                                                    return modifyElement(e, hash);
                                                })
                                            ]);
                                        })(n[counter])                      ,
                                        (counter + 1)
                                    );
                                    return void(0);
                                })(parts[0], parts[1]);

                            })(href.split('#'));

                    })(n[counter].getAttribute('xlink:href'));

            })(document.getElementsByTagName('use'), loaded, 0);
        };
    };

    return active ? createScanner([])() : void(0);
})(
    (window.requestAnimationFrame || function (fn) {
            window.setTimeout(fn, 300);
        }),
    (
        /MSIE\b/.test(navigator.userAgent)       ||
	    /Trident\b/.test(navigator.userAgent)    ||
        /AppleWebKit\/(\d+)/.test(navigator.userAgent)
    )
);
<|endoftext|>