<commit_before>/** @babel */

import elasticlunr from 'elasticlunr'
import fs from 'fs-plus'
import path from 'path'
import matter from 'gray-matter'
import * as NotesFs from './notes-fs'

let {EventEmitter} = require('events')
const {watchPath} = require('atom')

/**
  * @typedef DocumentItem
  * @type {Object}
  * @property {string} title - Title of the note.
  * @property {string} fileName - Name of the file where note is stored.
  * @property {string} filePath - Path to the file where note is stored.
  * @property {string} body - Body of the note.
  * @property {Array} keywords - Keywords of the note.
  * @property {Array} abstract - Summary of the note.
  * @property {Date} modifiedAt - Date and time of last modification to the note.
  */

/**
 * Builds a document object to hold state about a note document.
 * @param  {String} filePath Full path to the document.
 * @return {DocumentItem}
 */
function createDocument (filePath) {
  if (!fs.existsSync(filePath)) { return false }

  // we can't just check isFile() b/c we want to support symlinks to files
  let fileStats = fs.statSync(filePath)
  if (fileStats.isDirectory() ||
      fileStats.isBlockDevice() ||
      fileStats.isCharacterDevice() ||
      fileStats.isFIFO() ||
      fileStats.isSocket()) { return false }

  let fileName = path.basename(filePath)
  let title = path.basename(fileName, path.extname(fileName))
  let keywords = []
  let abstract = null

  let body
  try {
    body = fs.readFileSync(filePath, {encoding: 'utf8'})
  } catch (_) {
    // if we fail to read the file for whatever reason, let's ignore the file
    return false
  }

  let meta
  try {
    meta = matter(body).data
  } catch (_) {
    // If YAML parsing fails, that's fine. We just won't have meta data.
  }

  if (meta !== undefined && meta.keywords !== undefined) {
    keywords = meta.keywords
  }

  if (meta !== undefined && meta.abstract !== undefined) {
    abstract = meta.abstract
  }

  try {
    return {
      filePath: filePath,
      fileName: fileName,
      title: title,
      modifiedAt: fileStats.mtime,
      body: body,
      keywords: keywords,
      abstract: abstract
    }
  } catch (_) {
    return {}
  }
}

async function setupFileWatcher (directoryPath) {
  const watchedDirectory = fs.normalize(directoryPath)
  fs.listTreeSync(watchedDirectory).forEach(path => {
    if (!fs.isDirectorySync(path)) {
      if (NotesFs.isNote(path)) {
        this.addDocument(createDocument(path))
      }
    }
  })
  return watchPath(watchedDirectory, {}, events => {
    for (const event of events) {
      if (event.action === 'created') {
        this.addDocument(createDocument(event.path))
      } else if (event.action === 'modified') {
        this.updateDocument(createDocument(event.path))
      } else if (event.action === 'deleted') {
        this.removeDocument(this._documents[event.path])
      } else if (event.action === 'renamed') {
        this.removeDocument(this._documents[event.oldPath])
        this.addDocument(createDocument(event.path))
      }
    }
  })
}

class NotesStore extends EventEmitter {
  /**
   * Document storage for notes.
   * @param {String}   directoryPath Full path to where notes are stored.
   * @param {String[]} extensions    File extensions of notes.
   * @param {Object}   [index=null]  Serialized elasticlunr index to load.
   */
  constructor (directoryPath, extensions, index = null) {
    super()
    this.directoryPath = directoryPath
    this.extensions = extensions
    this.index = index
    this._documents = {}
  }

  /**
   * Initialize document storage by creating the document index.
   * Emits "ready" when index is ready.
   */
  initialize () {
    if (this.index) {
      console.log('atom-notes: loading...')
      this.loaded = true
      this.index = elasticlunr.Index.load(this.index)
    } else {
      console.log('atom-notes: indexing...')
      this.loaded = false
      this.index = elasticlunr(function () {
        this.addField('title')
        this.addField('body')
        this.addField('keywords')
        this.addField('abstract')
      })
    }

    this.watcher = setupFileWatcher.bind(this)(this.directoryPath)
    this.emit('ready')
  }

  /**
   * Adds the given document to our index.
   * @param {DocumentItem} doc
   */
  addDocument (doc) {
    this._documents[doc.filePath] = doc
    let data = {
      id: doc.filePath,
      title: doc.title,
      body: doc.body,
      abstract: doc.abstract
    }
    if (doc.keywords && Array.isArray(doc.keywords)) {
      data.keywords = doc.keywords.join(', ')
    }
    this.index.addDoc(data)
    this.emit('added', doc)
  }

  /**
   * Updates the given document, identified by filePath, in our index.
   * @param {DocumentItem} doc
   */
  updateDocument (doc) {
    this._documents[doc.filePath] = doc
    let data = {
      id: doc.filePath,
      title: doc.title,
      body: doc.body,
      abstract: doc.abstract
    }
    if (doc.keywords && Array.isArray(doc.keywords)) {
      data.keywords = doc.keywords.join(', ')
    }
    this.index.updateDoc(data)
    this.emit('updated', doc)
  }

  /**
   * Removes the given document, identified by filePath, from our index.
   * @param {DocumentItem} doc
   */
  removeDocument (doc) {
    if (doc === undefined) { return false }
    delete this._documents[doc.filePath]
    let data = {
      id: doc.filePath,
      title: doc.title,
      body: doc.body,
      abstract: doc.abstract
    }
    if (doc.keywords && Array.isArray(doc.keywords)) {
      data.keywords = doc.keywords.join(', ')
    }
    this.index.removeDoc(data)
    this.emit('removed', doc)
  }

  /**
   * Search for notes in our document store.
   * @param  {String} query Some text to use for matching indexed documents.
   * @return {DocumentItem[]}
   */
  search (query) {
    const config = {
      fields: {
        keywords: { boost: 20, bool: 'AND' },
        title: { boost: 10, bool: 'AND' },
        abstract: { boost: 5, bool: 'AND' },
        body: { boost: 1 }
      },
      bool: 'OR',
      expand: true
    }
    return this.index.search(query, config).map(result => {
      return this._documents[result.ref]
    })
  }

  /**
   * Fetch all documents in our index.
   * @return {DocumentItem[]}
   */
  get documents () {
    var documents = []
    for (let key in this._documents) {
      documents.push(this._documents[key])
    }
    return documents.sort((a, b) => {
      if (a.modifiedAt < b.modifiedAt) return 1
      if (a.modifiedAt > b.modifiedAt) return -1
      return 0
    })
  }
}

module.exports = NotesStore
<commit_msg>Adds catches for a possible error state.<commit_after>/** @babel */

import elasticlunr from 'elasticlunr'
import fs from 'fs-plus'
import path from 'path'
import matter from 'gray-matter'
import * as NotesFs from './notes-fs'

let {EventEmitter} = require('events')
const {watchPath} = require('atom')

function isEmpty (obj) {
  return Object.keys(obj).length === 0 && obj.constructor === Object
}

/**
  * @typedef DocumentItem
  * @type {Object}
  * @property {string} title - Title of the note.
  * @property {string} fileName - Name of the file where note is stored.
  * @property {string} filePath - Path to the file where note is stored.
  * @property {string} body - Body of the note.
  * @property {Array} keywords - Keywords of the note.
  * @property {Array} abstract - Summary of the note.
  * @property {Date} modifiedAt - Date and time of last modification to the note.
  */

/**
 * Builds a document object to hold state about a note document.
 * @param  {String} filePath Full path to the document.
 * @return {DocumentItem}
 */
function createDocument (filePath) {
  if (!fs.existsSync(filePath)) { return false }

  // we can't just check isFile() b/c we want to support symlinks to files
  let fileStats = fs.statSync(filePath)
  if (fileStats.isDirectory() ||
      fileStats.isBlockDevice() ||
      fileStats.isCharacterDevice() ||
      fileStats.isFIFO() ||
      fileStats.isSocket()) { return false }

  let fileName = path.basename(filePath)
  let title = path.basename(fileName, path.extname(fileName))
  let keywords = []
  let abstract = null

  let body
  try {
    body = fs.readFileSync(filePath, {encoding: 'utf8'})
  } catch (_) {
    // if we fail to read the file for whatever reason, let's ignore the file
    return false
  }

  let meta
  try {
    meta = matter(body).data
  } catch (_) {
    // If YAML parsing fails, that's fine. We just won't have meta data.
  }

  if (meta !== undefined && meta.keywords !== undefined) {
    keywords = meta.keywords
  }

  if (meta !== undefined && meta.abstract !== undefined) {
    abstract = meta.abstract
  }

  try {
    return {
      filePath: filePath,
      fileName: fileName,
      title: title,
      modifiedAt: fileStats.mtime,
      body: body,
      keywords: keywords,
      abstract: abstract
    }
  } catch (_) {
    return {}
  }
}

async function setupFileWatcher (directoryPath) {
  const watchedDirectory = fs.normalize(directoryPath)
  fs.listTreeSync(watchedDirectory).forEach(path => {
    if (!fs.isDirectorySync(path)) {
      if (NotesFs.isNote(path)) {
        this.addDocument(createDocument(path))
      }
    }
  })
  return watchPath(watchedDirectory, {}, events => {
    for (const event of events) {
      if (event.action === 'created') {
        this.addDocument(createDocument(event.path))
      } else if (event.action === 'modified') {
        this.updateDocument(createDocument(event.path))
      } else if (event.action === 'deleted') {
        this.removeDocument(this._documents[event.path])
      } else if (event.action === 'renamed') {
        this.removeDocument(this._documents[event.oldPath])
        this.addDocument(createDocument(event.path))
      }
    }
  })
}

class NotesStore extends EventEmitter {
  /**
   * Document storage for notes.
   * @param {String}   directoryPath Full path to where notes are stored.
   * @param {String[]} extensions    File extensions of notes.
   * @param {Object}   [index=null]  Serialized elasticlunr index to load.
   */
  constructor (directoryPath, extensions, index = null) {
    super()
    this.directoryPath = directoryPath
    this.extensions = extensions
    this.index = index
    this._documents = {}
  }

