<commit_before>'use strict';

const NamedMapMapConfigProvider = require('../models/mapconfig/provider/named-map-provider');
const templateName = require('../backends/template_maps').templateName;

const LruCache = require("lru-cache");

const TEN_MINUTES_IN_MILLISECONDS = 1000 * 60 * 10;
const ACTIONS = ['update', 'delete'];

function NamedMapProviderCache(
    templateMaps,
    pgConnection,
    metadataBackend,
    userLimitsBackend,
    mapConfigAdapter,
    affectedTablesCache
) {
    this.templateMaps = templateMaps;
    this.pgConnection = pgConnection;
    this.metadataBackend = metadataBackend;
    this.userLimitsBackend = userLimitsBackend;
    this.mapConfigAdapter = mapConfigAdapter;
    this.affectedTablesCache = affectedTablesCache;

    this.providerCache = new LruCache({ max: 2000, maxAge: TEN_MINUTES_IN_MILLISECONDS });

    ACTIONS.forEach(action => templateMaps.on(action, (...args) => this.invalidate(...args)));
}

module.exports = NamedMapProviderCache;

NamedMapProviderCache.prototype.get = function(user, templateId, config, authToken, params, callback) {
    const namedMapKey = createNamedMapKey(user, templateId);
    const namedMapProviders = this.providerCache.get(namedMapKey) || {};
    const providerKey = createProviderKey(config, authToken, params);

    if (namedMapProviders.hasOwnProperty(providerKey)) {
        return callback(null, namedMapProviders[providerKey]);
    }

    namedMapProviders[providerKey] = new NamedMapMapConfigProvider(
        this.templateMaps,
        this.pgConnection,
        this.metadataBackend,
        this.userLimitsBackend,
        this.mapConfigAdapter,
        this.affectedTablesCache,
        user,
        templateId,
        config,
        authToken,
        params
    );

    this.providerCache.set(namedMapKey, namedMapProviders);

    return callback(null, namedMapProviders[providerKey]);
};

NamedMapProviderCache.prototype.invalidate = function(user, templateId) {
    this.providerCache.del(createNamedMapKey(user, templateId));
};

function createNamedMapKey(user, templateId) {
    return user + ':' + templateName(templateId);
}

const providerKeyTpl = ctx => `${ctx.authToken}:${ctx.configHash}:${ctx.format}:${ctx.layer}:${ctx.scale_factor}`;

function createProviderKey(config, authToken, params) {
    const defaults = {
        authToken: authToken || '',
        configHash: NamedMapMapConfigProvider.configHash(config),
        layer: '',
        format: '',
        scale_factor: 1
    };
    const ctx = Object.assign({}, defaults, params);

    return providerKeyTpl(ctx);
}
<commit_msg>Use template string<commit_after>'use strict';

const LruCache = require("lru-cache");

const NamedMapMapConfigProvider = require('../models/mapconfig/provider/named-map-provider');
const { templateName } = require('../backends/template_maps');

const TEN_MINUTES_IN_MILLISECONDS = 1000 * 60 * 10;
const ACTIONS = ['update', 'delete'];

function NamedMapProviderCache(
    templateMaps,
    pgConnection,
    metadataBackend,
    userLimitsBackend,
    mapConfigAdapter,
    affectedTablesCache
) {
    this.templateMaps = templateMaps;
    this.pgConnection = pgConnection;
    this.metadataBackend = metadataBackend;
    this.userLimitsBackend = userLimitsBackend;
    this.mapConfigAdapter = mapConfigAdapter;
    this.affectedTablesCache = affectedTablesCache;

    this.providerCache = new LruCache({ max: 2000, maxAge: TEN_MINUTES_IN_MILLISECONDS });

    ACTIONS.forEach(action => templateMaps.on(action, (...args) => this.invalidate(...args)));
}

module.exports = NamedMapProviderCache;

NamedMapProviderCache.prototype.get = function(user, templateId, config, authToken, params, callback) {
    const namedMapKey = createNamedMapKey(user, templateId);
    const namedMapProviders = this.providerCache.get(namedMapKey) || {};
    const providerKey = createProviderKey(config, authToken, params);

    if (namedMapProviders.hasOwnProperty(providerKey)) {
        return callback(null, namedMapProviders[providerKey]);
    }

    namedMapProviders[providerKey] = new NamedMapMapConfigProvider(
        this.templateMaps,
        this.pgConnection,
        this.metadataBackend,
        this.userLimitsBackend,
        this.mapConfigAdapter,
        this.affectedTablesCache,
        user,
        templateId,
        config,
        authToken,
        params
    );

    this.providerCache.set(namedMapKey, namedMapProviders);

    return callback(null, namedMapProviders[providerKey]);
};

NamedMapProviderCache.prototype.invalidate = function(user, templateId) {
    this.providerCache.del(createNamedMapKey(user, templateId));
};

function createNamedMapKey (user, templateId) {
    return `${user}:${templateName(templateId)}`;
}

const providerKeyTpl = ctx => `${ctx.authToken}:${ctx.configHash}:${ctx.format}:${ctx.layer}:${ctx.scale_factor}`;

function createProviderKey (config, authToken, params) {
    const defaults = {
        authToken: authToken || '',
        configHash: NamedMapMapConfigProvider.configHash(config),
        layer: '',
        format: '',
        scale_factor: 1
    };
    const ctx = Object.assign({}, defaults, params);

    return providerKeyTpl(ctx);
}
<|endoftext|>


<commit_before>import {Icon} from '@conveyal/woonerf'
import React, { Component, PropTypes } from 'react'

import AccessLeg from './access-leg'
import TransitLeg from './transit-leg'
import { isTransit } from '../../util/itinerary'

export default class ItineraryDetails extends Component {

  static propTypes = {
    itinerary: PropTypes.object
  }
  render () {
    const { itinerary, activeLeg, activeStep, setActiveLeg, setActiveStep } = this.props
    return (

        {itinerary.legs.map((leg, index) => {
          const legIsActive = activeLeg === index
          return isTransit(leg.mode)
          ? <TransitLeg
            active={legIsActive}
            index={index}
            key={index}
            leg={leg}
            setActiveLeg={setActiveLeg} />
          : <AccessLeg
            active={legIsActive}
            activeStep={activeStep}
            index={index}
            key={index}
            leg={leg}
            setActiveLeg={setActiveLeg}
            setActiveStep={setActiveStep} />
        })}

    )
  }
}
<commit_msg>removed unused Icon<commit_after>import React, { Component, PropTypes } from 'react'

import AccessLeg from './access-leg'
import TransitLeg from './transit-leg'
import { isTransit } from '../../util/itinerary'

export default class ItineraryDetails extends Component {

  static propTypes = {
    itinerary: PropTypes.object
  }
  render () {
    const { itinerary, activeLeg, activeStep, setActiveLeg, setActiveStep } = this.props
    return (

        {itinerary.legs.map((leg, index) => {
          const legIsActive = activeLeg === index
          return isTransit(leg.mode)
          ? <TransitLeg
            active={legIsActive}
            index={index}
            key={index}
            leg={leg}
            setActiveLeg={setActiveLeg} />
          : <AccessLeg
            active={legIsActive}
            activeStep={activeStep}
            index={index}
            key={index}
            leg={leg}
            setActiveLeg={setActiveLeg}
            setActiveStep={setActiveStep} />
        })}

    )
  }
}
<|endoftext|>


<commit_before>/** @babel */
/** @jsx etch.dom */

import etch from 'etch'
import Tether from 'tether'
import ModelObserver from '../models/model-observer'
import BranchView from '../views/branch-view'
import BranchMenuView from '../views/branch-menu-view'
import PushPullView from '../views/push-pull-view'
import PushPullMenuView from '../views/push-pull-menu-view'
import ChangedFilesCountView from '../views/changed-files-count-view'

export default class StatusBarTileController {
  constructor (props) {
    this.props = props
    this.checkout = this.checkout.bind(this)
    this.push = this.push.bind(this)
    this.pull = this.pull.bind(this)
    this.fetch = this.fetch.bind(this)
    this.toggleBranchMenu = this.toggleBranchMenu.bind(this)
    this.togglePushPullMenu = this.togglePushPullMenu.bind(this)
    this.branchMenuView = null
    this.pushPullMenuView = null
    this.showingBranchMenuView = false
    this.showingPushPllMenuView = false
    this.repositoryObserver = new ModelObserver({
      fetchData: this.fetchRepositoryData.bind(this),
      didUpdate: () => etch.update(this)
    })
    this.repositoryObserver.setActiveModel(props.repository)
    etch.initialize(this)
  }

  update (props) {
    this.props = Object.assign({}, this.props, props)
    this.repositoryObserver.setActiveModel(props.repository)
    return etch.update(this)
  }

  render () {
    const modelData = this.repositoryObserver.getActiveModelData()

    const pushPullView = (
      <PushPullView
        ref='pushPullView'
        {...modelData}
        didClick={this.togglePushPullMenu}
      />
    )

    if (modelData) {
      return (

          { modelData.remoteName ? pushPullView :  }
          <BranchView
            ref="branchView"
            {...modelData}
            workspace={this.props.workspace}
            checkout={this.checkout}
            didClick={this.toggleBranchMenu} />
          <ChangedFilesCountView
            ref="changedFilesCountView"
            {...modelData}
            didClick={this.props.toggleGitPanel} />

      )
    } else {
      return

    }
  }

  writeAfterUpdate () {
    const modelData = this.repositoryObserver.getActiveModelData()
    if (modelData) {
      if (this.branchMenuView) {
        this.branchMenuView.update(modelData)
      } else {
        this.branchMenuView = new BranchMenuView({
          ...modelData,
          workspace: this.props.workspace,
          checkout: this.checkout
        })
      }

      if (this.pushPullMenuView) {
        this.pushPullMenuView.update(modelData)
      } else {
        this.pushPullMenuView = new PushPullMenuView({
          ...modelData,
          workspace: this.props.workspace,
          push: this.push,
          pull: this.pull,
          fetch: this.fetch
        })
      }
    }
  }

  getActiveRepository () {
    return this.repositoryObserver.getActiveModel()
  }