  /**
   * Initialize document storage by creating the document index.
   * Emits "ready" when index is ready.
   */
  initialize () {
    if (this.index) {
      console.log('atom-notes: loading...')
      this.loaded = true
      this.index = elasticlunr.Index.load(this.index)
    } else {
      console.log('atom-notes: indexing...')
      this.loaded = false
      this.index = elasticlunr(function () {
        this.addField('title')
        this.addField('body')
        this.addField('keywords')
        this.addField('abstract')
      })
    }

    this.watcher = setupFileWatcher.bind(this)(this.directoryPath)
    this.emit('ready')
  }

  /**
   * Adds the given document to our index.
   * @param {DocumentItem} doc
   */
  addDocument (doc) {
    if (isEmpty(doc)) return
    this._documents[doc.filePath] = doc
    let data = {
      id: doc.filePath,
      title: doc.title,
      body: doc.body,
      abstract: doc.abstract
    }
    if (doc.keywords && Array.isArray(doc.keywords)) {
      data.keywords = doc.keywords.join(', ')
    }
    this.index.addDoc(data)
    this.emit('added', doc)
  }

  /**
   * Updates the given document, identified by filePath, in our index.
   * @param {DocumentItem} doc
   */
  updateDocument (doc) {
    if (isEmpty(doc)) return
    this._documents[doc.filePath] = doc
    let data = {
      id: doc.filePath,
      title: doc.title,
      body: doc.body,
      abstract: doc.abstract
    }
    if (doc.keywords && Array.isArray(doc.keywords)) {
      data.keywords = doc.keywords.join(', ')
    }
    this.index.updateDoc(data)
    this.emit('updated', doc)
  }

  /**
   * Removes the given document, identified by filePath, from our index.
   * @param {DocumentItem} doc
   */
  removeDocument (doc) {
    if (isEmpty(doc)) return false
    if (doc === undefined) return false
    delete this._documents[doc.filePath]
    let data = {
      id: doc.filePath,
      title: doc.title,
      body: doc.body,
      abstract: doc.abstract
    }
    if (doc.keywords && Array.isArray(doc.keywords)) {
      data.keywords = doc.keywords.join(', ')
    }
    this.index.removeDoc(data)
    this.emit('removed', doc)
  }

  /**
   * Search for notes in our document store.
   * @param  {String} query Some text to use for matching indexed documents.
   * @return {DocumentItem[]}
   */
  search (query) {
    const config = {
      fields: {
        keywords: { boost: 20, bool: 'AND' },
        title: { boost: 10, bool: 'AND' },
        abstract: { boost: 5, bool: 'AND' },
        body: { boost: 1 }
      },
      bool: 'OR',
      expand: true
    }
    return this.index.search(query, config).map(result => {
      return this._documents[result.ref]
    })
  }

  /**
   * Fetch all documents in our index.
   * @return {DocumentItem[]}
   */
  get documents () {
    var documents = []
    for (let key in this._documents) {
      documents.push(this._documents[key])
    }
    return documents.sort((a, b) => {
      if (a.modifiedAt < b.modifiedAt) return 1
      if (a.modifiedAt > b.modifiedAt) return -1
      return 0
    })
  }
}

module.exports = NotesStore
<|endoftext|>


<commit_before>document.addEventListener('DOMContentLoaded', () => {
	/* Backgrounds */

	const currentDate = new Date();
	const setDate = (month, day) => new Date(currentDate.getFullYear(), month, day);

	let backgroundSetting = localStorage.getItem('background');
	const backgrounds = ['bg1', 'bg2', 'bg3', 'bg4', 'bg5', 'bg6', 'bg7', 'bg8'];
	const seasonalBackgrounds = [ // All months are 0-indexed! E.g. 11 is December
		{ filename: 'bg1_independence', displayName: 'Independence Day', start: setDate(6, 10), end: setDate(6, 16) },
		{ filename: 'bg1_christmas', displayName: 'Christmas', start: setDate(11, 15), end: setDate(11, 27) },
		{ filename: 'bg1_halloween', displayName: 'Halloween', start: setDate(9, 24), end: setDate(10, 3) },
		{ filename: 'bg1_easter', displayName: 'Easter', start: setDate(3, 15), end: setDate(3, 28) },
		// { filename: 'bg1_birthday', displayName: 'Birthday', start: setDate(0, 15), end: setDate(0, 28) }
		// No canon confirmation of the birthday month, January is speculation
	];
	const randomBg = backgrounds[Math.floor(Math.random() * backgrounds.length)];

	let preferSeasonals = localStorage.getItem('preferSeasonals');

	const bodyElem = document.body;
	const bgSelect = document.getElementById('bg-select');
	const preferSeasonalsToggle = document.getElementById('prefer-seasonals-toggle');

	if (!backgroundSetting || preferSeasonals) {
		const fittingSeasonalBackground = seasonalBackgrounds.find(sBg => currentDate >= sBg.start && currentDate <= sBg.end);
		if (fittingSeasonalBackground) backgroundSetting = fittingSeasonalBackground.filename;
		else if (!backgroundSetting) backgroundSetting = 'randomBg'; // Only applies when there is no preference & no seasonal
	}

	bodyElem.classList.add(backgroundSetting !== 'randomBg' ? backgroundSetting : randomBg);

	let currentBg = backgroundSetting === 'randomBg' ? randomBg : backgroundSetting;

	bgSelect.addEventListener('change', e => {
		const { value } = e.target;

		if (value === 'reset') {
			return localStorage.removeItem('background');
		}
		if (value !== 'randomBg') {
			bodyElem.classList.remove(currentBg);
			bodyElem.classList.add(value);

			currentBg = value;
		}
		return localStorage.setItem('background', value);
	});

	const bgOptions = backgrounds.map(bg => `<option value="${bg}">Background ${bg.substr(2)}</option>`);
	bgOptions.push(seasonalBackgrounds.map(seasonal => `<option value="${seasonal.filename}">${seasonal.displayName}</option>`));
	bgOptions.unshift('<option value="randomBg">Random (Default)</option>');
	bgOptions.unshift('<option value="reset">Reset Preference</option>');

	bgSelect.innerHTML = bgOptions.join('');
	bgSelect.value = backgroundSetting;

	preferSeasonalsToggle.checked = preferSeasonals;
	preferSeasonalsToggle.addEventListener('change', e => {
		if (e.target.checked) localStorage.setItem('preferSeasonals', true);
		else localStorage.removeItem('preferSeasonals');

		return preferSeasonals = e.target.checked;
	});

	/* Crazy mode */

	const crazyModeToggle = document.getElementById('crazymode-toggle');
	let crazyMode = localStorage.getItem('crazyMode');

	crazyModeToggle.checked = crazyMode;
	crazyModeToggle.addEventListener('change', e => {
		if (e.target.checked) localStorage.setItem('crazyMode', true);
		else localStorage.removeItem('crazyMode');

		return crazyMode = e.target.checked;
	});

	/* Util funcs */

	const util = {};

	util.fade = function(elem, displayDuration = 2000, step = 0.1) {
		elem.style.display = 'block';
		elem.style.opacity = 0;
		let fadedIn = false;
		let delayOver = false;

		const fadeInterval = setInterval(() => {
			if (elem.style.opacity === '1') {
				fadedIn = true; // So it doesn't increase opacity infinitely beyond 1
				if (!delayOver) setTimeout(() => delayOver = true, displayDuration);
			}
			if (elem.style.opacity < 1 && !fadedIn) elem.style.opacity = parseFloat(elem.style.opacity) + step;

			if (elem.style.opacity > 0 && delayOver) elem.style.opacity = parseFloat(elem.style.opacity) - step;
			if (elem.style.opacity === '0') {
				elem.style.display = 'none';
				clearInterval(fadeInterval);
			}
		}, 100);
	};

	window.util = util;
});<commit_msg>Change birthday date<commit_after>document.addEventListener('DOMContentLoaded', () => {
	/* Backgrounds */

	const currentDate = new Date();
	const setDate = (month, day) => new Date(currentDate.getFullYear(), month, day);

	let backgroundSetting = localStorage.getItem('background');
	const backgrounds = ['bg1', 'bg2', 'bg3', 'bg4', 'bg5', 'bg6', 'bg7', 'bg8'];
	const seasonalBackgrounds = [ // All months are 0-indexed! E.g. 11 is December
		{ filename: 'bg1_independence', displayName: 'Independence Day', start: setDate(6, 10), end: setDate(6, 16) },
		{ filename: 'bg1_christmas', displayName: 'Christmas', start: setDate(11, 15), end: setDate(11, 27) },
		{ filename: 'bg1_halloween', displayName: 'Halloween', start: setDate(9, 24), end: setDate(10, 3) },
		{ filename: 'bg1_easter', displayName: 'Easter', start: setDate(3, 15), end: setDate(3, 28) },
		// { filename: 'bg1_birthday', displayName: 'Birthday', start: setDate(11, 1), end: setDate(11, 6) }
		// Birthday is the 4th of December, apparently (from KonoSuba Discord)
	];
	const randomBg = backgrounds[Math.floor(Math.random() * backgrounds.length)];

	let preferSeasonals = localStorage.getItem('preferSeasonals');

	const bodyElem = document.body;
	const bgSelect = document.getElementById('bg-select');
	const preferSeasonalsToggle = document.getElementById('prefer-seasonals-toggle');

	if (!backgroundSetting || preferSeasonals) {
		const fittingSeasonalBackground = seasonalBackgrounds.find(sBg => currentDate >= sBg.start && currentDate <= sBg.end);
		if (fittingSeasonalBackground) backgroundSetting = fittingSeasonalBackground.filename;
		else if (!backgroundSetting) backgroundSetting = 'randomBg'; // Only applies when there is no preference & no seasonal
	}

	bodyElem.classList.add(backgroundSetting !== 'randomBg' ? backgroundSetting : randomBg);

	let currentBg = backgroundSetting === 'randomBg' ? randomBg : backgroundSetting;

	bgSelect.addEventListener('change', e => {
		const { value } = e.target;

		if (value === 'reset') {
			return localStorage.removeItem('background');
		}
		if (value !== 'randomBg') {
			bodyElem.classList.remove(currentBg);
			bodyElem.classList.add(value);

			currentBg = value;
		}
		return localStorage.setItem('background', value);
	});

	const bgOptions = backgrounds.map(bg => `<option value="${bg}">Background ${bg.substr(2)}</option>`);
	bgOptions.push(seasonalBackgrounds.map(seasonal => `<option value="${seasonal.filename}">${seasonal.displayName}</option>`));
	bgOptions.unshift('<option value="randomBg">Random (Default)</option>');
	bgOptions.unshift('<option value="reset">Reset Preference</option>');

	bgSelect.innerHTML = bgOptions.join('');
	bgSelect.value = backgroundSetting;

	preferSeasonalsToggle.checked = preferSeasonals;
	preferSeasonalsToggle.addEventListener('change', e => {
		if (e.target.checked) localStorage.setItem('preferSeasonals', true);
		else localStorage.removeItem('preferSeasonals');

		return preferSeasonals = e.target.checked;
	});

	/* Crazy mode */

	const crazyModeToggle = document.getElementById('crazymode-toggle');
	let crazyMode = localStorage.getItem('crazyMode');

	crazyModeToggle.checked = crazyMode;
	crazyModeToggle.addEventListener('change', e => {
		if (e.target.checked) localStorage.setItem('crazyMode', true);
		else localStorage.removeItem('crazyMode');

		return crazyMode = e.target.checked;
	});

	/* Util funcs */

	const util = {};

	util.fade = function(elem, displayDuration = 2000, step = 0.1) {
		elem.style.display = 'block';
		elem.style.opacity = 0;
		let fadedIn = false;
		let delayOver = false;

		const fadeInterval = setInterval(() => {
			if (elem.style.opacity === '1') {
				fadedIn = true; // So it doesn't increase opacity infinitely beyond 1
				if (!delayOver) setTimeout(() => delayOver = true, displayDuration);
			}
			if (elem.style.opacity < 1 && !fadedIn) elem.style.opacity = parseFloat(elem.style.opacity) + step;

			if (elem.style.opacity > 0 && delayOver) elem.style.opacity = parseFloat(elem.style.opacity) - step;
			if (elem.style.opacity === '0') {
				elem.style.display = 'none';
				clearInterval(fadeInterval);
			}
		}, 100);
	};

	window.util = util;
});<|endoftext|>


<commit_before>// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE

(function(mod) {
  if (typeof exports == "object" && typeof module == "object") // CommonJS
    mod(require("../../lib/codemirror"));
  else if (typeof define == "function" && define.amd) // AMD
    define(["../../lib/codemirror"], mod);
  else // Plain browser env
    mod(CodeMirror);
})(function(CodeMirror) {
  "use strict";

  function Bar(cls, orientation, scroll) {
    this.orientation = orientation;
    this.scroll = scroll;
    this.screen = this.total = this.size = 1;
    this.pos = 0;

    this.node = document.createElement("div");
    this.node.className = cls + "-" + orientation;
    this.inner = this.node.appendChild(document.createElement("div"));

    var self = this;
    CodeMirror.on(this.inner, "mousedown", function(e) {
      if (e.which != 1) return;
      CodeMirror.e_preventDefault(e);
      var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
      var start = e[axis], startpos = self.pos;
      function done() {
        CodeMirror.off(document, "mousemove", move);
        CodeMirror.off(document, "mouseup", done);
      }
      function move(e) {
        if (e.which != 1) return done();
        self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
      }
      CodeMirror.on(document, "mousemove", move);
      CodeMirror.on(document, "mouseup", done);
    });

    CodeMirror.on(this.node, "click", function(e) {
      CodeMirror.e_preventDefault(e);
      var innerBox = self.inner.getBoundingClientRect(), where;
      if (self.orientation == "horizontal")
        where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
      else
        where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
      self.moveTo(self.pos + where * self.screen);
    });

    function onWheel(e) {
      var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
      var oldPos = self.pos;
      self.moveTo(self.pos + moved);
      if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
    }
    CodeMirror.on(this.node, "mousewheel", onWheel);
    CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
  }

  Bar.prototype.setPos = function(pos) {
    if (pos < 0) pos = 0;
    if (pos > this.total - this.screen) pos = this.total - this.screen;
    if (pos == this.pos) return false;
    this.pos = pos;
    this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
      (pos * (this.size / this.total)) + "px";
    return true
  };

  Bar.prototype.moveTo = function(pos) {
    if (this.setPos(pos)) this.scroll(pos, this.orientation);
  }

  var minButtonSize = 10;

  Bar.prototype.update = function(scrollSize, clientSize, barSize) {
    this.screen = clientSize;
    this.total = scrollSize;
    this.size = barSize;

    var buttonSize = this.screen * (this.size / this.total);
    if (buttonSize < minButtonSize) {
      this.size -= minButtonSize - buttonSize;
      buttonSize = minButtonSize;
    }
    this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
      buttonSize + "px";
    this.setPos(this.pos);
  };

  function SimpleScrollbars(cls, place, scroll) {
    this.addClass = cls;
    this.horiz = new Bar(cls, "horizontal", scroll);
    place(this.horiz.node);
    this.vert = new Bar(cls, "vertical", scroll);
    place(this.vert.node);
    this.width = null;
  }

  SimpleScrollbars.prototype.update = function(measure) {
    if (this.width == null) {
      var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
      if (style) this.width = parseInt(style.height);
    }
    var width = this.width || 0;

    var needsH = measure.scrollWidth > measure.clientWidth + 1;
    var needsV = measure.scrollHeight > measure.clientHeight + 1;
    this.vert.node.style.display = needsV ? "block" : "none";
    this.horiz.node.style.display = needsH ? "block" : "none";

    if (needsV) {
      this.vert.update(measure.scrollHeight, measure.clientHeight,
                       measure.viewHeight - (needsH ? width : 0));
      this.vert.node.style.bottom = needsH ? width + "px" : "0";
    }
    if (needsH) {
      this.horiz.update(measure.scrollWidth, measure.clientWidth,
                        measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
      this.horiz.node.style.right = needsV ? width + "px" : "0";
      this.horiz.node.style.left = measure.barLeft + "px";
    }

    return {right: needsV ? width : 0, bottom: needsH ? width : 0};
  };

  SimpleScrollbars.prototype.setScrollTop = function(pos) {
    this.vert.setPos(pos);
  };

  SimpleScrollbars.prototype.setScrollLeft = function(pos) {
    this.horiz.setPos(pos);
  };

  SimpleScrollbars.prototype.clear = function() {
    var parent = this.horiz.node.parentNode;
    parent.removeChild(this.horiz.node);
    parent.removeChild(this.vert.node);
  };

  CodeMirror.scrollbarModel.simple = function(place, scroll) {
    return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
  };
  CodeMirror.scrollbarModel.overlay = function(place, scroll) {
    return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
  };
});
<commit_msg>[simplescrollbars addon] Make sure thumb position is updated when size changes<commit_after>// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE

(function(mod) {
  if (typeof exports == "object" && typeof module == "object") // CommonJS
    mod(require("../../lib/codemirror"));
  else if (typeof define == "function" && define.amd) // AMD
    define(["../../lib/codemirror"], mod);
  else // Plain browser env
    mod(CodeMirror);
})(function(CodeMirror) {
  "use strict";

  function Bar(cls, orientation, scroll) {
    this.orientation = orientation;
    this.scroll = scroll;
    this.screen = this.total = this.size = 1;
    this.pos = 0;

    this.node = document.createElement("div");
    this.node.className = cls + "-" + orientation;
    this.inner = this.node.appendChild(document.createElement("div"));

    var self = this;
    CodeMirror.on(this.inner, "mousedown", function(e) {
      if (e.which != 1) return;
      CodeMirror.e_preventDefault(e);
      var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
      var start = e[axis], startpos = self.pos;
      function done() {
        CodeMirror.off(document, "mousemove", move);
        CodeMirror.off(document, "mouseup", done);
      }
      function move(e) {
        if (e.which != 1) return done();
        self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
      }
      CodeMirror.on(document, "mousemove", move);
      CodeMirror.on(document, "mouseup", done);
    });

    CodeMirror.on(this.node, "click", function(e) {
      CodeMirror.e_preventDefault(e);
      var innerBox = self.inner.getBoundingClientRect(), where;
      if (self.orientation == "horizontal")
        where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
      else
        where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
      self.moveTo(self.pos + where * self.screen);
    });

    function onWheel(e) {
      var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
      var oldPos = self.pos;
      self.moveTo(self.pos + moved);
      if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
    }
    CodeMirror.on(this.node, "mousewheel", onWheel);
    CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
  }

  Bar.prototype.setPos = function(pos, force) {
    if (pos < 0) pos = 0;
    if (pos > this.total - this.screen) pos = this.total - this.screen;
    if (!force && pos == this.pos) return false;
    this.pos = pos;
    this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
      (pos * (this.size / this.total)) + "px";
    return true
  };

  Bar.prototype.moveTo = function(pos) {
    if (this.setPos(pos)) this.scroll(pos, this.orientation);
  }

  var minButtonSize = 10;

  Bar.prototype.update = function(scrollSize, clientSize, barSize) {
    var sizeChanged = this.screen != clientSize || this.total != scrollSize || this.size != barSize
    if (sizeChanged) {
      this.screen = clientSize;
      this.total = scrollSize;
      this.size = barSize;
    }

    var buttonSize = this.screen * (this.size / this.total);
    if (buttonSize < minButtonSize) {
      this.size -= minButtonSize - buttonSize;
      buttonSize = minButtonSize;
    }
    this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
      buttonSize + "px";
    this.setPos(this.pos, sizeChanged);
  };

  function SimpleScrollbars(cls, place, scroll) {
    this.addClass = cls;
    this.horiz = new Bar(cls, "horizontal", scroll);
    place(this.horiz.node);
    this.vert = new Bar(cls, "vertical", scroll);
    place(this.vert.node);
    this.width = null;
  }

  SimpleScrollbars.prototype.update = function(measure) {
    if (this.width == null) {
      var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
      if (style) this.width = parseInt(style.height);
    }
    var width = this.width || 0;

    var needsH = measure.scrollWidth > measure.clientWidth + 1;
    var needsV = measure.scrollHeight > measure.clientHeight + 1;
    this.vert.node.style.display = needsV ? "block" : "none";
    this.horiz.node.style.display = needsH ? "block" : "none";

    if (needsV) {
      this.vert.update(measure.scrollHeight, measure.clientHeight,
                       measure.viewHeight - (needsH ? width : 0));
      this.vert.node.style.bottom = needsH ? width + "px" : "0";
    }
    if (needsH) {
      this.horiz.update(measure.scrollWidth, measure.clientWidth,
                        measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
      this.horiz.node.style.right = needsV ? width + "px" : "0";
      this.horiz.node.style.left = measure.barLeft + "px";
    }

    return {right: needsV ? width : 0, bottom: needsH ? width : 0};
  };

  SimpleScrollbars.prototype.setScrollTop = function(pos) {
    this.vert.setPos(pos);
  };

  SimpleScrollbars.prototype.setScrollLeft = function(pos) {
    this.horiz.setPos(pos);
  };

  SimpleScrollbars.prototype.clear = function() {
    var parent = this.horiz.node.parentNode;
    parent.removeChild(this.horiz.node);
    parent.removeChild(this.vert.node);
  };

  CodeMirror.scrollbarModel.simple = function(place, scroll) {
    return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
  };
  CodeMirror.scrollbarModel.overlay = function(place, scroll) {
    return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
  };
});
<|endoftext|>


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

  angular.module('Library',[])
    .controller('LibraryController',function(){
      var vm = this;
      vm.newBook = {};
      vm.category = {};

      vm.books = [
        {
          category: 'Fiction',
          bookTitle: 'War and Peace',
          author: 'Leo Tolstoy',
          rating: 4,
          read: true
        },
        {
          category: 'Non-Fiction',
          bookTitle: 'The Big Bang',
          author: 'Simon Singh',
          rating: 3,
          read: true
        },
        {
          category: 'Fiction',
          bookTitle: 'Foundation',
          author: 'Issac Asimov',
          rating: 4,
          read: false
        },
        {
          category: 'Non-Fiction',
          bookTitle: 'The White Mouse',
          author: 'Nancy Wake',
          rating: 5,
          read: false
        },
        {
          category: 'Fiction',
          bookTitle: 'The Martian Chronicles',
          author: 'Ray Bradbury',
          rating: 2,
          read: true
        }
      ];

      vm.rating = {
        one: 1,
        two: 2,
        three: 3,
        four: 4,
        five: 5
      };

      vm.category = {
        fiction: 'Fiction',
        nonFiction: 'Non-Fiction'
      };

    vm.addNewBook = function(){
      console.log("called")
      vm.books.push(vm.newBook);
      vm.newBook = {};
    };
  });
})();