  async fetchRepositoryData (repository) {
    const branchName = await repository.getCurrentBranch()
    const remoteName = await repository.getRemote(branchName)
    const changedFilesCount = await this.fetchChangedFilesCount(repository)
    const data = {
      branchName,
      remoteName,
      changedFilesCount,
      branches: await repository.getBranches()
    }
    if (remoteName) {
      data.aheadCount = await repository.getAheadCount(branchName),
      data.behindCount = await repository.getBehindCount(branchName),
      data.pullDisabled = changedFilesCount > 0
    }
    return data
  }

  async fetchChangedFilesCount (repository) {
    const changedFiles = new Set()
    for (let filePatch of await repository.getUnstagedChanges()) {
      changedFiles.add(filePatch.getPath())
    }
    for (let filePatch of await repository.getStagedChanges()) {
      changedFiles.add(filePatch.getPath())
    }
    return changedFiles.size
  }

  getLastModelDataRefreshPromise () {
    return this.repositoryObserver.getLastModelDataRefreshPromise()
  }

  checkout (branchName, options) {
    return this.getActiveRepository().checkout(branchName, options)
  }

  push () {
    return this.getActiveRepository().push(this.branchName)
  }

  pull () {
    const {pullDisabled} = this.repositoryObserver.getActiveModelData()
    return pullDisabled ? Promise.resolve() : this.getActiveRepository().pull(this.branchName)
  }

  fetch () {
    return this.getActiveRepository().fetch(this.branchName)
  }

  toggleBranchMenu (event) {
    event && event.stopPropagation()

    if (this.branchMenuView) {
      if (this.showingBranchMenuView) {
        this.hideBranchMenu()
      } else {
        this.showBranchMenu()
      }
    }
  }

  hideBranchMenu () {
    this.tooltipDisposable.dispose()
    this.showingBranchMenuView = false
  }

  showBranchMenu () {
    const menuElement = this.branchMenuView.element
    this.tooltipDisposable =
      atom.tooltips.add(this.refs.branchView.element, {
        tooltipElement: menuElement,
        tooltipClass: 'git-StatusBarTileController-tooltipMenu',
        trigger: 'manual',
        delay: { show: 0, hide: 100 },
      })

    const hideBranchMenu = (event) => {
      if (event.target !== menuElement && !menuElement.contains(event.target)) {
        window.removeEventListener('click', hideBranchMenu, true)
        this.hideBranchMenu()
      }
    }
    window.addEventListener('click', hideBranchMenu, true)
    this.showingBranchMenuView = true
  }

  togglePushPullMenu (event) {
    event && event.stopPropagation()

    if (this.pushPullMenuView) {
      if (this.showingPushPullMenuView) {
        this.hidePushPullMenu()
      } else {
        this.showPushPullMenu()
      }
    }
  }

  hidePushPullMenu () {
    this.tooltipDisposable.dispose()
    this.showingPushPullMenuView = false
  }

  showPushPullMenu () {
    const menuElement = this.pushPullMenuView.element
    this.tooltipDisposable =
      atom.tooltips.add(this.refs.pushPullView.element, {
        tooltipElement: menuElement,
        tooltipClass: 'git-StatusBarTileController-tooltipMenu',
        trigger: 'manual',
        delay: { show: 0, hide: 100 },
      })

    const hidePushPullMenu = (event) => {
      if (event.target !== menuElement && !menuElement.contains(event.target)) {
        window.removeEventListener('click', hidePushPullMenu, true)
        this.hidePushPullMenu()
      }
    }
    window.addEventListener('click', hidePushPullMenu, true)
    this.showingPushPullMenuView = true
  }

  destroy () {
    if (this.showingBranchMenuView) this.toggleBranchMenu()
    if (this.showingPushPullMenuView) this.togglePushPullMenu()
  }
}
<commit_msg>WIP fix push/pull/fetch. Write tests. For some reason pull doesn't work after resetting<commit_after>/** @babel */
/** @jsx etch.dom */

import etch from 'etch'
import Tether from 'tether'
import ModelObserver from '../models/model-observer'
import BranchView from '../views/branch-view'
import BranchMenuView from '../views/branch-menu-view'
import PushPullView from '../views/push-pull-view'
import PushPullMenuView from '../views/push-pull-menu-view'
import ChangedFilesCountView from '../views/changed-files-count-view'

export default class StatusBarTileController {
  constructor (props) {
    this.props = props
    this.checkout = this.checkout.bind(this)
    this.push = this.push.bind(this)
    this.pull = this.pull.bind(this)
    this.fetch = this.fetch.bind(this)
    this.toggleBranchMenu = this.toggleBranchMenu.bind(this)
    this.togglePushPullMenu = this.togglePushPullMenu.bind(this)
    this.branchMenuView = null
    this.pushPullMenuView = null
    this.showingBranchMenuView = false
    this.showingPushPllMenuView = false
    this.repositoryObserver = new ModelObserver({
      fetchData: this.fetchRepositoryData.bind(this),
      didUpdate: () => etch.update(this)
    })
    this.repositoryObserver.setActiveModel(props.repository)
    etch.initialize(this)
  }

  update (props) {
    this.props = Object.assign({}, this.props, props)
    this.repositoryObserver.setActiveModel(props.repository)
    return etch.update(this)
  }

  render () {
    const modelData = this.repositoryObserver.getActiveModelData()

    const pushPullView = (
      <PushPullView
        ref='pushPullView'
        {...modelData}
        didClick={this.togglePushPullMenu}
      />
    )

    if (modelData) {
      return (

          { modelData.remoteName ? pushPullView :  }
          <BranchView
            ref="branchView"
            {...modelData}
            workspace={this.props.workspace}
            checkout={this.checkout}
            didClick={this.toggleBranchMenu} />
          <ChangedFilesCountView
            ref="changedFilesCountView"
            {...modelData}
            didClick={this.props.toggleGitPanel} />

      )
    } else {
      return

    }
  }

  writeAfterUpdate () {
    const modelData = this.repositoryObserver.getActiveModelData()
    if (modelData) {
      if (this.branchMenuView) {
        this.branchMenuView.update(modelData)
      } else {
        this.branchMenuView = new BranchMenuView({
          ...modelData,
          workspace: this.props.workspace,
          checkout: this.checkout
        })
      }

      if (this.pushPullMenuView) {
        this.pushPullMenuView.update(modelData)
      } else {
        this.pushPullMenuView = new PushPullMenuView({
          ...modelData,
          workspace: this.props.workspace,
          push: this.push,
          pull: this.pull,
          fetch: this.fetch
        })
      }
    }
  }

  getActiveRepository () {
    return this.repositoryObserver.getActiveModel()
  }

  async fetchRepositoryData (repository) {
    const branchName = await repository.getCurrentBranch()
    const remoteName = await repository.getRemote(branchName)
    const changedFilesCount = await this.fetchChangedFilesCount(repository)
    const data = {
      branchName,
      remoteName,
      changedFilesCount,
      branches: await repository.getBranches()
    }
    if (remoteName) {
      data.aheadCount = await repository.getAheadCount(branchName),
      data.behindCount = await repository.getBehindCount(branchName),
      data.pullDisabled = changedFilesCount > 0
    }
    return data
  }

  async fetchChangedFilesCount (repository) {
    const changedFiles = new Set()
    for (let filePatch of await repository.getUnstagedChanges()) {
      changedFiles.add(filePatch.getPath())
    }
    for (let filePatch of await repository.getStagedChanges()) {
      changedFiles.add(filePatch.getPath())
    }
    return changedFiles.size
  }

  getLastModelDataRefreshPromise () {
    return this.repositoryObserver.getLastModelDataRefreshPromise()
  }

  checkout (branchName, options) {
    return this.getActiveRepository().checkout(branchName, options)
  }

  push () {
    const {branchName} = this.repositoryObserver.getActiveModelData()
    return this.getActiveRepository().push(branchName)
  }

  pull () {
    const {pullDisabled, branchName} = this.repositoryObserver.getActiveModelData()
    console.log('status bar pull');
    return pullDisabled ? Promise.resolve() : this.getActiveRepository().pull(branchName)
  }

  fetch () {
    const {branchName} = this.repositoryObserver.getActiveModelData()
    return this.getActiveRepository().fetch(branchName)
  }

  toggleBranchMenu (event) {
    event && event.stopPropagation()

    if (this.branchMenuView) {
      if (this.showingBranchMenuView) {
        this.hideBranchMenu()
      } else {
        this.showBranchMenu()
      }
    }
  }

  hideBranchMenu () {
    this.tooltipDisposable.dispose()
    this.showingBranchMenuView = false
  }

  showBranchMenu () {
    const menuElement = this.branchMenuView.element
    this.tooltipDisposable =
      atom.tooltips.add(this.refs.branchView.element, {
        tooltipElement: menuElement,
        tooltipClass: 'git-StatusBarTileController-tooltipMenu',
        trigger: 'manual',
        delay: { show: 0, hide: 100 },
      })

    const hideBranchMenu = (event) => {
      if (event.target !== menuElement && !menuElement.contains(event.target)) {
        window.removeEventListener('click', hideBranchMenu, true)
        this.hideBranchMenu()
      }
    }
    window.addEventListener('click', hideBranchMenu, true)
    this.showingBranchMenuView = true
  }

  togglePushPullMenu (event) {
    event && event.stopPropagation()

    if (this.pushPullMenuView) {
      if (this.showingPushPullMenuView) {
        this.hidePushPullMenu()
      } else {
        this.showPushPullMenu()
      }
    }
  }

  hidePushPullMenu () {
    this.tooltipDisposable.dispose()
    this.showingPushPullMenuView = false
  }

  showPushPullMenu () {
    const menuElement = this.pushPullMenuView.element
    this.tooltipDisposable =
      atom.tooltips.add(this.refs.pushPullView.element, {
        tooltipElement: menuElement,
        tooltipClass: 'git-StatusBarTileController-tooltipMenu',
        trigger: 'manual',
        delay: { show: 0, hide: 100 },
      })

    const hidePushPullMenu = (event) => {
      if (event.target !== menuElement && !menuElement.contains(event.target)) {
        window.removeEventListener('click', hidePushPullMenu, true)
        this.hidePushPullMenu()
      }
    }
    window.addEventListener('click', hidePushPullMenu, true)
    this.showingPushPullMenuView = true
  }

  destroy () {
    if (this.showingBranchMenuView) this.toggleBranchMenu()
    if (this.showingPushPullMenuView) this.togglePushPullMenu()
  }
}
<|endoftext|>


<commit_before>import StringManipulator from 'src/database/stringManipulation';
import exceptions from 'src/database/exceptions';
import constants from 'src/database/constants';
import DateTime from 'src/database/generated-data/dateTime';

const alasql = require('alasql');

const stringManipulator = new StringManipulator();
const dateTime = new DateTime();

function getDataOutOfAlasql(data) {
  return Object.values(data[0][0])[0];
}

function getSecondDataOutOfAlasql(data) {
  return Object.values(data[0][0])[1];
}

function getArray(data) {
  return data[0];
}

function getCurrentFilePath(fileId) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('SELECT ', constants.HEADER_FILE_MANAGER_PATH,
                                                   ' FROM ', constants.ENTITIES_FILE_MANAGER,
                                                   ' WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                   ' = ', fileId)])
    .then(filePath => resolve(filePath))
    .catch(sqlErr => reject(sqlErr))
  );
}

function getCurrentFolderPath(folderId) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('SELECT ', constants.HEADER_FOLDER_PATH,
                                                   ' FROM ', constants.ENTITIES_FOLDER,
                                                   ' WHERE ', constants.HEADER_FOLDER_FOLDER_ID,
                                                   ' = ', folderId)])
    .then(folderPath => resolve(folderPath))
    .catch(sqlErr => reject(sqlErr))
  );
}

// duplicate private function to help with cascadeChangeFilePath
function changeSingleFilePath(fileId, newPath) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('UPDATE ', constants.ENTITIES_FILE_MANAGER,
                                                   ' SET ', constants.HEADER_FILE_MANAGER_PATH,
                                                   ' = "', newPath,
                                                   '" WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                   ' = ', fileId)])
    .then(() => resolve())
    .catch(sqlError => reject(sqlError))
  );
}

function cascadeChangeFilePath(index, prevBasePath, newBasePath, fileArr) {
  return new Promise((resolve, reject) => {
    if (index >= fileArr.length) {
      return true;
    }
    const fileToChangePathIndex = Object.values(fileArr[index])[0];
    let newPath;
    return getCurrentFilePath(fileToChangePathIndex)
    .then((currentFilePath) => {
      const childPath = currentFilePath.toString().split(prevBasePath)[1];
      newPath = stringManipulator.stringConcat(newBasePath, childPath);
      return changeSingleFilePath(fileToChangePathIndex, newPath)
      .catch(sqlErr => reject(sqlErr));
    })
    .then(() => {
      cascadeChangeFilePath(index + 1, prevBasePath, newBasePath, fileArr)
      .catch(err => reject(err));
      resolve();
    })
    .catch(err => reject(err));
  });
}

function changeSingleFolderPath(folderId, newPath) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('UPDATE ', constants.ENTITIES_FOLDER,
                                                   ' SET ', constants.HEADER_FOLDER_PATH,
                                                   ' = "', newPath,
                                                   '" WHERE ', constants.HEADER_FOLDER_FOLDER_ID,
                                                   ' = ', folderId)])
    .then(() => resolve())
    .catch(sqlError => reject(sqlError))
  );
}

function changeSingleFolderName(folderId, newFolderName) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('UPDATE ', constants.ENTITIES_FOLDER,
                                                   ' SET ', constants.HEADER_FOLDER_FOLDER_NAME,
                                                   ' = "', newFolderName,
                                                   '" WHERE ', constants.HEADER_FOLDER_FOLDER_ID,
                                                   ' = ', folderId)])
    .then(() => resolve())
    .catch(sqlError => reject(sqlError))
  );
}

}

export default function sqlCommands() {
  this.linkDatabaseToIndexedDB = function linkDatabaseToIndexedDB(databaseName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        const databaseRequestStr = stringManipulator.stringConcat(
          'CREATE INDEXEDDB DATABASE IF NOT EXISTS ', databaseName, ';',
          'ATTACH INDEXEDDB DATABASE ', databaseName, ';',
          'USE ', databaseName, ';');
        return alasql.promise([databaseRequestStr])
          .then(data => resolve(true))
          .catch(sqlError => reject(sqlError));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.getFullTableData = function getFullTableData(tableName) {
    // ensure working in browsers that support Promise
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', tableName)])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError)));
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.createTable = function createTable(sqlStatement) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('CREATE TABLE IF NOT EXISTS ', sqlStatement)])
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.insertContent = function insertContent(tableName, alasqlArray) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise(stringManipulator.stringConcat('INSERT INTO ', tableName,
                                                       ' VALUES ?'), alasqlArray)
        .then(data => resolve(data))
        .catch(sqlError => reject(sqlError)));
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.partialSearchFileName = function partialSearchFileName(searchString) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', constants.ENTITIES_FILE_MANAGER,
                                                       ' WHERE ', constants.HEADER_FILE_MANAGER_FILE_NAME,
                                                       ' LIKE "%', searchString, '%"')])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };
  this.getMaxFileId = function getMaxFileId() {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT max(', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                       ') FROM ', constants.ENTITIES_FILE_MANAGER)])
        .then((data) => {
          const maxFileId = getDataOutOfAlasql(data);
          if (typeof maxFileId === 'number') {
            resolve(maxFileId);
          } else {
            resolve(-1);
          }
        }).catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };
  this.getMaxFolderId = function getMaxFolderId() {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT MAX(', constants.HEADER_FOLDER_FOLDER_ID,
                                                       ') FROM ', constants.ENTITIES_FOLDER)])
        .then((data) => {
          const maxFolderId = getDataOutOfAlasql(data);
          if (typeof maxFolderId === 'number') {
            resolve(maxFolderId);
          } else {
            resolve(0);
          }
        }).catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.partialSearchFolderName = function partialSearchFolderName(searchString) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', constants.ENTITIES_FOLDER,
                                                       ' WHERE ', constants.HEADER_FOLDER_FOLDER_NAME,
                                                       ' LIKE "%', searchString, '%"')])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.loadFilesFromFolder = function loadFilesFromFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', constants.ENTITIES_FILE_MANAGER,
                                                       ' WHERE ', constants.HEADER_FILE_MANAGER_FOLDER_ID,
                                                       ' = ', folderId)])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.loadFoldersFromFolder = function loadFoldersFromFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', constants.ENTITIES_FOLDER,
                                                       ' WHERE ', constants.HEADER_FOLDER_PARENT_FOLDER_ID,
                                                       ' = ', folderId)])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.loadFile = function loadFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT ', constants.HEADER_FILE_MANAGER_FILE_MARKDOWN,
                                                       ' FROM ', constants.ENTITIES_FILE_MANAGER,
                                                       ' WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                       ' = ', fileId)])
        .then(data => resolve(getDataOutOfAlasql(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.saveFile = function saveFile(fileId, markdownFile) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        .then(() => {
          const currentDateTime = dateTime.getCurrentDateTime();
          alasql.promise([stringManipulator.stringConcat('UPDATE ', constants.ENTITIES_FILE_MANAGER,
                                                         ' SET ', constants.HEADER_FILE_MANAGER_LAST_MODIFIED_DATE,
                                                         ' = "', currentDateTime,
                                                         '" WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                         ' = ', fileId)])
          .catch(sqlError => reject(sqlError));
        })
        .then(() => resolve(true))
        .catch(sqlErr => reject(sqlErr));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.deleteFile = function deleteFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('DELETE FROM ', constants.ENTITIES_FILE_MANAGER,
                                                       ' WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                       ' = ', fileId)])
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.deleteFolder = function deleteFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('DELETE FROM ', constants.ENTITIES_FOLDER,
                                                       ' WHERE ', constants.HEADER_FOLDER_FOLDER_ID,
                                                       ' = ', folderId)])
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  // external library not functioning so I cannot do anything here
  this.deleteTable = function deleteTable(tableName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('DROP TABLE IF EXISTS ', tableName)])
        .then(isSuccess => resolve(isSuccess))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };
}
<commit_msg>Add cascadeChangeFolderPath function to sqlCommands.js<commit_after>import StringManipulator from 'src/database/stringManipulation';
import exceptions from 'src/database/exceptions';
import constants from 'src/database/constants';
import DateTime from 'src/database/generated-data/dateTime';

const alasql = require('alasql');

const stringManipulator = new StringManipulator();
const dateTime = new DateTime();

function getDataOutOfAlasql(data) {
  return Object.values(data[0][0])[0];
}

function getSecondDataOutOfAlasql(data) {
  return Object.values(data[0][0])[1];
}

function getArray(data) {
  return data[0];
}

function getCurrentFilePath(fileId) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('SELECT ', constants.HEADER_FILE_MANAGER_PATH,
                                                   ' FROM ', constants.ENTITIES_FILE_MANAGER,
                                                   ' WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                   ' = ', fileId)])
    .then(filePath => resolve(filePath))
    .catch(sqlErr => reject(sqlErr))
  );
}

function getCurrentFolderPath(folderId) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('SELECT ', constants.HEADER_FOLDER_PATH,
                                                   ' FROM ', constants.ENTITIES_FOLDER,
                                                   ' WHERE ', constants.HEADER_FOLDER_FOLDER_ID,
                                                   ' = ', folderId)])
    .then(folderPath => resolve(folderPath))
    .catch(sqlErr => reject(sqlErr))
  );
}

// duplicate private function to help with cascadeChangeFilePath
function changeSingleFilePath(fileId, newPath) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('UPDATE ', constants.ENTITIES_FILE_MANAGER,
                                                   ' SET ', constants.HEADER_FILE_MANAGER_PATH,
                                                   ' = "', newPath,
                                                   '" WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                   ' = ', fileId)])
    .then(() => resolve())
    .catch(sqlError => reject(sqlError))
  );
}