<commit_msg>book objects stored on Firebase<commit_after>;(function(){
  'use strict';

  angular.module('Library',[])
    .controller('LibraryController',function($http){
      //private vars
      var vm = this;

      //private functions
      $http.get('https://bcd-library.firebaseio.com/books.json')
        .success(function(data){
          vm.books = data;
        })
        .error(function(err){
          console.log('book error: ' + err);
        });

      //public vars
      vm.newBook = {};
      vm.rating = {
        one: 1,
        two: 2,
        three: 3,
        four: 4,
        five: 5
      };
      vm.category = {
        fiction: 'Fiction',
        nonFiction: 'Non-Fiction'
      };

      //public functions
      vm.addNewBook = function(){
        $http.post('https://bcd-library.firebaseio.com/books.json',vm.newBook)
        .success(function(data){
          vm.books[data.name] = vm.newBook;
          vm.newBook = {};
        })
        .error(function(err){
          console.log('add Book error:' + err);
        });
      };
    });
})();

<|endoftext|>


<commit_before>(function(){

function updateStatus(statusEl, result){
	statusEl.removeClass('success error loading-small');
	if (result && result.status == 'success' && result.data.message) {
		statusEl.addClass('success');
		return true;
	} else {
		statusEl.addClass('error');
		return false;
	}
}

OC.MountConfig={
	saveStorage:function(tr, callback) {
		var mountPoint = $(tr).find('.mountPoint input').val();
		if (mountPoint == '') {
			return false;
		}
		var statusSpan = $(tr).closest('tr').find('.status span');
		var backendClass = $(tr).find('.backend').data('class');
		var configuration = $(tr).find('.configuration input');
		var addMountPoint = true;
		if (configuration.length < 1) {
			return false;
		}
		var classOptions = {};
		$.each(configuration, function(index, input) {
			if ($(input).val() == '' && !$(input).hasClass('optional')) {
				addMountPoint = false;
				return false;
			}
			if ($(input).is(':checkbox')) {
				if ($(input).is(':checked')) {
					classOptions[$(input).data('parameter')] = true;
				} else {
					classOptions[$(input).data('parameter')] = false;
				}
			} else {
				classOptions[$(input).data('parameter')] = $(input).val();
			}
		});
		if ($('#externalStorage').data('admin') === true) {
			var multiselect = $(tr).find('.chzn-select').val();
			if (multiselect == null) {
				return false;
			}
		}
		if (addMountPoint) {
			var status = false;
			if ($('#externalStorage').data('admin') === true) {
				var isPersonal = false;
				var oldGroups = $(tr).find('.applicable').data('applicable-groups');
				var oldUsers = $(tr).find('.applicable').data('applicable-users');
				var groups = [];
				var users = [];
				$.each(multiselect, function(index, value) {
					var pos = value.indexOf('(group)');
					if (pos != -1) {
						var mountType = 'group';
						var applicable = value.substr(0, pos);
						if ($.inArray(applicable, oldGroups) != -1) {
							oldGroups.splice($.inArray(applicable, oldGroups), 1);
						}
						groups.push(applicable);
					} else {
						var mountType = 'user';
						var applicable = value;
						if ($.inArray(applicable, oldUsers) != -1) {
							oldUsers.splice($.inArray(applicable, oldUsers), 1);
						}
						users.push(applicable);
					}
					statusSpan.addClass('loading-small').removeClass('error success');
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'addMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						},
						success: function(result) {
							status = updateStatus(statusSpan, result);
							if (callback) {
								callback(status);
							}
						},
						error: function(result){
							status = updateStatus(statusSpan, result);
							if (callback) {
								callback(status);
							}
						}
					});
				});
				$(tr).find('.applicable').data('applicable-groups', groups);
				$(tr).find('.applicable').data('applicable-users', users);
				var mountType = 'group';
				$.each(oldGroups, function(index, applicable) {
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						}
					});
				});
				var mountType = 'user';
				$.each(oldUsers, function(index, applicable) {
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						}
					});
				});
			} else {
				var isPersonal = true;
				var mountType = 'user';
				var applicable = OC.currentUser;
				statusSpan.addClass('loading-small').removeClass('error success');
				$.ajax({type: 'POST',
					url: OC.filePath('files_external', 'ajax', 'addMountPoint.php'),
					data: {
						mountPoint: mountPoint,
						'class': backendClass,
						classOptions: classOptions,
						mountType: mountType,
						applicable: applicable,
						isPersonal: isPersonal
					},
					success: function(result) {
						status = updateStatus(statusSpan, result);
						if (callback) {
							callback(status);
						}
					},
					error: function(result){
						status = updateStatus(statusSpan, result);
						if (callback) {
							callback(status);
						}
					}
				});
			}
			return status;
		}
	}
};