function cascadeChangeFilePath(index, prevBasePath, newBasePath, fileArr) {
  return new Promise((resolve, reject) => {
    if (index >= fileArr.length) {
      return true;
    }
    const fileToChangePathIndex = Object.values(fileArr[index])[0];
    let newPath;
    return getCurrentFilePath(fileToChangePathIndex)
    .then((currentFilePath) => {
      const childPath = currentFilePath.toString().split(prevBasePath)[1];
      newPath = stringManipulator.stringConcat(newBasePath, childPath);
      return changeSingleFilePath(fileToChangePathIndex, newPath)
      .catch(sqlErr => reject(sqlErr));
    })
    .then(() => {
      cascadeChangeFilePath(index + 1, prevBasePath, newBasePath, fileArr)
      .catch(err => reject(err));
      resolve();
    })
    .catch(err => reject(err));
  });
}

function changeSingleFolderPath(folderId, newPath) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('UPDATE ', constants.ENTITIES_FOLDER,
                                                   ' SET ', constants.HEADER_FOLDER_PATH,
                                                   ' = "', newPath,
                                                   '" WHERE ', constants.HEADER_FOLDER_FOLDER_ID,
                                                   ' = ', folderId)])
    .then(() => resolve())
    .catch(sqlError => reject(sqlError))
  );
}

function changeSingleFolderName(folderId, newFolderName) {
  return new Promise((resolve, reject) =>
    alasql.promise([stringManipulator.stringConcat('UPDATE ', constants.ENTITIES_FOLDER,
                                                   ' SET ', constants.HEADER_FOLDER_FOLDER_NAME,
                                                   ' = "', newFolderName,
                                                   '" WHERE ', constants.HEADER_FOLDER_FOLDER_ID,
                                                   ' = ', folderId)])
    .then(() => resolve())
    .catch(sqlError => reject(sqlError))
  );
}

function cascadeChangeFolderPath(index, prevBasePath, newBasePath, folderArr) {
  return new Promise((resolve, reject) => {
    if (index >= folderArr.length) {
      return true;
    }
    const folderToChangePathIndex = Object.values(folderArr[index])[0];
    let newPath;
    return getCurrentFolderPath(folderToChangePathIndex)
    .then((currentFolderPath) => {
      const childPath = currentFolderPath.toString().split(prevBasePath)[1];
      newPath = stringManipulator.stringConcat(newBasePath, childPath);
      return changeSingleFolderPath(folderToChangePathIndex, newPath)
      .catch(sqlErr => reject(sqlErr));
    })
    .then(() => {
      cascadeChangeFolderPath(index + 1, prevBasePath, newBasePath, folderArr)
      .catch(err => reject(err));
      resolve();
    })
    .catch(err => reject(err));
  });
}
}