$(document).ready(function() {
	$('.chzn-select').chosen();

	$('#externalStorage').on('change', '#selectBackend', function() {
		var tr = $(this).parent().parent();
		$('#externalStorage tbody').append($(tr).clone());
		$('#externalStorage tbody tr').last().find('.mountPoint input').val('');
		var selected = $(this).find('option:selected').text();
		var backendClass = $(this).val();
		$(this).parent().text(selected);
		if ($(tr).find('.mountPoint input').val() == '') {
			$(tr).find('.mountPoint input').val(suggestMountPoint(selected));
		}
		$(tr).addClass(backendClass);
		$(tr).find('.status').append('');
		$(tr).find('.backend').data('class', backendClass);
		var configurations = $(this).data('configurations');
		var td = $(tr).find('td.configuration');
		$.each(configurations, function(backend, parameters) {
			if (backend == backendClass) {
				$.each(parameters['configuration'], function(parameter, placeholder) {
					if (placeholder.indexOf('*') != -1) {
						td.append('<input type="password" data-parameter="'+parameter+'" placeholder="'+placeholder.substring(1)+'" />');
					} else if (placeholder.indexOf('!') != -1) {
						td.append('<input type="checkbox" data-parameter="'+parameter+'" />'+placeholder.substring(1)+'');
					} else if (placeholder.indexOf('&') != -1) {
						td.append('<input type="text" class="optional" data-parameter="'+parameter+'" placeholder="'+placeholder.substring(1)+'" />');
					} else if (placeholder.indexOf('#') != -1) {
						td.append('<input type="hidden" data-parameter="'+parameter+'" />');
					} else {
						td.append('<input type="text" data-parameter="'+parameter+'" placeholder="'+placeholder+'" />');
					}
				});
				if (parameters['custom'] && $('#externalStorage tbody tr.'+backendClass.replace(/\\/g, '\\\\')).length == 1) {
					OC.addScript('files_external', parameters['custom']);
				}
				return false;
			}
		});
		// Reset chosen
		var chosen = $(tr).find('.applicable select');
		chosen.parent().find('div').remove();
		chosen.removeAttr('id').removeClass('chzn-done').css({display:'inline-block'});
		chosen.chosen();
		$(tr).find('td').last().attr('class', 'remove');
		$(tr).find('td').last().removeAttr('style');
		$(tr).removeAttr('id');
		$(this).remove();
	});

	function suggestMountPoint(defaultMountPoint) {
		var pos = defaultMountPoint.indexOf('/');
		if (pos !== -1) {
			defaultMountPoint = defaultMountPoint.substring(0, pos);
		}
		defaultMountPoint = defaultMountPoint.replace(/\s+/g, '');
		var i = 1;
		var append = '';
		var match = true;
		while (match && i < 20) {
			match = false;
			$('#externalStorage tbody td.mountPoint input').each(function(index, mountPoint) {
				if ($(mountPoint).val() == defaultMountPoint+append) {
					match = true;
					return false;
				}
			});
			if (match) {
				append = i;
				i++;
			} else {
				break;
			}
		}
		return defaultMountPoint+append;
	}

	$('#externalStorage').on('paste', 'td', function() {
		var tr = $(this).parent();
		setTimeout(function() {
			OC.MountConfig.saveStorage(tr);
		}, 20);
	});

	var timer;

	$('#externalStorage').on('keyup', 'td input', function() {
		clearTimeout(timer);
		var tr = $(this).parent().parent();
		if ($(this).val) {
			timer = setTimeout(function() {
				OC.MountConfig.saveStorage(tr);
			}, 2000);
		}
	});

	$('#externalStorage').on('change', 'td input:checkbox', function() {
		OC.MountConfig.saveStorage($(this).parent().parent().parent());
	});

	$('#externalStorage').on('change', '.applicable .chzn-select', function() {
		OC.MountConfig.saveStorage($(this).parent().parent());
	});

	$('#sslCertificate').on('click', 'td.remove>img', function() {
		var $tr = $(this).parent().parent();
		var row = this.parentNode.parentNode;
		$.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), {cert: row.id});
		$tr.remove();
		return true;
	});

	$('#externalStorage').on('click', 'td.remove>img', function() {
		var tr = $(this).parent().parent();
		var mountPoint = $(tr).find('.mountPoint input').val();

		if ($('#externalStorage').data('admin') === true) {
			var isPersonal = false;
			var multiselect = $(tr).find('.chzn-select').val();
			if (multiselect != null) {
				$.each(multiselect, function(index, value) {
					var pos = value.indexOf('(group)');
					if (pos != -1) {
						var mountType = 'group';
						var applicable = value.substr(0, pos);
					} else {
						var mountType = 'user';
						var applicable = value;
					}
					$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
				});
			}
		} else {
			var mountType = 'user';
			var applicable = OC.currentUser;
			var isPersonal = true;
			$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
		}
		$(tr).remove();
	});

	$('#allowUserMounting').bind('change', function() {
		OC.msg.startSaving('#userMountingMsg');
		if (this.checked) {
			OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'yes');
			$('#userMountingBackups').removeClass('hidden');
		} else {
			OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'no');
			$('#userMountingBackups').addClass('hidden');
		}
		OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});
	});

	$('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() {
		OC.msg.startSaving('#userMountingMsg');
		var user_mounting_backends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get();
		OC.AppConfig.setValue('files_external', 'user_mounting_backends', user_mounting_backends.join());
		OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});
	});
});

})();
<commit_msg>Enable the use of 'optional' on password fields (JavaScript part)<commit_after>(function(){

function updateStatus(statusEl, result){
	statusEl.removeClass('success error loading-small');
	if (result && result.status == 'success' && result.data.message) {
		statusEl.addClass('success');
		return true;
	} else {
		statusEl.addClass('error');
		return false;
	}
}

OC.MountConfig={
	saveStorage:function(tr, callback) {
		var mountPoint = $(tr).find('.mountPoint input').val();
		if (mountPoint == '') {
			return false;
		}
		var statusSpan = $(tr).closest('tr').find('.status span');
		var backendClass = $(tr).find('.backend').data('class');
		var configuration = $(tr).find('.configuration input');
		var addMountPoint = true;
		if (configuration.length < 1) {
			return false;
		}
		var classOptions = {};
		$.each(configuration, function(index, input) {
			if ($(input).val() == '' && !$(input).hasClass('optional')) {
				addMountPoint = false;
				return false;
			}
			if ($(input).is(':checkbox')) {
				if ($(input).is(':checked')) {
					classOptions[$(input).data('parameter')] = true;
				} else {
					classOptions[$(input).data('parameter')] = false;
				}
			} else {
				classOptions[$(input).data('parameter')] = $(input).val();
			}
		});
		if ($('#externalStorage').data('admin') === true) {
			var multiselect = $(tr).find('.chzn-select').val();
			if (multiselect == null) {
				return false;
			}
		}
		if (addMountPoint) {
			var status = false;
			if ($('#externalStorage').data('admin') === true) {
				var isPersonal = false;
				var oldGroups = $(tr).find('.applicable').data('applicable-groups');
				var oldUsers = $(tr).find('.applicable').data('applicable-users');
				var groups = [];
				var users = [];
				$.each(multiselect, function(index, value) {
					var pos = value.indexOf('(group)');
					if (pos != -1) {
						var mountType = 'group';
						var applicable = value.substr(0, pos);
						if ($.inArray(applicable, oldGroups) != -1) {
							oldGroups.splice($.inArray(applicable, oldGroups), 1);
						}
						groups.push(applicable);
					} else {
						var mountType = 'user';
						var applicable = value;
						if ($.inArray(applicable, oldUsers) != -1) {
							oldUsers.splice($.inArray(applicable, oldUsers), 1);
						}
						users.push(applicable);
					}
					statusSpan.addClass('loading-small').removeClass('error success');
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'addMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						},
						success: function(result) {
							status = updateStatus(statusSpan, result);
							if (callback) {
								callback(status);
							}
						},
						error: function(result){
							status = updateStatus(statusSpan, result);
							if (callback) {
								callback(status);
							}
						}
					});
				});
				$(tr).find('.applicable').data('applicable-groups', groups);
				$(tr).find('.applicable').data('applicable-users', users);
				var mountType = 'group';
				$.each(oldGroups, function(index, applicable) {
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						}
					});
				});
				var mountType = 'user';
				$.each(oldUsers, function(index, applicable) {
					$.ajax({type: 'POST',
						url: OC.filePath('files_external', 'ajax', 'removeMountPoint.php'),
						data: {
							mountPoint: mountPoint,
							'class': backendClass,
							classOptions: classOptions,
							mountType: mountType,
							applicable: applicable,
							isPersonal: isPersonal
						}
					});
				});
			} else {
				var isPersonal = true;
				var mountType = 'user';
				var applicable = OC.currentUser;
				statusSpan.addClass('loading-small').removeClass('error success');
				$.ajax({type: 'POST',
					url: OC.filePath('files_external', 'ajax', 'addMountPoint.php'),
					data: {
						mountPoint: mountPoint,
						'class': backendClass,
						classOptions: classOptions,
						mountType: mountType,
						applicable: applicable,
						isPersonal: isPersonal
					},
					success: function(result) {
						status = updateStatus(statusSpan, result);
						if (callback) {
							callback(status);
						}
					},
					error: function(result){
						status = updateStatus(statusSpan, result);
						if (callback) {
							callback(status);
						}
					}
				});
			}
			return status;
		}
	}
};

$(document).ready(function() {
	$('.chzn-select').chosen();

	$('#externalStorage').on('change', '#selectBackend', function() {
		var tr = $(this).parent().parent();
		$('#externalStorage tbody').append($(tr).clone());
		$('#externalStorage tbody tr').last().find('.mountPoint input').val('');
		var selected = $(this).find('option:selected').text();
		var backendClass = $(this).val();
		$(this).parent().text(selected);
		if ($(tr).find('.mountPoint input').val() == '') {
			$(tr).find('.mountPoint input').val(suggestMountPoint(selected));
		}
		$(tr).addClass(backendClass);
		$(tr).find('.status').append('');
		$(tr).find('.backend').data('class', backendClass);
		var configurations = $(this).data('configurations');
		var td = $(tr).find('td.configuration');
		$.each(configurations, function(backend, parameters) {
			if (backend == backendClass) {
				$.each(parameters['configuration'], function(parameter, placeholder) {
					var is_optional = false;
					if (placeholder.indexOf('&') === 0) {
						is_optional = true;
						placeholder = placeholder.substring(1);
					}
					if (placeholder.indexOf('*') === 0) {
						var class_string = is_optional ? ' class="optional"' : '';
						td.append('<input type="password"' + class_string + ' data-parameter="'+parameter+'" placeholder="'+placeholder.substring(1)+'" />');
					else if (placeholder.indexOf('!') === 0) {
						td.append('<input type="checkbox" data-parameter="'+parameter+'" />'+placeholder.substring(1)+'');
					else if (placeholder.indexOf('#') === 0) {
						td.append('<input type="hidden" data-parameter="'+parameter+'" />');
					else {
						var class_string = is_optional ? ' class="optional"' : '';
						td.append('<input type="text"' + class_string + ' data-parameter="'+parameter+'" placeholder="'+placeholder+'" />');
					}
				});
				if (parameters['custom'] && $('#externalStorage tbody tr.'+backendClass.replace(/\\/g, '\\\\')).length == 1) {
					OC.addScript('files_external', parameters['custom']);
				}
				return false;
			}
		});
		// Reset chosen
		var chosen = $(tr).find('.applicable select');
		chosen.parent().find('div').remove();
		chosen.removeAttr('id').removeClass('chzn-done').css({display:'inline-block'});
		chosen.chosen();
		$(tr).find('td').last().attr('class', 'remove');
		$(tr).find('td').last().removeAttr('style');
		$(tr).removeAttr('id');
		$(this).remove();
	});

	function suggestMountPoint(defaultMountPoint) {
		var pos = defaultMountPoint.indexOf('/');
		if (pos !== -1) {
			defaultMountPoint = defaultMountPoint.substring(0, pos);
		}
		defaultMountPoint = defaultMountPoint.replace(/\s+/g, '');
		var i = 1;
		var append = '';
		var match = true;
		while (match && i < 20) {
			match = false;
			$('#externalStorage tbody td.mountPoint input').each(function(index, mountPoint) {
				if ($(mountPoint).val() == defaultMountPoint+append) {
					match = true;
					return false;
				}
			});
			if (match) {
				append = i;
				i++;
			} else {
				break;
			}
		}
		return defaultMountPoint+append;
	}

	$('#externalStorage').on('paste', 'td', function() {
		var tr = $(this).parent();
		setTimeout(function() {
			OC.MountConfig.saveStorage(tr);
		}, 20);
	});

	var timer;

	$('#externalStorage').on('keyup', 'td input', function() {
		clearTimeout(timer);
		var tr = $(this).parent().parent();
		if ($(this).val) {
			timer = setTimeout(function() {
				OC.MountConfig.saveStorage(tr);
			}, 2000);
		}
	});

	$('#externalStorage').on('change', 'td input:checkbox', function() {
		OC.MountConfig.saveStorage($(this).parent().parent().parent());
	});

	$('#externalStorage').on('change', '.applicable .chzn-select', function() {
		OC.MountConfig.saveStorage($(this).parent().parent());
	});

	$('#sslCertificate').on('click', 'td.remove>img', function() {
		var $tr = $(this).parent().parent();
		var row = this.parentNode.parentNode;
		$.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), {cert: row.id});
		$tr.remove();
		return true;
	});

	$('#externalStorage').on('click', 'td.remove>img', function() {
		var tr = $(this).parent().parent();
		var mountPoint = $(tr).find('.mountPoint input').val();

		if ($('#externalStorage').data('admin') === true) {
			var isPersonal = false;
			var multiselect = $(tr).find('.chzn-select').val();
			if (multiselect != null) {
				$.each(multiselect, function(index, value) {
					var pos = value.indexOf('(group)');
					if (pos != -1) {
						var mountType = 'group';
						var applicable = value.substr(0, pos);
					} else {
						var mountType = 'user';
						var applicable = value;
					}
					$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
				});
			}
		} else {
			var mountType = 'user';
			var applicable = OC.currentUser;
			var isPersonal = true;
			$.post(OC.filePath('files_external', 'ajax', 'removeMountPoint.php'), { mountPoint: mountPoint, mountType: mountType, applicable: applicable, isPersonal: isPersonal });
		}
		$(tr).remove();
	});

	$('#allowUserMounting').bind('change', function() {
		OC.msg.startSaving('#userMountingMsg');
		if (this.checked) {
			OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'yes');
			$('#userMountingBackups').removeClass('hidden');
		} else {
			OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'no');
			$('#userMountingBackups').addClass('hidden');
		}
		OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});
	});

	$('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() {
		OC.msg.startSaving('#userMountingMsg');
		var user_mounting_backends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get();
		OC.AppConfig.setValue('files_external', 'user_mounting_backends', user_mounting_backends.join());
		OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}});
	});
});

})();
<|endoftext|>


<commit_before>export function halTr(isim, hal) {
	let iyelik = 'iyelik',
		iHali = 'i',
		eHali = 'e',
		deHali = 'de',
		denHali = 'den',
		iEkleri = 'ııiiuuüü',
		sonHarf = isim[isim.length - 1],
		istisna = ~~/[ei][^ıüoö]*[au]l$|alp$/.test(isim) * 2, // Sapkali harf istisnasi var mı kontrol eder Orn: Alp, Resul, Cemal... 0 veya 2 degeri doner
		sonSesli = isim.match(/[aıeiouöü]/g).pop(), // seslilerden sonuncusunu alır

		// Ek in sesli harfine karar verir
		ek = (hal == iyelik || hal == iHali) ? // iyelik veya i hali ise
		// Son sesli harf aıeiouöü harflerinin hangisine denk geliyorsa o index numarasıyla iEkleri nin n'inci elemanı seçilir
		iEkleri['aıeiouöü'.indexOf(sonSesli) + istisna] : // e, de veya den hali ise
		// Son sesli harf a, ı, o veya u ise ek a (istisna var ise e ), e, i, ö veya ü ise ek e harfi
		(/[aıou]/.test(sonSesli)) ? istisna ? 'e' : 'a' : 'e';

	// Kaynastirma harflerini ekler
	if (sonHarf == sonSesli) {
		ek = (hal == iyelik) ? 'n' + ek : (hal == iHali || hal == eHali) ? 'y' + ek : ek
	}

	// Harf yumusamalarini kontrol eder
	if (hal == deHali || hal == denHali) {
		ek = (/[fstkçşhp]/.test(sonHarf) ? 't' : 'd') + ek
	}

	// Iyelik veya den hali icin ek in sonuna n harfi ekler
	if (hal == iyelik || hal == denHali) {
		ek += 'n'
	}

	return isim + ek;
}

export function halEn(noun, condition) {
	return condition ? condition + " " + noun : noun;
}
<commit_msg>Add support for hub changes in noun js<commit_after>export function halTr(isim, hal) {
	let iyelik = 'iyelik',
		yalinHali = "",
		iHali = 'i',
		eHali = 'e',
		deHali = 'de',
		denHali = 'den',
		iEkleri = 'ııiiuuüü',
		sonHarf = isim[isim.length - 1],
		istisna = ~~/[ei][^ıüoö]*[au]l$|alp$/.test(isim) * 2, // Sapkali harf istisnasi var mı kontrol eder Orn: Alp, Resul, Cemal... 0 veya 2 degeri doner
		sonSesli = isim.match(/[aıeiouöü]/g).pop(), // seslilerden sonuncusunu alır

		// Ek in sesli harfine karar verir
		ek = (hal == iyelik || hal == iHali) ? // iyelik veya i hali ise
		// Son sesli harf aıeiouöü harflerinin hangisine denk geliyorsa o index numarasıyla iEkleri nin n'inci elemanı seçilir
		iEkleri['aıeiouöü'.indexOf(sonSesli) + istisna] : // e, de veya den hali ise
		// Son sesli harf a, ı, o veya u ise ek a (istisna var ise e ), e, i, ö veya ü ise ek e harfi
		(/[aıou]/.test(sonSesli)) ? istisna ? 'e' : 'a' : 'e';

	if (hal == yalinHali) {
		return isim;
	}
	// Kaynastirma harflerini ekler
	if (sonHarf == sonSesli) {
		ek = (hal == iyelik) ? 'n' + ek : (hal == iHali || hal == eHali) ? 'y' + ek : ek
	}
	// Kok degisimlerini kontrol eder
	if (hal == iHali || hal == eHali) {
		if ((/[tçkp]/.test(sonHarf))) {
			isim = isim.substr(0, isim.length - 1);
			var yumusamisHarfMap = {
				"t": "d",
				"ç": "c",
				"k": "ğ",
				"p": "b"
			};
			isim = isim + yumusamisHarfMap[sonHarf];
		}
	}
	// Harf yumusamalarini kontrol eder
	if (hal == deHali || hal == denHali) {
		ek = (/[fstkçşhp]/.test(sonHarf) ? 't' : 'd') + ek
	}

	// Iyelik veya den hali icin ek in sonuna n harfi ekler
	if (hal == iyelik || hal == denHali) {
		ek += 'n'
	}

	return isim + ek;
}

export function halEn(noun, condition) {
	return condition ? condition + " " + noun : noun;
}
<|endoftext|>


<commit_before>/*jslint regexp: true */

var http = require("http"),
	url = require('url'),
	properties = require('./schema.org').declaration.properties,
	datatypes = require('./schema.org').declaration.datatypes,
	types = require('./schema.org').declaration.types;
function findSchemaDatatypes(searchTerm, callback) {
	'use strict';

	var schema_senses = [],
		sense,
		termName,
		term;
	try {
		for (termName in datatypes) {
			if (datatypes.hasOwnProperty(termName)) {
				term = datatypes[termName];
				if (term.label.search(new RegExp("(\\s|^)" + searchTerm, "i")) !== -1) {
					sense = {};
					sense.senseid = "http://schema.org/" + term.id;
					sense.explanation = term.comment;
					schema_senses.push(sense);
				}
			}
		}
	} catch (e) {
	}
	callback(schema_senses);
}
function findSchemaProperties(searchTerm, callback) {
	'use strict';
	var schema_senses = [],
		sense,
		termName,
		term;
	try {
		for (termName in properties) {
			if (properties.hasOwnProperty(termName)) {
				term = properties[termName];
				if (term.label.search(new RegExp("(\\s|^)" + searchTerm, "i")) !== -1) {
					sense = {};
					sense.senseid = "http://schema.org/" + term.id;
					sense.explanation = term.comment;
					schema_senses.push(sense);
				}
			}
		}
	} catch (e) {
	}
	callback(schema_senses);
}
function findSchemaTypes(searchTerm, callback) {
	'use strict';

	var schema_senses = [],
		sense,
		termName,
		term;
	try {
		for (termName in types) {
			if (types.hasOwnProperty(termName)) {
				term = types[termName];
				if (term.label.search(new RegExp("(\\s|^)" + searchTerm, "i")) !== -1) {
					sense = {};
					sense.senseid = "http://schema.org/" + term.id;
					sense.explanation = term.comment;
					schema_senses.push(sense);
				}
			}
		}
	} catch (e) {
	}
	callback(schema_senses);
}
function schemaRunner(run, q, callback) {
	'use strict';
	var i,
		counter = 0,
		matches = [],
		onMatch = function (matchList) {

			counter += 1;
			matches = matchList.concat(matches);

			if (counter >= run.length) {
				callback(matches);
			}
		};
	for (i = 0; i < run.length; i += 1) {
		run[i](q, onMatch);
	}
}
function findSchemaTerms(searchString, callback) {
	'use strict';
	var searchTerm,
		findWord;
	findWord = /:%22(.*?)%22\}$/g;

	searchTerm = JSON.parse(searchString).word;
	searchTerm = searchTerm.replace(/s$/, "s?"); // Catches a lot of plurals and makes them optional
	searchTerm = searchTerm.replace(/\./g, "\\.");
	schemaRunner([findSchemaDatatypes, findSchemaProperties, findSchemaTypes], searchTerm, function (schema_senses) {
		callback({senses: schema_senses});
	});
}
function findLexitagTerms(searchString, callback) {
	'use strict';
	var body = '',
		url = 'http://lexitags.dyndns.org:8080/server/lexitags2/Semtags?data=';
	http.get(url + searchString,
		function (response) {
			response.on('data', function (chunk) {
				body += chunk;
			});
			response.on('end', function () {
				callback(JSON.parse(body));
			}).on('error', function (e) {
				callback({});
			});
		});
}
function runQueries(run, query, callback) {
	'use strict';
	var i,
		counter = 0,
		json = {word: '', senses: []},
		onComplete = function (jsonResult) {
			counter += 1;
			json.word = jsonResult.word || json.word;
			json.senses = jsonResult.senses ? json.senses.concat(jsonResult.senses) : json.senses;
			if (counter === run.length) {
				callback(json);
			}
		};
	for (i = 0; i < run.length; i += 1) {
		run[i](query, onComplete);
	}
}
exports.lexitag = function (req, res) {
	'use strict';
	var q = url.parse(req.url, true);
	runQueries([findSchemaTerms, findLexitagTerms], q.query.data, function (json) {
		res.writeHead(200, {"Content-Type" : "application/json"});
		if (req.query.callback) {
			res.write(req.query.callback + '(' + JSON.stringify(json) + ')');
		} else {
			res.write(JSON.stringify(json));
		}
		res.end();
	});
};<commit_msg>Swiched to document 'use strict', made test to sanitize input sent to lexitags backend<commit_after>/*jslint regexp: true */
'use strict';
var http = require("http"),
	url = require('url'),
	properties = require('./schema.org').declaration.properties,
	datatypes = require('./schema.org').declaration.datatypes,
	types = require('./schema.org').declaration.types,
	saneString = function (searchString, callback) {
		if (searchString.length > 60) {
			callback(new Error('Search string <' + searchString + '> was to long'));
		} else {
			callback(null, searchString);
		}
	};