export default function sqlCommands() {
  this.linkDatabaseToIndexedDB = function linkDatabaseToIndexedDB(databaseName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        const databaseRequestStr = stringManipulator.stringConcat(
          'CREATE INDEXEDDB DATABASE IF NOT EXISTS ', databaseName, ';',
          'ATTACH INDEXEDDB DATABASE ', databaseName, ';',
          'USE ', databaseName, ';');
        return alasql.promise([databaseRequestStr])
          .then(data => resolve(true))
          .catch(sqlError => reject(sqlError));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.getFullTableData = function getFullTableData(tableName) {
    // ensure working in browsers that support Promise
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', tableName)])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError)));
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.createTable = function createTable(sqlStatement) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('CREATE TABLE IF NOT EXISTS ', sqlStatement)])
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.insertContent = function insertContent(tableName, alasqlArray) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise(stringManipulator.stringConcat('INSERT INTO ', tableName,
                                                       ' VALUES ?'), alasqlArray)
        .then(data => resolve(data))
        .catch(sqlError => reject(sqlError)));
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.partialSearchFileName = function partialSearchFileName(searchString) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', constants.ENTITIES_FILE_MANAGER,
                                                       ' WHERE ', constants.HEADER_FILE_MANAGER_FILE_NAME,
                                                       ' LIKE "%', searchString, '%"')])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };
  this.getMaxFileId = function getMaxFileId() {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT max(', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                       ') FROM ', constants.ENTITIES_FILE_MANAGER)])
        .then((data) => {
          const maxFileId = getDataOutOfAlasql(data);
          if (typeof maxFileId === 'number') {
            resolve(maxFileId);
          } else {
            resolve(-1);
          }
        }).catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };
  this.getMaxFolderId = function getMaxFolderId() {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT MAX(', constants.HEADER_FOLDER_FOLDER_ID,
                                                       ') FROM ', constants.ENTITIES_FOLDER)])
        .then((data) => {
          const maxFolderId = getDataOutOfAlasql(data);
          if (typeof maxFolderId === 'number') {
            resolve(maxFolderId);
          } else {
            resolve(0);
          }
        }).catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.partialSearchFolderName = function partialSearchFolderName(searchString) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', constants.ENTITIES_FOLDER,
                                                       ' WHERE ', constants.HEADER_FOLDER_FOLDER_NAME,
                                                       ' LIKE "%', searchString, '%"')])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.loadFilesFromFolder = function loadFilesFromFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', constants.ENTITIES_FILE_MANAGER,
                                                       ' WHERE ', constants.HEADER_FILE_MANAGER_FOLDER_ID,
                                                       ' = ', folderId)])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.loadFoldersFromFolder = function loadFoldersFromFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT * FROM ', constants.ENTITIES_FOLDER,
                                                       ' WHERE ', constants.HEADER_FOLDER_PARENT_FOLDER_ID,
                                                       ' = ', folderId)])
        .then(data => resolve(getArray(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.loadFile = function loadFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('SELECT ', constants.HEADER_FILE_MANAGER_FILE_MARKDOWN,
                                                       ' FROM ', constants.ENTITIES_FILE_MANAGER,
                                                       ' WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                       ' = ', fileId)])
        .then(data => resolve(getDataOutOfAlasql(data)))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.saveFile = function saveFile(fileId, markdownFile) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        .then(() => {
          const currentDateTime = dateTime.getCurrentDateTime();
          alasql.promise([stringManipulator.stringConcat('UPDATE ', constants.ENTITIES_FILE_MANAGER,
                                                         ' SET ', constants.HEADER_FILE_MANAGER_LAST_MODIFIED_DATE,
                                                         ' = "', currentDateTime,
                                                         '" WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                         ' = ', fileId)])
          .catch(sqlError => reject(sqlError));
        })
        .then(() => resolve(true))
        .catch(sqlErr => reject(sqlErr));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.deleteFile = function deleteFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('DELETE FROM ', constants.ENTITIES_FILE_MANAGER,
                                                       ' WHERE ', constants.HEADER_FILE_MANAGER_FILE_ID,
                                                       ' = ', fileId)])
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  this.deleteFolder = function deleteFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('DELETE FROM ', constants.ENTITIES_FOLDER,
                                                       ' WHERE ', constants.HEADER_FOLDER_FOLDER_ID,
                                                       ' = ', folderId)])
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };

  // external library not functioning so I cannot do anything here
  this.deleteTable = function deleteTable(tableName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        alasql.promise([stringManipulator.stringConcat('DROP TABLE IF EXISTS ', tableName)])
        .then(isSuccess => resolve(isSuccess))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  };
}
<|endoftext|>


<commit_before>var net = require('net'),
    zmq = require('zmq'),
    zmqSock = zmq.socket('push'),
    debug = require('debug')('gps'),
    config = require('./config.json');

zmqSock.bindSync('tcp://' + config.zmq_server.host + ':' + config.zmq_server.port);

var server = net.createServer(function (s) {
  s.on('data', function(data) {

    // Determin message type
    var msgType = null;

    if(data.length === 36) {
      msgType = 'heartbeat';
    } else if (data.length === 80) {
      msgType = 'location';
    } else {
      // Unknown message type
      return;
    }

    // Trim leading and trailing parens
    data = data.slice(1,data.length-1);

    if(msgType === 'location') {
      /**
       * Example record:
       * (027042854711BR00150117A5702.5470N00955.1263E000.61648574.770000000000L00000000)
       *
       * 027042854711     # imei                        12 chars
       * BR00             # command                      4 chars
       * 150117           # date yy/mm/dd                6 chars
       * A                # A=valid GPS data, V=invalid  1 char
       * 5702.5470        # lat                          9 chars
       * N                # lat indicator                1 char
       * 00955.1263       # long                        10 chars
       * E                # long indicator               1 char
       * 000.6            # speed, km/hour               5 chars
       * 164857           # time hh/mm/ss                6 chars
       * 4.7700           # orientation, deb             6 chars
       * 00000000         # status                       8 chars
       * L                # always L ?                   1 char
       * 00000000         # mean milage ?                8 chars
       */
      var rec = {};
      rec.imei          = data.toString('ascii',  0, 12);
      rec.command       = data.toString('ascii', 12, 16);
      rec.year          = data.toString('ascii', 16, 18);
      rec.month         = data.toString('ascii', 18, 20);
      rec.date          = data.toString('ascii', 20, 22);
      rec.status        = data.toString('ascii', 22, 23);
      rec.lat           = data.toString('ascii', 23, 32)*1 / 100;
      rec.latIndicator  = data.toString('ascii', 32, 33);
      rec.long          = data.toString('ascii', 33, 43)*1 / 100;
      rec.longIndicator = data.toString('ascii', 43, 44);
      rec.speed         = data.toString('ascii', 44, 49);
      rec.hours         = data.toString('ascii', 49, 51);
      rec.minutes       = data.toString('ascii', 51, 53);
      rec.seconds       = data.toString('ascii', 53, 55);
      rec.orientation   = data.toString('ascii', 55, 61);
      rec.status        = data.toString('ascii', 61, 69);
      rec.l             = data.toString('ascii', 69, 70);
      rec.milage        = data.toString('ascii', 70, 78);
    } else if (msgType === 'heartbeat') {
      /**
       * Example record: (027042854711BP00000027042854711HSO)
       *
       * 027042854711       # imei            12 chars
       * BP00               # record type      4 chars
       * 000027042854711    # device id       15 chars
       * HSO                # message body     3 chars
       */
      var rec = {};
      rec.imei          = data.toString('ascii',  0, 12);
      rec.command       = data.toString('ascii', 12, 16);
      rec.deviceId      = data.toString('ascii', 16, 31);
      rec.body          = data.toString('ascii', 31, 34);
    }

    zmqSock.send(JSON.stringify(rec));
  });
});

server.listen(config.tcp_server.port);<commit_msg>Seriously ugly lat/lng parsing<commit_after>var net = require('net'),
    zmq = require('zmq'),
    zmqSock = zmq.socket('push'),
    debug = require('debug')('gps'),
    config = require('./config.json');

zmqSock.bindSync('tcp://' + config.zmq_server.host + ':' + config.zmq_server.port);

// Look away
var convertLat = function(lat) {
  var deg = lat.slice(0, 2),
      minutes = lat.slice(2, lat.length);
  minutes = (Number(minutes)/60)*100;
  minutes = minutes < 10 ? '0' + minutes : minutes;
  minutes = String(minutes).replace('.', '');

  return Number(deg + '.' + minutes).toFixed(5);
}

// Dont look
var convertLng = function(lng) {
  var deg = lng.slice(0, 3),
      part = lng.slice(3, lng.length);

  part = (Number(part)/60)*100;
  part = part < 10 ? '0' + part : part;
  part = String(part).replace('.', '');

  return Number(deg + '.' + part).toFixed(5);
}

var server = net.createServer(function (s) {
  s.on('data', function(data) {

    // Determin message type
    var msgType = null;

    if(data.length === 36) {
      msgType = 'heartbeat';
    } else if (data.length === 80) {
      msgType = 'location';
    } else {
      // Unknown message type
      return;
    }

    // Trim leading and trailing parens
    data = data.slice(1,data.length-1);

    if(msgType === 'location') {
      /**
       * Example record:
       * (027042854711BR00150117A5702.5470N00955.1263E000.61648574.770000000000L00000000)
       *
       * 027042854711     # imei                        12 chars
       * BR00             # command                      4 chars
       * 150117           # date yy/mm/dd                6 chars
       * A                # A=valid GPS data, V=invalid  1 char
       * 5702.5470        # lat                          9 chars
       * N                # lat indicator                1 char
       * 00955.1263       # long                        10 chars
       * E                # long indicator               1 char
       * 000.6            # speed, km/hour               5 chars
       * 164857           # time hh/mm/ss                6 chars
       * 4.7700           # orientation, deb             6 chars
       * 00000000         # status                       8 chars
       * L                # always L ?                   1 char
       * 00000000         # mean milage ?                8 chars
       */
      var rec = {};
      rec.imei          = data.toString('ascii',  0, 12);
      rec.command       = data.toString('ascii', 12, 16);
      rec.year          = data.toString('ascii', 16, 18);
      rec.month         = data.toString('ascii', 18, 20);
      rec.date          = data.toString('ascii', 20, 22);
      rec.status        = data.toString('ascii', 22, 23);
      rec.lat           = convertLat(data.toString('ascii', 23, 32));
      rec.latIndicator  = data.toString('ascii', 32, 33);
      rec.lng           = convertLng(data.toString('ascii', 33, 43));
      rec.lngIndicator  = data.toString('ascii', 43, 44);
      rec.speed         = data.toString('ascii', 44, 49);
      rec.hours         = data.toString('ascii', 49, 51);
      rec.minutes       = data.toString('ascii', 51, 53);
      rec.seconds       = data.toString('ascii', 53, 55);
      rec.orientation   = data.toString('ascii', 55, 61);
      rec.status        = data.toString('ascii', 61, 69);
      rec.l             = data.toString('ascii', 69, 70);
      rec.milage        = data.toString('ascii', 70, 78);
    } else if (msgType === 'heartbeat') {
      /**
       * Example record: (027042854711BP00000027042854711HSO)
       *
       * 027042854711       # imei            12 chars
       * BP00               # record type      4 chars
       * 000027042854711    # device id       15 chars
       * HSO                # message body     3 chars
       */
      var rec = {};
      rec.imei          = data.toString('ascii',  0, 12);
      rec.command       = data.toString('ascii', 12, 16);
      rec.deviceId      = data.toString('ascii', 16, 31);
      rec.body          = data.toString('ascii', 31, 34);
    }

    zmqSock.send(JSON.stringify(rec));
  });
});

server.listen(config.tcp_server.port);
<|endoftext|>


<commit_before><commit_msg>Allow editing of package.json<commit_after><|endoftext|>


<commit_before>(function(){
    'use strict';

    function mdDataTableDirective(ColumnAwareService){
        return {
            restrict: 'E',
            templateUrl: '/main/templates/mdDataTable.html',
            transclude: true,
            scope: {
                tableCard: '=',
                tableRowsData: '=',
                selectableRows: '='
            },
            controller: function($scope){
                ColumnAwareService.initialize($scope);
            },
            link: function($scope, element, attrs, ctrl, transclude){
                transclude(function (clone) {
                    var headings = [];
                    var body = [];

                    clone.each(function (index, child) {
                        var $child = angular.element(child);

                        if ($child.hasClass('theadTrRow')) {
                            headings.push($child);
                        } else {
                            body.push($child);
                        }
                    });

                    element.find('table thead').append(headings);
                    element.find('table tbody').append(body);
                });
            }
        };
    }

    angular
        .module('mdDataTable')
        .directive('mdDataTable', mdDataTableDirective);
}());<commit_msg>activation page 2: fixings for IEnot a working solutionnot a working solution<commit_after>(function(){
    'use strict';

    function mdDataTableDirective(ColumnAwareService){
        return {
            restrict: 'E',
            templateUrl: '/main/templates/mdDataTable.html',
            transclude: true,
            scope: {
                tableCard: '=',
                tableRowsData: '=',
                selectableRows: '='
            },
            controller: function($scope){
                ColumnAwareService.initialize($scope);
            },
            compile: function compile(tElement, tAttrs, transclude) {

                separateTranscludeAndInject();

                return {
                    pre: function preLink(scope, iElement, iAttrs, controller) { },
                    post: function postLink(scope, iElement, iAttrs, controller) { }
                };

                function separateTranscludeAndInject(){
                    transclude(function (clone) {
                        var headings = [];
                        var body = [];

                        clone.each(function (index, child) {
                            var $child = angular.element(child);

                            if ($child.hasClass('theadTrRow')) {
                                headings.push($child);
                            } else {
                                body.push($child);
                            }
                        });

                        tElement.find('table thead').append(headings);
                        tElement.find('table tbody').append(body);
                    });
                }

            }
        };
    }

    angular
        .module('mdDataTable')
        .directive('mdDataTable', mdDataTableDirective);
}());<|endoftext|>


<commit_before>'use strict';
const path = require('path');

const { ipcRenderer } = require('electron');
const { app, dialog } = require('electron').remote;

const fs = require('fs-extra');

const BaseSection = require(__dirname + '/base-section.js');
const ConfigUtil = require(__dirname + '/../../utils/config-util.js');

class GeneralSection extends BaseSection {
	constructor(props) {
		super();
		this.props = props;
	}

	template() {
		return `

Appearance

Show app icon in system tray

Show sidebar (CmdOrCtrl+S)

Show app unread badge

Desktop Notification

Mute all sounds from Zulip (requires reload)

App Updates

Get beta updates

Functionality

Start app at login

Reset Application Data

This will delete all application data which will remove all added accounts and preferences

						<button class="reset-data-button green">Reset App Data</button>

		`;
	}

	init() {
		this.props.$root.innerHTML = this.template();
		this.updateTrayOption();
		this.updateBadgeOption();
		this.updateUpdateOption();
		this.updateSilentOption();
		this.updateSidebarOption();
		this.updateStartAtLoginOption();
		this.updateResetDataOption();
	}

	updateTrayOption() {
		this.generateSettingOption({
			$element: document.querySelector('#tray-option .setting-control'),
			value: ConfigUtil.getConfigItem('trayIcon', true),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('trayIcon');
				ConfigUtil.setConfigItem('trayIcon', newValue);
				ipcRenderer.send('forward-message', 'toggletray');
				this.updateTrayOption();
			}
		});
	}

	updateBadgeOption() {
		this.generateSettingOption({
			$element: document.querySelector('#badge-option .setting-control'),
			value: ConfigUtil.getConfigItem('badgeOption', true),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('badgeOption');
				ConfigUtil.setConfigItem('badgeOption', newValue);
				ipcRenderer.send('toggle-badge-option', newValue);
				this.updateBadgeOption();
			}
		});
	}

	updateUpdateOption() {
		this.generateSettingOption({
			$element: document.querySelector('#betaupdate-option .setting-control'),
			value: ConfigUtil.getConfigItem('betaUpdate', false),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('betaUpdate');
				ConfigUtil.setConfigItem('betaUpdate', newValue);
				this.updateUpdateOption();
			}
		});
	}

	updateSilentOption() {
		this.generateSettingOption({
			$element: document.querySelector('#silent-option .setting-control'),
			value: ConfigUtil.getConfigItem('silent', false),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('silent', true);
				ConfigUtil.setConfigItem('silent', newValue);
				this.updateSilentOption();
			}
		});
	}

	updateSidebarOption() {
		this.generateSettingOption({
			$element: document.querySelector('#sidebar-option .setting-control'),
			value: ConfigUtil.getConfigItem('showSidebar', true),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('showSidebar');
				ConfigUtil.setConfigItem('showSidebar', newValue);
				ipcRenderer.send('forward-message', 'toggle-sidebar', newValue);
				this.updateSidebarOption();
			}
		});
	}

	updateStartAtLoginOption() {
		this.generateSettingOption({
			$element: document.querySelector('#startAtLogin-option .setting-control'),
			value: ConfigUtil.getConfigItem('startAtLogin', false),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('startAtLogin');
				ConfigUtil.setConfigItem('startAtLogin', newValue);
				ipcRenderer.send('toggleAutoLauncher', newValue);
				this.updateStartAtLoginOption();
			}
		});
	}

	clearAppData() {
		const clearAppDataMessage = 'By clicking proceed you will be removing all added accounts and preferences from Zulip. When the application restarts, it will be as if you are starting Zulip for the first time.';
		const getAppPath = path.join(app.getPath('appData'), app.getName());

		dialog.showMessageBox({
			type: 'warning',
			buttons: ['Yes', 'No'],
			defaultId: 0,
			message: 'Are you sure',
			detail: clearAppDataMessage
		}, response => {
			if (response === 0) {
				fs.remove(getAppPath);
				setTimeout(() => ipcRenderer.send('forward-message', 'hard-reload'), 1000);
			}
		});
	}

	updateResetDataOption() {
		const resetDataButton = document.querySelector('#resetdata-option .reset-data-button');
		resetDataButton.addEventListener('click', () => {
			this.clearAppData();
		});
	}

}