function findSchemaDatatypes(searchTerm, callback) {
	var schema_senses = [],
		sense,
		termName,
		term;
	try {
		for (termName in datatypes) {
			if (datatypes.hasOwnProperty(termName)) {
				term = datatypes[termName];
				if (term.label.search(new RegExp("(\\s|^)" + searchTerm, "i")) !== -1) {
					sense = {};
					sense.senseid = "http://schema.org/" + term.id;
					sense.explanation = term.comment;
					schema_senses.push(sense);
				}
			}
		}
	} catch (e) {
	}
	callback(schema_senses);
}
function findSchemaProperties(searchTerm, callback) {

	var schema_senses = [],
		sense,
		termName,
		term;
	try {
		for (termName in properties) {
			if (properties.hasOwnProperty(termName)) {
				term = properties[termName];
				if (term.label.search(new RegExp("(\\s|^)" + searchTerm, "i")) !== -1) {
					sense = {};
					sense.senseid = "http://schema.org/" + term.id;
					sense.explanation = term.comment;
					schema_senses.push(sense);
				}
			}
		}
	} catch (e) {
	}
	callback(schema_senses);
}
function findSchemaTypes(searchTerm, callback) {

	var schema_senses = [],
		sense,
		termName,
		term;
	try {
		for (termName in types) {
			if (types.hasOwnProperty(termName)) {
				term = types[termName];
				if (term.label.search(new RegExp("(\\s|^)" + searchTerm, "i")) !== -1) {
					sense = {};
					sense.senseid = "http://schema.org/" + term.id;
					sense.explanation = term.comment;
					schema_senses.push(sense);
				}
			}
		}
	} catch (e) {
	}
	callback(schema_senses);
}
function schemaRunner(run, q, callback) {

	var i,
		counter = 0,
		matches = [],
		onMatch = function (matchList) {

			counter += 1;
			matches = matchList.concat(matches);

			if (counter >= run.length) {
				callback(matches);
			}
		};
	for (i = 0; i < run.length; i += 1) {
		run[i](q, onMatch);
	}
}
function findSchemaTerms(searchString, callback) {

	var searchTerm;

	searchTerm = searchString;
	searchTerm = searchTerm.replace(/s$/, "s?"); // Catches a lot of plurals and makes them optional
	searchTerm = searchTerm.replace(/\./g, "\\.");
	schemaRunner([findSchemaDatatypes, findSchemaProperties, findSchemaTypes], searchTerm, function (schema_senses) {
		callback({senses: schema_senses});
	});
}

function findLexitagTerms(searchString, callback) {

	var body = '',
		url = 'http://lexitags.dyndns.org:8080/server/lexitags2/Semtags?data={"word": "',
		queryEnd = '"}';
	saneString(searchString, function (error, saneSearchString) {
		if (error) {
			console.log(error);
			callback(JSON.parse('{"senses": []}'));
		} else {
			http.get(url + saneSearchString + queryEnd,
				function (response) {
					response.on('data', function (chunk) {
						body += chunk;
					});
					response.on('end', function () {
						callback(JSON.parse(body));
					}).on('error', function (e) {
						callback({});
					});
				});
		}
	});
}
function runQueries(run, query, callback) {

	var i,
		counter = 0,
		json = {word: '', senses: []},
		onComplete = function (jsonResult) {
			counter += 1;
			json.word = jsonResult.word || json.word;
			json.senses = jsonResult.senses ? json.senses.concat(jsonResult.senses) : json.senses;
			if (counter === run.length) {
				callback(json);
			}
		};
	for (i = 0; i < run.length; i += 1) {
		run[i](query, onComplete);
	}
}
exports.lexitag = function (req, res) {

	console.log('Starting to lexitag');
	var q = url.parse(req.url, true);
	runQueries([findSchemaTerms, findLexitagTerms], q.query.word, function (json) {
		res.writeHead(200, {"Content-Type" : "application/json"});
		if (req.query.callback) {
			res.write(req.query.callback + '(' + JSON.stringify(json) + ')');
		} else {
			res.write(JSON.stringify(json));
		}
		res.end();
	});
};<|endoftext|>


<commit_before>var express = require( "express" );
var async = require( "async" );
var moment = require( "moment" );
var models = require( "./models" );

var handleSensorReading = function ( messageBroker, logger, app ) {
    var getSensorData = function ( done ) {
        messageBroker.publish( "sensor.get", { serialMessage: "A" }, function ( err, data ) {
            if ( err ) {
                return done( err );
            }
            return done( null, data );
        } );
    };

    var saveSensorData = function ( sensorData, done ) {
        models.SensorReading.create( sensorData, function ( err, data ) {
            if ( err ) {
                return done( err );
            }
            return done( null, data );
        } );
    };

    app.get( "/job/sensor-reading", function ( req, res ) {
        async.waterfall( [ getSensorData, saveSensorData ], function ( err, data ) {
            if ( err ) {
                logger.log( err );
                return res.status( 500 ).json();
            }
            return res.status( 200 ).json( data );
        } );
    } );
};

var handleSystemReading = function ( messageBroker, logger, app ) {
    var getSystemData = function ( done ) {
        messageBroker.publish( "system.get", {}, function ( err, data ) {
            if ( err ) {
                return done( err );
            }
            return done( null, data );
        } );
    };

    var saveSystemData = function ( systemData, done ) {
        models.SystemReading.create( systemData, function ( err, data ) {
            if ( err ) {
                return done( err );
            }
            return done( null, data );
        } );
    };

    app.get( "/job/system-reading", function ( req, res ) {
        async.waterfall( [ getSystemData, saveSystemData ], function ( err, data ) {
            if ( err ) {
                logger.log( err );
                return res.status( 500 ).json();
            }
            return res.status( 200 ).json( data );
        } );
    } );
};

var handleDailySensorStats = function ( messageBroker, logger, app ) {
    app.get( "/job/sensor-stats/day", function ( req, res ) {
        var yesterdayStart = moment().subtract( 1, "day" ).startOf( "day" ).toDate();
        var yesterdayEnd = moment().subtract( 1, "day" ).endOf( "day" ).toDate();

        var options = {
            startDate: yesterdayStart,
            endDate: yesterdayEnd,
            date: yesterdayStart,
            type: "day"
        };

        models.SensorReading.calcStatsForDateRange( options, function ( err, data ) {
            if ( err ) {
                logger.log( err );
                return res.status( 500 ).json();
            }
            return res.status( 200 ).json( data );
        } );
    } );
};

module.exports = function ( messageBroker, logger ) {

    var app = express();

    messageBroker.create( "sensor.get" );
    messageBroker.create( "system.get" );

    handleSensorReading( messageBroker, logger, app );
    handleSystemReading( messageBroker, logger, app );
    handleDailySensorStats( messageBroker, logger, app );

    return app;

};
<commit_msg>Add handler for system stats<commit_after>var express = require( "express" );
var async = require( "async" );
var moment = require( "moment" );
var models = require( "./models" );

var handleSensorReading = function ( messageBroker, logger, app ) {
    var getSensorData = function ( done ) {
        messageBroker.publish( "sensor.get", { serialMessage: "A" }, function ( err, data ) {
            if ( err ) {
                return done( err );
            }
            return done( null, data );
        } );
    };

    var saveSensorData = function ( sensorData, done ) {
        models.SensorReading.create( sensorData, function ( err, data ) {
            if ( err ) {
                return done( err );
            }
            return done( null, data );
        } );
    };

    app.get( "/job/sensor-reading", function ( req, res ) {
        async.waterfall( [ getSensorData, saveSensorData ], function ( err, data ) {
            if ( err ) {
                logger.log( err );
                return res.status( 500 ).json();
            }
            return res.status( 200 ).json( data );
        } );
    } );
};

var handleSystemReading = function ( messageBroker, logger, app ) {
    var getSystemData = function ( done ) {
        messageBroker.publish( "system.get", {}, function ( err, data ) {
            if ( err ) {
                return done( err );
            }
            return done( null, data );
        } );
    };

    var saveSystemData = function ( systemData, done ) {
        models.SystemReading.create( systemData, function ( err, data ) {
            if ( err ) {
                return done( err );
            }
            return done( null, data );
        } );
    };

    app.get( "/job/system-reading", function ( req, res ) {
        async.waterfall( [ getSystemData, saveSystemData ], function ( err, data ) {
            if ( err ) {
                logger.log( err );
                return res.status( 500 ).json();
            }
            return res.status( 200 ).json( data );
        } );
    } );
};

var handleDailySensorStats = function ( messageBroker, logger, app ) {
    app.get( "/job/sensor-stats/day", function ( req, res ) {
        var yesterdayStart = moment().subtract( 1, "day" ).startOf( "day" ).toDate();
        var yesterdayEnd = moment().subtract( 1, "day" ).endOf( "day" ).toDate();

        var options = {
            startDate: yesterdayStart,
            endDate: yesterdayEnd,
            date: yesterdayStart,
            type: "day"
        };

        models.SensorReading.calcStatsForDateRange( options, function ( err, data ) {
            if ( err ) {
                logger.log( err );
                return res.status( 500 ).json();
            }
            return res.status( 200 ).json( data );
        } );
    } );
};

var handleDailySystemStats = function ( messageBroker, logger, app ) {
    app.get( "/job/system-stats/day", function ( req, res ) {
        var yesterdayStart = moment().subtract( 1, "day" ).startOf( "day" ).toDate();
        var yesterdayEnd = moment().subtract( 1, "day" ).endOf( "day" ).toDate();

        var options = {
            startDate: yesterdayStart,
            endDate: yesterdayEnd,
            date: yesterdayStart,
            type: "day"
        };

        models.SystemReading.calcStatsForDateRange( options, function ( err, data ) {
            if ( err ) {
                logger.log( err );
                return res.status( 500 ).json();
            }
            return res.status( 200 ).json( data );
        } );
    } );
};

module.exports = function ( messageBroker, logger ) {

    var app = express();

    messageBroker.create( "sensor.get" );
    messageBroker.create( "system.get" );

    handleSensorReading( messageBroker, logger, app );
    handleSystemReading( messageBroker, logger, app );
    handleDailySensorStats( messageBroker, logger, app );
    handleDailySystemStats( messageBroker, logger, app );

    return app;

};
<|endoftext|>