module.exports = GeneralSection;
<commit_msg>code refactor<commit_after>'use strict';
const path = require('path');

const { ipcRenderer } = require('electron');
const { app, dialog } = require('electron').remote;

const fs = require('fs-extra');

const BaseSection = require(__dirname + '/base-section.js');
const ConfigUtil = require(__dirname + '/../../utils/config-util.js');

class GeneralSection extends BaseSection {
	constructor(props) {
		super();
		this.props = props;
	}

	template() {
		return `

Appearance

Show app icon in system tray

Show sidebar (CmdOrCtrl+S)

Show app unread badge

Desktop Notification

Mute all sounds from Zulip (requires reload)

App Updates

Get beta updates

Functionality

Start app at login

Reset Application Data

This will delete all application data which will remove all added accounts and preferences

						<button class="reset-data-button green">Reset App Data</button>

		`;
	}

	init() {
		this.props.$root.innerHTML = this.template();
		this.updateTrayOption();
		this.updateBadgeOption();
		this.updateUpdateOption();
		this.updateSilentOption();
		this.updateSidebarOption();
		this.updateStartAtLoginOption();
		this.updateResetDataOption();
	}

	updateTrayOption() {
		this.generateSettingOption({
			$element: document.querySelector('#tray-option .setting-control'),
			value: ConfigUtil.getConfigItem('trayIcon', true),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('trayIcon');
				ConfigUtil.setConfigItem('trayIcon', newValue);
				ipcRenderer.send('forward-message', 'toggletray');
				this.updateTrayOption();
			}
		});
	}

	updateBadgeOption() {
		this.generateSettingOption({
			$element: document.querySelector('#badge-option .setting-control'),
			value: ConfigUtil.getConfigItem('badgeOption', true),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('badgeOption');
				ConfigUtil.setConfigItem('badgeOption', newValue);
				ipcRenderer.send('toggle-badge-option', newValue);
				this.updateBadgeOption();
			}
		});
	}

	updateUpdateOption() {
		this.generateSettingOption({
			$element: document.querySelector('#betaupdate-option .setting-control'),
			value: ConfigUtil.getConfigItem('betaUpdate', false),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('betaUpdate');
				ConfigUtil.setConfigItem('betaUpdate', newValue);
				this.updateUpdateOption();
			}
		});
	}

	updateSilentOption() {
		this.generateSettingOption({
			$element: document.querySelector('#silent-option .setting-control'),
			value: ConfigUtil.getConfigItem('silent', false),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('silent', true);
				ConfigUtil.setConfigItem('silent', newValue);
				this.updateSilentOption();
			}
		});
	}

	updateSidebarOption() {
		this.generateSettingOption({
			$element: document.querySelector('#sidebar-option .setting-control'),
			value: ConfigUtil.getConfigItem('showSidebar', true),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('showSidebar');
				ConfigUtil.setConfigItem('showSidebar', newValue);
				ipcRenderer.send('forward-message', 'toggle-sidebar', newValue);
				this.updateSidebarOption();
			}
		});
	}

	updateStartAtLoginOption() {
		this.generateSettingOption({
			$element: document.querySelector('#startAtLogin-option .setting-control'),
			value: ConfigUtil.getConfigItem('startAtLogin', false),
			clickHandler: () => {
				const newValue = !ConfigUtil.getConfigItem('startAtLogin');
				ConfigUtil.setConfigItem('startAtLogin', newValue);
				ipcRenderer.send('toggleAutoLauncher', newValue);
				this.updateStartAtLoginOption();
			}
		});
	}

	clearAppDataDialog() {
		const clearAppDataMessage = 'By clicking proceed you will be removing all added accounts and preferences from Zulip. When the application restarts, it will be as if you are starting Zulip for the first time.';
		const getAppPath = path.join(app.getPath('appData'), app.getName());

		dialog.showMessageBox({
			type: 'warning',
			buttons: ['YES', 'NO'],
			defaultId: 0,
			message: 'Are you sure',
			detail: clearAppDataMessage
		}, response => {
			if (response === 0) {
				fs.remove(getAppPath);
				setTimeout(() => ipcRenderer.send('forward-message', 'hard-reload'), 1000);
			}
		});
	}

	updateResetDataOption() {
		const resetDataButton = document.querySelector('#resetdata-option .reset-data-button');
		resetDataButton.addEventListener('click', () => {
			this.clearAppDataDialog();
		});
	}

}

module.exports = GeneralSection;
<|endoftext|>