<commit_before>/*
 * Copyright 2017, Maha Farhat
 *
 * This file is part of the software gentb, consisting of custom
 * code for the GenTB's django-based website.
 *
 * gentb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * gentb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with gentb.  If not, see <http://www.gnu.org/licenses/>.
 */

$(document).ready(function() {
  var svg = 'svg.drugs';
  var chart = initialiseDrugChart(svg);
  $('#drug-store').data('json-signal', function(data) {
    console.log("Drugging up!");
    chartData(svg, chart, data.data);

    // Highlights all selected drug labels
    var existing = getTabData('drug');
    d3.selectAll('.tick.zero').filter(function() { return existing.includes(d3.select(this).text()) })
      .classed('selected-drug', true);
  });
});

function initialiseDrugChart(svg) {

    //So we first make the chart
    var chart = nv.models.multiBarChart()
      .stacked(true)
      .reduceXTicks(false);

    var width = 1000;
    var height = 600;

    //Some properties of the chart
    chart.margin({top: 50, right: 0, bottom: 60, left: 80});
    chart.height(height);
    chart.width(width);
    chart.yAxis.scale(100).orient("left")
        .axisLabel('Number of strains')
        .tickFormat(d3.format("d"));

    chart.xAxis
        .axisLabel("Drug Codename")
        .rotateLabels(-45);

    chart.showLegend(true);

    //use d3 (a javascript library) to select the svg tag in the html that you made for the chart and then to put in the chart
    var svg = d3.select(svg)
          .attr('perserveAspectRatio', 'xMinYMid')
          .attr('width', width)
          .attr('height', height)
          .attr('viewBox', '0 0 ' + width + ' ' + height)
          .datum([])
          .transition().duration(1200)
          .call(chart);

    // Selects/deselects the clicked drug
    chart.multibar.dispatch.on("elementClick", function(e) {
        var label = d3.selectAll('.tick.zero').filter(function() { return d3.select(this).text() == e.data.x });
        label.classed('selected-drug', !label.classed('selected-drug'));
        toggleTabData('drug', e.data.x, e.data.x, 'map-marker');
    });

    // Deselects all drugs
    $('#drugs').parent().click(function(e) {
      d3.selectAll('.tick.zero').classed('selected-drug', false);
      unsetTabData('drug');
    });

    return chart;
}
<commit_msg>added option to switch between grouped and stacked and attempts to highlight bars when selected<commit_after>/*
 * Copyright 2017, Maha Farhat
 *
 * This file is part of the software gentb, consisting of custom
 * code for the GenTB's django-based website.
 *
 * gentb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * gentb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with gentb.  If not, see <http://www.gnu.org/licenses/>.
 */

$(document).ready(function() {
  var svg = 'svg.drugs';
  var chart = initialiseDrugChart(svg);
  $('#drug-store').data('json-signal', function(data) {
    console.log("Drugging up!");
    chartData(svg, chart, data.data);

    // Highlights all selected drug labels
    var existing = getTabData('drug');
    d3.selectAll('.tick.zero').filter(function() { return existing.includes(d3.select(this).text()) })
      .classed('selected-drug', true);
  });
});

function initialiseDrugChart(svg) {

    //So we first make the chart
    var chart = nv.models.multiBarChart()
      .showControls(true)
      .stacked(true)
      .reduceXTicks(false);

    var width = 1000;
    var height = 600;

    //Some properties of the chart
    chart.margin({top: 50, right: 0, bottom: 60, left: 80});
    chart.height(height);
    chart.width(width);
    chart.yAxis.scale(100).orient("left")
        .axisLabel('Number of strains')
        .tickFormat(d3.format("d"));

    chart.xAxis
        .axisLabel("Drug Codename")
        .rotateLabels(-45);

    chart.showLegend(true);

    //use d3 (a javascript library) to select the svg tag in the html that you made for the chart and then to put in the chart
    var svg = d3.select(svg)
          .attr('perserveAspectRatio', 'xMinYMid')
          .attr('width', width)
          .attr('height', height)
          .attr('viewBox', '0 0 ' + width + ' ' + height)
          .datum([])
          .transition().duration(1200)
          .call(chart);

    // Selects/deselects the clicked drug
    chart.multibar.dispatch.on("elementClick", function(e) {
        var label = d3.selectAll('.tick.zero').filter(function() { return d3.select(this).text() == e.data.x });
        label.classed('selected-drug', !label.classed('selected-drug'));
        toggleTabData('drug', e.data.x, e.data.x, 'map-marker');
    //trying to highlight bars when selected:
    //    bars = d3.selectAll("rect")
    //    console.log(bars)

    });

    // bars.classed('selected-drug', !bars.classed('selected-drug'));

    // Deselects all drugs
    $('#drugs').parent().click(function(e) {
      d3.selectAll('.tick.zero').classed('selected-drug', false);
      unsetTabData('drug');
    });

    return chart;
}
<|endoftext|>


<commit_before>import debugModule from "debug";
const debug = debugModule("test:data:decode");

import Ganache from "ganache-cli";
import Web3 from "web3";
import { assert } from "chai";
import changeCase from "change-case";

import { prepareContracts } from "test/helpers";

import Debugger from "lib/debugger";

import * as TruffleDecodeUtils from "truffle-decode-utils";

import data from "lib/data/selectors";

export function *generateUints() {
  let x = 0;
  while (true) {
    yield x;
    x++;
  }
}

function contractName(testName) {
  return testName.replace(/ /g, "");
}

function fileName(testName) {
  return `${contractName(testName)}.sol`;
}

function generateTests(fixtures) {
  for (let { name, value: expected } of fixtures) {
    it(`correctly decodes ${name}`,
      () => { assert.deepEqual(this.decode(name), expected); }
    );
  }
}

function lastStatementLine(source) {
  const lines = source.split("\n");
  for (let i = lines.length - 1; i >= 0; i--) {
    let line = lines[i];
    if (line.indexOf(";") != -1) {
      return i;
    }
  }
}

async function prepareDebugger(testName, sources) {
  const provider = Ganache.provider({seed: "debugger", gasLimit: 7000000});
  const web3 = new Web3(provider);

  let { abstractions, artifacts: contracts, files } =
    await prepareContracts(provider, sources);

  let instance = await abstractions[contractName(testName)].deployed();
  let receipt = await instance.run();
  let txHash = receipt.tx;

  let bugger = await Debugger.forTx(txHash, { provider, files, contracts });

  let session = bugger.connect();

  let breakpoint = {
    address: instance.address,
    line: lastStatementLine(sources[fileName(testName)])
  };

  session.continueUntil(breakpoint);

  return session;
}

async function getDecode(session) {
  const definitions = session.view(data.current.identifiers.definitions);
  const refs = session.view(data.current.identifiers.refs);

  const decode = session.view(data.views.decoder);
  return (name) => TruffleDecodeUtils.Conversion.cleanBNs(
    decode(definitions[name], refs[name])
  );
}

export function describeDecoding(testName, fixtures, selector, generateSource) {
  const sources = {
    [fileName(testName)]: generateSource(contractName(testName), fixtures)
  };

  describe(testName, function() {
    const testDebug = debugModule(
      `test:data:decode:${changeCase.paramCase(testName)}`
    );

    testDebug("source %s", Object.values(sources)[0]);

    this.timeout(30000);

    before("runs and observes debugger", async () => {
      const session = await prepareDebugger(testName, sources);
      this.decode = await getDecode(session);

      if (selector) {
        debug("selector %O", session.view(selector));
      }
    });

    generateTests.bind(this)(fixtures);
  });
}<commit_msg>make sure to wait for the decode function to finish<commit_after>import debugModule from "debug";
const debug = debugModule("test:data:decode");

import Ganache from "ganache-cli";
import Web3 from "web3";
import { assert } from "chai";
import changeCase from "change-case";

import { prepareContracts } from "test/helpers";

import Debugger from "lib/debugger";

import * as TruffleDecodeUtils from "truffle-decode-utils";

import data from "lib/data/selectors";

export function *generateUints() {
  let x = 0;
  while (true) {
    yield x;
    x++;
  }
}

function contractName(testName) {
  return testName.replace(/ /g, "");
}

function fileName(testName) {
  return `${contractName(testName)}.sol`;
}

function generateTests(fixtures) {
  for (let { name, value: expected } of fixtures) {
    it(`correctly decodes ${name}`,
      async () => { assert.deepEqual(await this.decode(name), expected); }
    );
  }
}

function lastStatementLine(source) {
  const lines = source.split("\n");
  for (let i = lines.length - 1; i >= 0; i--) {
    let line = lines[i];
    if (line.indexOf(";") != -1) {
      return i;
    }
  }
}

async function prepareDebugger(testName, sources) {
  const provider = Ganache.provider({seed: "debugger", gasLimit: 7000000});
  const web3 = new Web3(provider);

  let { abstractions, artifacts: contracts, files } =
    await prepareContracts(provider, sources);

  let instance = await abstractions[contractName(testName)].deployed();
  let receipt = await instance.run();
  let txHash = receipt.tx;

  let bugger = await Debugger.forTx(txHash, { provider, files, contracts });

  let session = bugger.connect();

  let breakpoint = {
    address: instance.address,
    line: lastStatementLine(sources[fileName(testName)])
  };

  session.continueUntil(breakpoint);

  return session;
}

async function getDecode(session) {
  const definitions = session.view(data.current.identifiers.definitions);
  const refs = session.view(data.current.identifiers.refs);

  const decode = session.view(data.views.decoder);
  return (name) => TruffleDecodeUtils.Conversion.cleanBNs(
    decode(definitions[name], refs[name])
  );
}

export function describeDecoding(testName, fixtures, selector, generateSource) {
  const sources = {
    [fileName(testName)]: generateSource(contractName(testName), fixtures)
  };

  describe(testName, function() {
    const testDebug = debugModule(
      `test:data:decode:${changeCase.paramCase(testName)}`
    );

    testDebug("source %s", Object.values(sources)[0]);

    this.timeout(30000);

    before("runs and observes debugger", async () => {
      const session = await prepareDebugger(testName, sources);
      this.decode = await getDecode(session);

      if (selector) {
        debug("selector %O", session.view(selector));
      }
    });

    generateTests.bind(this)(fixtures);
  });
}<|endoftext|>