<commit_before>export let serviceName = 'notifications';
export default /*@ngInject*/ function notifications(
  $cordovaLocalNotification,
  $rootScope,
  $window,
  $q,
  devices,
  identity,
  navigation,
  state,
  R
) {
  let contacts;
  // cordovaLocalNotification uses number IDs
  // notificationId is just channelId, and has the form toc-{32hex-chars}
  let getCordovaNotificationId = (notificationId) => {
    let lastEightHex = notificationId.substr(notificationId.length - 8);
    return parseInt(lastEightHex, 16);
  };

  let getNotificationMessage = function getNotificationMessage(notificationId) {
    let channelId = notificationId;
    let channelCursor = state.cloud.channels.select([channelId]);

    let notificationMessage;
    if (channelCursor.get(['inviteStatus']) === 'received') {
      return 'New invite received!';
    }

    let messageIdCursor = channelCursor.select(['latestMessageId']);
    let messageId = messageIdCursor.get();
    if (!messageId) {
      return '';
    }

    return state.cloud.messages.get([
      channelId, messageId, 'messageInfo', 'content'
    ]);
  };

  let notifyCordova = function notifyCordova(notificationInfo) {
    let channelId = notificationInfo.id;
    let channelCursor = state.cloud.channels.select([channelId]);
    let contactId = channelCursor.get(['channelInfo', 'contactIds'])[0];
    let contactCursor = state.cloud.contacts.select(contactId);
    let contactInfo = contactCursor.get('userInfo');

    let icon = identity.getAvatar(contactInfo);
    let title = contactInfo.displayName || 'Anonymous';
    let text = getNotificationMessage(notificationInfo.id);

    let cordovaNotificationInfo = {
      id: notificationInfo.cordovaNotificationId,
      title,
      text,
      icon,
      sound: 'res://platform_default',
      smallIcon: 'res://icon.png',
      data: notificationInfo
    };

    return $cordovaLocalNotification.schedule(cordovaNotificationInfo);
  };

  let notifyWeb = function notifyWeb(notificationInfo) {
    return $q.when();
  };

  let notify = function notify(notificationId) {
    let cordovaNotificationId = getCordovaNotificationId(notificationId);

    let notifyNative = (notificationInfo) => {
      if (devices.isInForeground()) {
        return $q.when();
      }

      return devices.isCordovaApp() ?
        notifyCordova(notificationInfo) :
        notifyWeb(notificationInfo);
    };

    let notificationCursor = state.cloud.notifications.select([notificationId]);

    let notificationInfo = {
      id: notificationId,
      cordovaNotificationId
    };

    return notifyNative(notificationInfo)
      .then(() => state.save(
        notificationCursor, ['notificationInfo'], notificationInfo
      ))
      .then(() => state.save(notificationCursor, ['dismissed'], false));
  };

  let dismissCordova = function dismissCordova(notificationInfo) {
    return $cordovaLocalNotification
      .clear(notificationInfo.cordovaNotificationId);
  };

  let dismissWeb = function dismissWeb(notificationInfo) {
    return $q.when();
  };

  let dismiss = function dismiss(notificationId) {
    let cordovaNotificationId = getCordovaNotificationId(notificationId);

    if (isDismissed(notificationId)) {
      return $q.when();
    }

    let dismissNative = (notificationInfo) => {
      return devices.isCordovaApp() ?
        dismissCordova(notificationInfo) :
        dismissWeb(notificationInfo);
    };

    let notificationCursor = state.cloud.notifications.select([notificationId]);

    let notificationInfo = {
      id: notificationId,
      cordovaNotificationId
    };

    return dismissNative(notificationInfo)
      .then(() => state.save(notificationCursor, ['dismissed'], true));
  };

  let isDismissed = function isDismissed(notificationId) {
    return state.cloud.notifications.get([notificationId, 'dismissed']);
  };

  $rootScope.$on('$cordovaLocalNotification:click', (event, notification) => {
    let viewId = JSON.parse(notification.data).id;

    if (viewId === 'home') {
      return navigation.navigate(viewId);
    }

    let channelId = viewId;
    let channelCursor = state.cloud.channels.select([channelId]);

    if (channelCursor.get(['inviteStatus'])  === 'received') {
      return contacts.showAcceptInviteDialog(channelId);
    }

    return navigation.navigate(channelId)
      .then(() => state.save(channelCursor, ['viewingLatest'], true));
  });

  let initialize = function initialize(contactsService) {
    contacts = contactsService;

    if (devices.isCordovaApp()) {
      let notificationsCursor = state.cloud.notifications;
      let updateOngoingNotification = () => {
        let notificationCount = R.pipe(
          R.values,
          R.reject(R.prop('dismissed'))
        )(notificationsCursor.get()).length;

        let message;
        if (notificationCount === 0) {
          message = 'No new notifications';
        }
        else if(notificationCount === 1) {
          message = '1 new notification';
        }
        else {
          message = `${notificationCount} new notifications`;
        }

        return $cordovaLocalNotification.schedule({
          id: 0,
          title: 'Toc Messenger',
          text: message,
          sound: 'res://platform_default',
          icon: 'res://icon.png',
          smallIcon: 'res://icon.png',
          data: { id: 'home' },
          ongoing: devices.isAndroidApp()
        });
      };

      state.addListener(notificationsCursor, updateOngoingNotification);
    }

    if (devices.isWebApp()) {
      if (!$window.Notification) {
        return $q.when();
      }

      $window.Notification.requestPermission();
    }

    return $q.when();
  };

  return {
    isDismissed,
    notify,
    dismiss,
    initialize
  };
}
<commit_msg>Added web notification triggering and autohide<commit_after>export let serviceName = 'notifications';
export default /*@ngInject*/ function notifications(
  $cordovaLocalNotification,
  $rootScope,
  $window,
  $timeout,
  $q,
  devices,
  identity,
  navigation,
  state,
  R
) {
  let contacts;
  let activeWebNotifications = {};
  // cordovaLocalNotification uses number IDs
  // notificationId is just channelId, and has the form toc-{32hex-chars}
  let getCordovaNotificationId = (notificationId) => {
    let lastEightHex = notificationId.substr(notificationId.length - 8);
    return parseInt(lastEightHex, 16);
  };

  let getNotificationMessage = function getNotificationMessage(notificationId) {
    let channelId = notificationId;
    let channelCursor = state.cloud.channels.select([channelId]);

    let notificationMessage;
    if (channelCursor.get(['inviteStatus']) === 'received') {
      return 'New invite received!';
    }

    let messageIdCursor = channelCursor.select(['latestMessageId']);
    let messageId = messageIdCursor.get();
    if (!messageId) {
      return '';
    }

    return state.cloud.messages.get([
      channelId, messageId, 'messageInfo', 'content'
    ]);
  };

  let notifyCordova = function notifyCordova(notificationInfo) {
    let channelId = notificationInfo.id;
    let channelCursor = state.cloud.channels.select([channelId]);
    let contactId = channelCursor.get(['channelInfo', 'contactIds'])[0];
    let contactCursor = state.cloud.contacts.select(contactId);
    let contactInfo = contactCursor.get('userInfo');

    let icon = identity.getAvatar(contactInfo);
    let title = contactInfo.displayName || 'Anonymous';
    let text = getNotificationMessage(notificationInfo.id);

    let cordovaNotificationInfo = {
      id: notificationInfo.cordovaNotificationId,
      title,
      text,
      icon,
      sound: 'res://platform_default',
      smallIcon: 'res://icon.png',
      data: notificationInfo
    };

    return $cordovaLocalNotification.schedule(cordovaNotificationInfo);
  };

  let notifyWeb = function notifyWeb(notificationInfo) {
    if (!$window.Notification) {
      return $q.when();
    }
    let channelId = notificationInfo.id;
    let channelCursor = state.cloud.channels.select([channelId]);
    let contactId = channelCursor.get(['channelInfo', 'contactIds'])[0];
    let contactCursor = state.cloud.contacts.select(contactId);
    let contactInfo = contactCursor.get('userInfo');

    let webNotificationOptions = {
      body: getNotificationMessage(notificationInfo.id),
      icon: identity.getAvatar(contactInfo),
      tag: notificationInfo.id
    };

    let notificationTitle = contactInfo.displayName || 'Anonymous';

    activeWebNotifications[notificationInfo.id] =
      new Notification(notificationTitle, webNotificationOptions);

    let notificationInstance = activeWebNotifications[notificationInfo.id];
    $timeout(() => {
      notificationInstance.close();
    }, 5000, false);

    return $q.when();
  };

  let notify = function notify(notificationId) {
    let cordovaNotificationId = getCordovaNotificationId(notificationId);

    let notifyNative = (notificationInfo) => {
      if (devices.isInForeground()) {
        return $q.when();
      }

      return devices.isCordovaApp() ?
        notifyCordova(notificationInfo) :
        notifyWeb(notificationInfo);
    };

    let notificationCursor = state.cloud.notifications.select([notificationId]);

    let notificationInfo = {
      id: notificationId,
      cordovaNotificationId
    };

    return notifyNative(notificationInfo)
      .then(() => state.save(
        notificationCursor, ['notificationInfo'], notificationInfo
      ))
      .then(() => state.save(notificationCursor, ['dismissed'], false));
  };

  let dismissCordova = function dismissCordova(notificationInfo) {
    return $cordovaLocalNotification
      .clear(notificationInfo.cordovaNotificationId);
  };

  let dismissWeb = function dismissWeb(notificationInfo) {
    if (!$window.Notification) {
      return $q.when();
    }
    return $q.when();
  };

  let dismiss = function dismiss(notificationId) {
    let cordovaNotificationId = getCordovaNotificationId(notificationId);

    if (isDismissed(notificationId)) {
      return $q.when();
    }

    let dismissNative = (notificationInfo) => {
      return devices.isCordovaApp() ?
        dismissCordova(notificationInfo) :
        dismissWeb(notificationInfo);
    };

    let notificationCursor = state.cloud.notifications.select([notificationId]);

    let notificationInfo = {
      id: notificationId,
      cordovaNotificationId
    };

    return dismissNative(notificationInfo)
      .then(() => state.save(notificationCursor, ['dismissed'], true));
  };

  let isDismissed = function isDismissed(notificationId) {
    return state.cloud.notifications.get([notificationId, 'dismissed']);
  };

  $rootScope.$on('$cordovaLocalNotification:click', (event, notification) => {
    let viewId = JSON.parse(notification.data).id;

    if (viewId === 'home') {
      return navigation.navigate(viewId);
    }

    let channelId = viewId;
    let channelCursor = state.cloud.channels.select([channelId]);

    if (channelCursor.get(['inviteStatus'])  === 'received') {
      return contacts.showAcceptInviteDialog(channelId);
    }

    return navigation.navigate(channelId)
      .then(() => state.save(channelCursor, ['viewingLatest'], true));
  });

  let initialize = function initialize(contactsService) {
    contacts = contactsService;

    if (devices.isCordovaApp()) {
      let notificationsCursor = state.cloud.notifications;
      let updateOngoingNotification = () => {
        let notificationCount = R.pipe(
          R.values,
          R.reject(R.prop('dismissed'))
        )(notificationsCursor.get()).length;

        let message;
        if (notificationCount === 0) {
          message = 'No new notifications';
        }
        else if(notificationCount === 1) {
          message = '1 new notification';
        }
        else {
          message = `${notificationCount} new notifications`;
        }

        return $cordovaLocalNotification.schedule({
          id: 0,
          title: 'Toc Messenger',
          text: message,
          sound: 'res://platform_default',
          icon: 'res://icon.png',
          smallIcon: 'res://icon.png',
          data: { id: 'home' },
          ongoing: devices.isAndroidApp()
        });
      };

      state.addListener(notificationsCursor, updateOngoingNotification);
    }

    if (devices.isWebApp()) {
      if (!$window.Notification) {
        return $q.when();
      }

      $window.Notification.requestPermission();
    }

    return $q.when();
  };

  return {
    isDismissed,
    notify,
    dismiss,
    initialize
  };
}
<|endoftext|>


<commit_before>function StudentSelectorChanged() {
	let selectedStudentOption = getSelectedStudentOption();
	if (selectedStudentOption.className.indexOf('not-admitted') === -1) {
		$('#remove_student').removeAttr("disabled");
		$('#new_student_pw').removeAttr("disabled");
		$('#new_student_pw_submit').removeAttr("disabled");
		$('#admit_student').attr("disabled", "disabled");
	} else {
		$('#remove_student').removeAttr("disabled");
		$('#new_student_pw').attr("disabled", "disabled");
		$('#new_student_pw_submit').attr("disabled", "disabled");
		$('#admit_student').removeAttr("disabled");
	}
}

function RequestStudents() {
	socket.emit('Request_StudentsForClass', {
		cid: getSelectedClassId()
	});
}

function getSelectedStudentOption() {
	let options = $('#student_selector')[0].getElementsByTagName("option");
	for (let i = options.length; i--;)
		if (options[i].selected)
			return options[i];
}

socket.on('Response_StudentsForClass', function (data) {
	let enrollments = data.enrollments;
	let sSelect = document.getElementById("student_selector");
	sSelect.innerHTML = "";
	for (let i = 0; i < enrollments.length; i++) {
		let option = document.createElement("option");
		option.text = enrollments[i].student.username;
		option.value = enrollments[i].student._id;
		if (enrollments[i].admitted === false) {
			option.className += ' bg-info not-admitted ';
		}
		sSelect.add(option);
	}
});

function RemoveStudent() {
	socket.emit('Request_RemoveStudent', {
		cid: getSelectedClassId(),
		sid: getSelectedStudentOption().value
	})
}

socket.on('Response_RemoveStudent', function () {
	RequestStudents();
});

function AdmitStudent() {
	socket.emit('Request_AdmitStudent', {
		cid: getSelectedClassId(),
		sid: getSelectedStudentOption().value
	})
}

socket.on('Response_AdmitStudent', function () {
	RequestStudents();
});

function changeStudentPassword() {
	socket.emit('Request_ChangeStudentPassword', {
		cid: getSelectedClassId(),
		sid: getSelectedStudentOption().value,
		password: $('#new_student_pw').val()
	})
}

socket.on('Response_ChangeStudentPassword', function (data) {
	$('#manage_students_alert_box').text(data.message);
	document.getElementById('manage_students_alert_box').style.display = "block";
});

window.addEventListener("load", function () {
	$('#student_selector').change(StudentSelectorChanged);
	$('#manage_students_button').click(RequestStudents);
	$('#remove_student').click(RemoveStudent);
	$('#admit_student').click(AdmitStudent);
	$('#new_student_pw_submit').click(changeStudentPassword);

	$(".manage-students-modal").on("hidden.bs.modal", function(){
		$('#manage_students_alert_box').text('');
		document.getElementById('manage_students_alert_box').style.display = "none";
	});
});<commit_msg>Simplify manage students module<commit_after>function StudentSelectorChanged() {
	if (getSelectedStudentOption().className.indexOf('not-admitted') === -1) {
		document.querySelector('#remove_student').removeAttribute("disabled");
		document.querySelector('#new_student_pw').removeAttribute("disabled");
		document.querySelector('#new_student_pw_submit').removeAttribute("disabled");
		document.querySelector('#admit_student').setAttribute("disabled", "disabled");
	} else {
		document.querySelector('#remove_student').removeAttribute("disabled");
		document.querySelector('#new_student_pw').setAttribute("disabled", "disabled");
		document.querySelector('#new_student_pw_submit').setAttribute("disabled", "disabled");
		document.querySelector('#admit_student').removeAttribute("disabled");
	}
}

function RequestStudents() {
	socket.emit('Request_StudentsForClass', {
		cid: getSelectedClassId()
	});
}

function getSelectedStudentOption() {
	return document.querySelector('#student_selector option:checked');
}

socket.on('Response_StudentsForClass', function (data) {
	const student_selector = document.getElementById("student_selector");
	student_selector.innerHTML = "";
	data.enrollments.forEach(enrollment => {
		const option = new Option(enrollment.student.username, enrollment.student._id);
		if (enrollment.admitted === false) {
			option.className = 'bg-info not-admitted ';
		}
		student_selector.add(option);
	});
});

function RemoveStudent() {
	socket.emit('Request_RemoveStudent', {
		cid: getSelectedClassId(),
		sid: getSelectedStudentOption().value
	})
}

function AdmitStudent() {
	socket.emit('Request_AdmitStudent', {
		cid: getSelectedClassId(),
		sid: getSelectedStudentOption().value
	})
}

function changeStudentPassword() {
	socket.emit('Request_ChangeStudentPassword', {
		cid: getSelectedClassId(),
		sid: getSelectedStudentOption().value,
		password: $('#new_student_pw').val()
	})
}

function handleResponseChangeStudentPassword(data) {
	document.querySelector('#manage_students_alert_box').innerText = data.message;
	document.querySelector('#manage_students_alert_box').style.display = "block";
}

function clearManageStudentsModal() {
	document.querySelector('#manage_students_alert_box').innerText = '';
	document.querySelector('#manage_students_alert_box').style.display = "none";
}

function initManageStudentsModule() {
	document.querySelector('#student_selector').addEventListener('change', StudentSelectorChanged);
	document.querySelector('#manage_students_button').addEventListener('click', RequestStudents);
	document.querySelector('#remove_student').addEventListener('click', RemoveStudent);
	document.querySelector('#admit_student').addEventListener('click', AdmitStudent);
	document.querySelector('#new_student_pw_submit').click(changeStudentPassword);

	$(".manage-students-modal").on("hidden.bs.modal", clearManageStudentsModal);

	socket.on('Response_ChangeStudentPassword', handleResponseChangeStudentPassword);
	socket.on('Response_AdmitStudent', 	RequestStudents);
	socket.on('Response_RemoveStudent', RequestStudents);
}

window.addEventListener("load", initManageStudentsModule);<|endoftext|>


<commit_before>// Source Model
AV.source = Backbone.Model.extend({
	url: 'php/redirect.php/source',
	defaults: {
		name: '',
		type: 'raw',
		contentType: 'txt',
		data: ''
	},
});
// Source Model Tests

// test_source = new AV.source({
//     name: 'The Wind and the Rain',
//     type: 'raw',
//     contentType: 'txt',
//     data: "When that I was and a little tiny boy, with a hey-ho, the wind and the rain, a foolish thing was but a toy, for the rain it raineth every day."
// });
// alert('potato');
// test_source.save( {
//         success: function () {
//             alert('success');
//         },
//         error: function(d){
//             alert('everything is terrible');
//         }
//     });

other_test = new AV.source();
other_test.url = 'php/redirect.php/source/15';
other_test.fetch();

// Source Model End
<commit_msg>Add some tests, they're commented out right now. Things work!<commit_after>// Source Model
AV.Source = Backbone.Model.extend({
	url: 'php/redirect.php/source',
	defaults: {
		name: '',
		type: 'raw',
		contentType: 'txt',
		data: ''
	},
});
// Source Model Tests

// test_Source = new AV.Source({
//     name: 'The Wind and the Rain',
//     type: 'raw',
//     contentType: 'txt',
//     data: "When that I was and a little tiny boy, with a hey-ho, the wind and "+
//     the rain, a foolish thing was but a toy, for the rain it raineth every day."
// });
// alert('potato');
// test_Source.save( {
//         success: function () {
//             alert('success');
//         },
//         error: function(d){
//             alert('everything is terrible');
//         }
//     });

// other_test = new AV.Source();
// other_test.url = 'php/redirect.php/Source/15';
// other_test.fetch();
// alert(other_test.name);

// Source Model End
<|endoftext|>


<commit_before>var Key = new function() {
	// TODO: make sure the keys are called the same as in Scriptographer
	var keys = {
		 '8': 'backspace',
		'13': 'enter',
		'16': 'shift',
		'17': 'control',
		'19': 'alt',
		'20': 'capsLock',
		'27': 'escape',
		'32': 'space',
		'37': 'left',
		'38': 'up',
		'39': 'right',
		'40': 'down',
		'46': 'delete',
		'91': 'command'
	};

	var activeKeys = {};

	var modifiers = {
		shift: false,
		control: false,
		alt: false,
		command: false,
		capsLock: false
	};

	var eventHandlers = Base.each(['keyDown', 'keyUp'], function(type) {
		var toolHandler = 'on' + Base.capitalize(type),
			keyDown = type == 'keyDown';
		this[type.toLowerCase()] = function(event) {
			var code = event.which || event.keyCode,
				key = keys[code] || String.fromCharCode(code).toLowerCase();
			activeKeys[key] = keyDown;

			// If the key is a modifier, update the modifiers:
			if (modifiers[key] !== undefined)
				modifiers[key] = keyDown;

			// Call the onKeyDown or onKeyUp handler if present:
			// TODO: don't call the key handler if the key is a modifier?
			if (paper.tool[toolHandler]) {
				// TODO: Introduce a class for this?
				var keyEvent = {
					type: keyDown ? 'key-down' : 'key-up',
					keyCode: code,
					character: key,
					modifiers: modifiers,
					// 'preventDefault: event.preventDefault' throws
					// an error in Safari when called, so we have to wrap
					// it into a function.
					// TODO: Port to Scriptographer:
					preventDefault: function() {
						if (event.preventDefault) {
							event.preventDefault();
						} else {
							event.returnValue = false;
						}
					}
				}
				var res = paper.tool[toolHandler](keyEvent);
				// TODO: Port to Scriptographer:
				// When the handler function returns false, prevent the
				// default behaviour of the key event:
				if (res === false)
					keyEvent.preventDefault();
			}
		};
	}, {});
	Event.add(document, eventHandlers);

	return {
		modifiers: modifiers,
		isDown: function(key) {
			return !!activeKeys[key];
		}
	};
};<commit_msg>Some changes to Key code, rename alt to option to go with Scriptographer, and check for paper.toolt to exist since it caused errors when reloading a page.<commit_after>var Key = new function() {
	// TODO: make sure the keys are called the same as in Scriptographer
	// Missing: tab, cancel, clear, pause, page-down, page-up, end, home, comma,
	// minus, period, slash, etc etc etc.
	var keys = {
		 '8': 'backspace',
		'13': 'enter',
		'16': 'shift',
		'17': 'control',
		'19': 'option', // was alt
		'20': 'capsLock',
		'27': 'escape',
		'32': 'space',
		'37': 'left',
		'38': 'up',
		'39': 'right',
		'40': 'down',
		'46': 'delete',
		'91': 'command'
	},
	modifiers = {
		shift: false,
		control: false,
		option: false,
		command: false,
		capsLock: false
	},
	activeKeys = {};

	Event.add(document, Base.each(['keyDown', 'keyUp'], function(type) {
		var toolHandler = 'on' + Base.capitalize(type),
			keyDown = type == 'keyDown';
		this[type.toLowerCase()] = function(event) {
			var code = event.which || event.keyCode,
				key = keys[code] || String.fromCharCode(code).toLowerCase();
			activeKeys[key] = keyDown;

			// If the key is a modifier, update the modifiers:
			if (modifiers[key] !== undefined)
				modifiers[key] = keyDown;

			// Call the onKeyDown or onKeyUp handler if present:
			// TODO: don't call the key handler if the key is a modifier?
			if (paper.tool && paper.tool[toolHandler]) {
				// TODO: Introduce a class for this?
				var keyEvent = {
					type: keyDown ? 'key-down' : 'key-up',
					keyCode: code,
					character: key,
					modifiers: modifiers,
					// 'preventDefault: event.preventDefault' throws
					// an error in Safari when called, so we have to wrap
					// it into a function.
					// TODO: Port to Scriptographer:
					preventDefault: function() {
						if (event.preventDefault) {
							event.preventDefault();
						} else {
							event.returnValue = false;
						}
					}
				}
				var res = paper.tool[toolHandler](keyEvent);
				// TODO: Port to Scriptographer:
				// When the handler function returns false, prevent the
				// default behaviour of the key event:
				if (res === false)
					keyEvent.preventDefault();
			}
		};
	}, {}));

	return {
		modifiers: modifiers,
		isDown: function(key) {
			return !!activeKeys[key];
		}
	};
};<|endoftext|>


<commit_before>var Application = require('spectron').Application;
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
var electron = require('electron-prebuilt');

global.before(function () {
    chai.should()
    chai.use(chaiAsPromised)
});

beforeEach(function () {
    this.app = new Application({
        path: electron,
        args: ['electron-app']
    });
    return this.app.start()
});

beforeEach(function () {
    chaiAsPromised.transferPromiseness = this.app.transferPromiseness
});

afterEach(function () {
    if (this.app && this.app.isRunning()) {
        return this.app.stop()
    }
});<commit_msg>consolidate before each into one<commit_after>var Application = require('spectron').Application;
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
var electron = require('electron-prebuilt');

global.before(function () {
    chai.should()
    chai.use(chaiAsPromised)
});

beforeEach(function () {
    this.app = new Application({
        path: electron,
        args: ['electron-app']
    });
    return this.app.start().then(function (app) {
        chaiAsPromised.transferPromiseness = app.transferPromiseness;
        return app
    })
});

afterEach(function () {
    if (this.app && this.app.isRunning()) {
        return this.app.stop()
    }
});<|endoftext|>