<commit_before>// Aurelia
import {
  inject,  // eslint-disable-line
  LogManager
} from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';  // eslint-disable-line

// Injectable
import Export from 'services/export';  // eslint-disable-line
import Font from 'services/font';  // eslint-disable-line
import States from 'services/states';  // eslint-disable-line

// Utils
import { updateConfigs } from 'app-actions';
import { ERROR_DURATION } from 'app-defaults';
import { name, routes } from 'configs/app';
import { externalLinks } from 'configs/nav';
import FgmState from 'components/fragments/fragments-state';
import checkTextInputFocus from 'utils/check-text-input-focus';
import dragDrop from 'utils/drag-drop';
import readJsonFile from 'utils/read-json-file';
import validateConfig from 'utils/validate-config';
import { requestNextAnimationFrame } from 'utils/request-animation-frame';

const logger = LogManager.getLogger('app');

@inject(EventAggregator, Export, Font, States)
export default class App {
  constructor (event, exportData, font, states) {
    this.event = event;

    this.font = font;

    this.store = states.store;
    this.store.subscribe(this.update.bind(this));

    this.undo = states.undo.bind(states);
    this.redo = states.redo.bind(states);
    this.reset = states.reset.bind(states);

    this.isRehydrated = states.isRehydrated;

    this.appName = name;

    this.update();

    this.externalLinks = externalLinks;

    this.swag = [
      [66, 79, 67, 75, 87, 85, 82, 83, 84],
      [67, 79, 80, 82, 69, 83, 83, 79],
      [72, 69, 76, 80],
      [67, 79, 79, 76]
    ];
    this.swagI = 0;
    this.swagJ = 0;
    this.swagInterval = 500;
    this.swagTime = performance.now();

    if (window.hipilerConfig.ghp) {
      this.navEvent = this.event.subscribe(
        'router:navigation:processing',
        () => {
          if (typeof location.hash !== 'string') {
            return;
          }

          const el = document.getElementById(location.hash.slice(1));

          if (el) el.scrollIntoView();
        });
    }

    // Global method for programmatically exporting the piling status
    window.hipilerExportPiles = () => exportData.get('piles');
  }

  /* ----------------------- Aurelia-specific methods ----------------------- */

  attached () {
    this.font.size = parseInt(
      window
        .getComputedStyle(document.body, null)
        .getPropertyValue('font-size')
        .slice(0, -2),
      10
    );

    // Drag and drop handler
    dragDrop(this.baseEl, this.dragDropArea, (event) => {
      readJsonFile(event.dataTransfer.files[0])
        .then(json => this.setConfig(json))
        .catch((error) => {
          logger.info(error);
          this.showGlobalError('Invalid JSON file');
        });
    });

    document.addEventListener('keydown', this.keyDownHandler.bind(this));
    document.addEventListener('keyup', this.keyUpHandler.bind(this));
    document.addEventListener('mousemove', this.mouseMoveHandler.bind(this));
    document.addEventListener('mouseup', this.mouseUpHandler.bind(this));
    document.addEventListener('scroll', this.scrollHandler.bind(this));

    this.event.subscribe('showGlobalError', (args) => {
      this.showGlobalError(...args);
    });

    if (
      this.router.currentInstruction.config.name === 'explore' &&
      !this.exploreIsReady
    ) {
      this.router.navigateToRoute(
        'home', this.router.currentInstruction.queryParams
      );
    }

    // Check if page is loaded with a hash link
    if (typeof location.hash === 'string') {
      const el = document.getElementById(location.hash.slice(1));

      if (el) {
        requestNextAnimationFrame(() => { el.scrollIntoView(); });
      }
    }
  }

  configureRouter (config, router) {
    this.router = router;

    config.title = this.appName;

    if (window.hipilerConfig.ghp) {
      config.options.pushState = true;
      config.options.hashChange = false;
      config.options.root = '/';
    }

    config.map(routes);

    config.mapUnknownRoutes(() => ({
      route: 'not-found',
      moduleId: 'views/not-found'
    }));

    config.fallbackRoute('/');
  }

  deactivate () {
    this.navEvent.dispose();
  }

  /* ----------------------- Getter / Setter Variables ---------------------- */

  get currentRoute () {
    try {
      return this.router.currentInstruction.config.name;
    } catch (e) {
      return undefined;
    }
  }

  /* ----------------------- Getter / Setter Variables ---------------------- */

  /**
   * Mouse click event handler.
   *
   * @param {object} event - Mouse click event object.
   */
  clickHandler (event) {
    this.event.publish('app.click', event);
    return true;
  }

  /**
   * Hide global error message.
   */
  hideGlobalError () {
    this.corruptConfig = false;
    this.globalError = false;
    this.globalErrorMsg = undefined;
  }

  /**
   * Key down event handler.
   *
   * @param {object} event - Kep down event object.
   */
  keyDownHandler (event) {
    if (event.ctrlKey || event.metaKey) {
      this.isCtrlMetaKeyDown = true;
    }

    // 83 === S
    if (event.keyCode === 83 && this.isCtrlMetaKeyDown) {
      event.preventDefault();
      this.event.publish('app.save', event);
    }

    // 89 === Y
    if (event.keyCode === 89 && this.isCtrlMetaKeyDown) {
      event.preventDefault();
      if (!this.wasUndoRedo) {
        this.redo();
        this.wasUndoRedo = true;
      }
    }

    // 90 === Z
    if (event.keyCode === 90 && this.isCtrlMetaKeyDown) {
      event.preventDefault();
      if (!this.wasUndoRedo) {
        this.undo();
        this.wasUndoRedo = true;
      }
    }

    this.event.publish('app.keyDown', event);
  }

  /**
   * Key up event handler.
   *
   * @param {object} event - Kep up event object.
   */
  keyUpHandler (event) {
    if (checkTextInputFocus()) { return; }

    event.preventDefault();

    if (event.code === 'ControlLeft' || event.code === 'MetaLeft') {
      this.isCtrlMetaKeyDown = false;
    }

    if (this.wasUndoRedo && !this.isCtrlMetaKeyDown) {
      this.wasUndoRedo = false;
    }

    if (this.globalError && event.keyCode === 27) {  // ESC
      this.hideGlobalError();
      return;
    }

    this.keyUpSwagHandler(event.keyCode);

    this.event.publish('app.keyUp', event);
  }

  keyUpSwagHandler (keyCode) {
    const now = performance.now();

    if (now - this.swagTime > this.swagInterval) {
      this.swagJ = 0;
    }

    this.swagTime = now;

    if (this.swagJ === 0) {
      this.swag.forEach((codeWurst, index) => {
        if (keyCode === codeWurst[0]) {
          this.swagI = index;
          this.swagJ = 1;
        }
      });
    } else if (keyCode === this.swag[this.swagI][this.swagJ]) {
      this.swagJ += 1;
    }

    if (this.swagJ === this.swag[this.swagI].length) {
      this.dialogPromise = new Promise((resolve, reject) => {
        this.dialogDeferred = { resolve, reject };
      });

      this.dialogIsOpen = true;

      switch (this.swagI) {
        case 0:
        case 1:
          this.dialogMessage =
            'May the bockwurst be with you my young compression lover.' +
            '
Learn more about Compresso\'s awesome bockwurst-guided ' +
            'compression for segmentation data by clicking Okay' +
            '.';
          break;
        case 2:
          this.dialogMessage =
            'We hear you! You are not alone, help is on it\'s way.
' +
            'Meanwhile have a look at our extensive documentation' +
            ', get yourself a nice cup of ☕ , and ping us on Twitter';
          break;
        case 3:
          this.dialogMessage =
            'Exactly! HiPiler is a cool piece of software. ' +
            'If you want to go more low-level and play with those Hi-C maps ' +
            'directly we highly recommend checking out ' +
            ' ' +
            'Cooler. Cooler is a fine piece of digital ' +
            'craftmanship for smart storing and outrageously efficient ' +
            'querying of Hi-C maps, provided by the smart folks at Mirnylab.';
          break;
        default:
          // Nothing
      }

      this.dialogPromise
        .then(() => {
          if (this.swagI < 2) {
            window.open('https://github.com/vcg/compresso');
          } else {
            this.router.navigateToRoute('docs');
          }
        })
        .catch(() => {
          // Nothing
        });
    }
  }

  /**
   * Mouse up event handler.
   *
   * @param {object} event - Mouse up event object.
   */
  mouseUpHandler (event) {
    this.event.publish('app.mouseUp', event);
  }

  /**
   * Mouse move hander
   *
   * @param {object} event - Mouse move event object.
   */
  mouseMoveHandler (event) {
    this.event.publish('app.mouseMove', event);
  }

  /**
   * Reset state and destroy the current exploration session.
   */
  resetHandler () {
    this.dialogPromise = new Promise((resolve, reject) => {
      this.dialogDeferred = { resolve, reject };
    });

    this.dialogIsOpen = true;
    this.dialogMessage =
      'Are you sure you want to reset your current session? This cannot be ' +
      'undone.';

    this.dialogPromise
      .then(() => {
        this.reset();
        FgmState.reset();
        this.exploreIsReady = false;
        this.router.navigateToRoute('home');
      })
      .catch(() => {
        // Nothing
      });
  }

  /**
   * Resume previous exploration
   */
  resumeExploration () {
    this.router.navigateToRoute('explore');
  }

  /**
   * Publish scroll event
   *
   * @param {object} event - Scroll event object.
   */
  scrollHandler (event) {
    this.event.publish('app.scroll', event);
    // this.event.subscribe
  }

  /**
   * Set HiPiler config for exploration
   *
   * @param {object} config - Configuration.
   */
  setConfig (config) {
    if (validateConfig(config.fgm, config.hgl)) {
      this.store.dispatch(updateConfigs(config));
      this.router.navigateToRoute('explore');
    } else {
      this.showGlobalError('Corrupted Config File', 3000);
    }
  }

  /**
   * Show a global error message.
   *
   * @param {string} msg - Message to be displayed.
   * @param {number} duration - Time in milliseconds the error is to be shown.
   */
  showGlobalError (msg, duration = ERROR_DURATION) {
    if (this.globalErrorDisplay) {
      clearTimeout(this.globalErrorDisplay);
    }

    this.globalError = true;
    this.globalErrorMsg = msg;

    this.globalErrorDisplay = setTimeout(
      this.hideGlobalError.bind(this), duration
    );
  }

  /**
   * Update app after the state changed..
   */
  update () {
    const state = this.store.getState().present;

    try {
      this.exploreIsReady = validateConfig(
        state.explore.fragments.config,
        state.explore.higlass.config
      );
    } catch (e) {
      this.exploreIsReady = false;
    }
  }
}
<commit_msg>Add support for CSV dropping<commit_after>// Aurelia
import {
  inject,  // eslint-disable-line
  LogManager
} from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';  // eslint-disable-line
import * as Papa from 'papaparse';

// Injectable
import Export from 'services/export';  // eslint-disable-line
import Font from 'services/font';  // eslint-disable-line
import States from 'services/states';  // eslint-disable-line

// Utils
import { updateConfigs } from 'app-actions';
import { ERROR_DURATION } from 'app-defaults';
import { name, routes } from 'configs/app';
import { externalLinks } from 'configs/nav';
import FgmState from 'components/fragments/fragments-state';
import checkTextInputFocus from 'utils/check-text-input-focus';
import dragDrop from 'utils/drag-drop';
import readJsonFile from 'utils/read-json-file';
import validateConfig from 'utils/validate-config';
import basicHiglassConfig from 'utils/basic-higlass-config';
import { requestNextAnimationFrame } from 'utils/request-animation-frame';

const logger = LogManager.getLogger('app');

@inject(EventAggregator, Export, Font, States)
export default class App {
  constructor (event, exportData, font, states) {
    this.event = event;

    this.font = font;

    this.store = states.store;
    this.store.subscribe(this.update.bind(this));

    this.undo = states.undo.bind(states);
    this.redo = states.redo.bind(states);
    this.reset = states.reset.bind(states);

    this.isRehydrated = states.isRehydrated;

    this.appName = name;

    this.update();

    this.externalLinks = externalLinks;

    this.swag = [
      [66, 79, 67, 75, 87, 85, 82, 83, 84],
      [67, 79, 80, 82, 69, 83, 83, 79],
      [72, 69, 76, 80],
      [67, 79, 79, 76]
    ];
    this.swagI = 0;
    this.swagJ = 0;
    this.swagInterval = 500;
    this.swagTime = performance.now();

    if (window.hipilerConfig.ghp) {
      this.navEvent = this.event.subscribe(
        'router:navigation:processing',
        () => {
          if (typeof location.hash !== 'string') {
            return;
          }

          const el = document.getElementById(location.hash.slice(1));

          if (el) el.scrollIntoView();
        });
    }

    // Global method for programmatically exporting the piling status
    window.hipilerExportPiles = () => exportData.get('piles');
  }

  /* ----------------------- Aurelia-specific methods ----------------------- */

  attached () {
    this.font.size = parseInt(
      window
        .getComputedStyle(document.body, null)
        .getPropertyValue('font-size')
        .slice(0, -2),
      10
    );

    // Drag and drop handler
    dragDrop(this.baseEl, this.dragDropArea, (event) => {
      switch (event.dataTransfer.files[0].type) {
        case 'text/csv':
          Papa.parse(event.dataTransfer.files[0], {
            complete: (results) => {
              this.buildConfig(results.data);
            },
            error: (error) => {
              logger.info(error);
              this.showGlobalError('Invalid CSV file');
            }
          });
          break;

        case 'application/json':
          readJsonFile(event.dataTransfer.files[0])
            .then(json => this.setConfig(json))
            .catch((error) => {
              logger.info(error);
              this.showGlobalError('Invalid JSON file');
            });
          break;

        default:
          this.showGlobalError('Unsupported file type. Drop a JSON or CSV!');
          break;
      }
    });

    document.addEventListener('keydown', this.keyDownHandler.bind(this));
    document.addEventListener('keyup', this.keyUpHandler.bind(this));
    document.addEventListener('mousemove', this.mouseMoveHandler.bind(this));
    document.addEventListener('mouseup', this.mouseUpHandler.bind(this));
    document.addEventListener('scroll', this.scrollHandler.bind(this));

    this.event.subscribe('showGlobalError', (args) => {
      this.showGlobalError(...args);
    });

    if (
      this.router.currentInstruction.config.name === 'explore' &&
      !this.exploreIsReady
    ) {
      this.router.navigateToRoute(
        'home', this.router.currentInstruction.queryParams
      );
    }

    // Check if page is loaded with a hash link
    if (typeof location.hash === 'string') {
      const el = document.getElementById(location.hash.slice(1));

      if (el) {
        requestNextAnimationFrame(() => { el.scrollIntoView(); });
      }
    }
  }

  configureRouter (config, router) {
    this.router = router;

    config.title = this.appName;

    if (window.hipilerConfig.ghp) {
      config.options.pushState = true;
      config.options.hashChange = false;
      config.options.root = '/';
    }

    config.map(routes);

    config.mapUnknownRoutes(() => ({
      route: 'not-found',
      moduleId: 'views/not-found'
    }));

    config.fallbackRoute('/');
  }

  deactivate () {
    this.navEvent.dispose();
  }

  /* ----------------------- Getter / Setter Variables ---------------------- */

  get currentRoute () {
    try {
      return this.router.currentInstruction.config.name;
    } catch (e) {
      return undefined;
    }
  }

  /* -------------------------------- Methods ------------------------------- */

  buildConfig (rows) {
    // Scan loci and extract
    const colIds = {};
    const fragments = [];
    const noInt = {
      chrom1: true,
      strand1: true,
      chrom2: true,
      strand2: true,
      dataset: true,
      server: true,
      coords: true
    };
    const datasets = {};
    let server;

    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      if (i === 0) {
        const header = [];
        row.forEach((col, j) => {
          header.push(col.toLowerCase());
          colIds[col.toLowerCase()] = j;
        });
        if (this.checkLoci(colIds)) {
          fragments.push(header);
        } else {
          this.showGlobalError('Invalid CSV file!');
          return;
        }
      } else if (row.length === fragments[0].length) {
        const parsedRow = [];
        row.forEach((val, j) => {
          if (noInt[fragments[0][j]] || fragments[0][j][0] === '_') {
            parsedRow.push(val);
          } else {
            parsedRow.push(parseInt(val, 10));
          }
        });
        fragments.push(parsedRow);
        datasets[parsedRow[colIds.dataset]] = parsedRow[colIds.coords] || 'hg19';
        server = parsedRow[colIds.server];
      }
    }

    const config = {
      fgm: {
        fragmentsServer: server,
        fragmentsPrecision: 2,
        fragments
      },
      hgl: basicHiglassConfig(
        server, Object.keys(datasets)
          .map(matrix => ({ matrix, coords: datasets[matrix] }))
      )
    };

    // Set new config
    this.setConfig(config);
  }

  checkLoci (header) {
    const minCols = {
      chrom1: 0,
      start1: 0,
      end1: 0,
      chrom2: 0,
      start2: 0,
      end2: 0,
      dataset: 0,
      zoomoutlevel: 0,
      server: 0
    };
    const cols = Object.keys(header);

    if (cols.length < 8) return false;

    cols.forEach((col) => {
      if (typeof minCols[col] !== 'undefined') minCols[col] += 1;
    });

    return Object.values(minCols).every(col => col > 0);
  }

  /**
   * Mouse click event handler.
   *
   * @param {object} event - Mouse click event object.
   */
  clickHandler (event) {
    this.event.publish('app.click', event);
    return true;
  }

  /**
   * Hide global error message.
   */
  hideGlobalError () {
    this.corruptConfig = false;
    this.globalError = false;
    this.globalErrorMsg = undefined;
  }

  /**
   * Key down event handler.
   *
   * @param {object} event - Kep down event object.
   */
  keyDownHandler (event) {
    if (event.ctrlKey || event.metaKey) {
      this.isCtrlMetaKeyDown = true;
    }

    // 83 === S
    if (event.keyCode === 83 && this.isCtrlMetaKeyDown) {
      event.preventDefault();
      this.event.publish('app.save', event);
    }

    // 89 === Y
    if (event.keyCode === 89 && this.isCtrlMetaKeyDown) {
      event.preventDefault();
      if (!this.wasUndoRedo) {
        this.redo();
        this.wasUndoRedo = true;
      }
    }

    // 90 === Z
    if (event.keyCode === 90 && this.isCtrlMetaKeyDown) {
      event.preventDefault();
      if (!this.wasUndoRedo) {
        this.undo();
        this.wasUndoRedo = true;
      }
    }

    this.event.publish('app.keyDown', event);
  }

  /**
   * Key up event handler.
   *
   * @param {object} event - Kep up event object.
   */
  keyUpHandler (event) {
    if (checkTextInputFocus()) { return; }

    event.preventDefault();

    if (event.code === 'ControlLeft' || event.code === 'MetaLeft') {
      this.isCtrlMetaKeyDown = false;
    }

    if (this.wasUndoRedo && !this.isCtrlMetaKeyDown) {
      this.wasUndoRedo = false;
    }

    if (this.globalError && event.keyCode === 27) {  // ESC
      this.hideGlobalError();
      return;
    }

    this.keyUpSwagHandler(event.keyCode);

    this.event.publish('app.keyUp', event);
  }

  keyUpSwagHandler (keyCode) {
    const now = performance.now();

    if (now - this.swagTime > this.swagInterval) {
      this.swagJ = 0;
    }

    this.swagTime = now;

    if (this.swagJ === 0) {
      this.swag.forEach((codeWurst, index) => {
        if (keyCode === codeWurst[0]) {
          this.swagI = index;
          this.swagJ = 1;
        }
      });
    } else if (keyCode === this.swag[this.swagI][this.swagJ]) {
      this.swagJ += 1;
    }

    if (this.swagJ === this.swag[this.swagI].length) {
      this.dialogPromise = new Promise((resolve, reject) => {
        this.dialogDeferred = { resolve, reject };
      });

      this.dialogIsOpen = true;

      switch (this.swagI) {
        case 0:
        case 1:
          this.dialogMessage =
            'May the bockwurst be with you my young compression lover.' +
            '
Learn more about Compresso\'s awesome bockwurst-guided ' +
            'compression for segmentation data by clicking Okay' +
            '.';
          break;
        case 2:
          this.dialogMessage =
            'We hear you! You are not alone, help is on it\'s way.
' +
            'Meanwhile have a look at our extensive documentation' +
            ', get yourself a nice cup of ☕ , and ping us on Twitter';
          break;
        case 3:
          this.dialogMessage =
            'Exactly! HiPiler is a cool piece of software. ' +
            'If you want to go more low-level and play with those Hi-C maps ' +
            'directly we highly recommend checking out ' +
            ' ' +
            'Cooler. Cooler is a fine piece of digital ' +
            'craftmanship for smart storing and outrageously efficient ' +
            'querying of Hi-C maps, provided by the smart folks at Mirnylab.';
          break;
        default:
          // Nothing
      }

      this.dialogPromise
        .then(() => {
          if (this.swagI < 2) {
            window.open('https://github.com/vcg/compresso');
          } else {
            this.router.navigateToRoute('docs');
          }
        })
        .catch(() => {
          // Nothing
        });
    }
  }

  /**
   * Mouse up event handler.
   *
   * @param {object} event - Mouse up event object.
   */
  mouseUpHandler (event) {
    this.event.publish('app.mouseUp', event);
  }

  /**
   * Mouse move hander
   *
   * @param {object} event - Mouse move event object.
   */
  mouseMoveHandler (event) {
    this.event.publish('app.mouseMove', event);
  }

  /**
   * Reset state and destroy the current exploration session.
   */
  resetHandler () {
    this.dialogPromise = new Promise((resolve, reject) => {
      this.dialogDeferred = { resolve, reject };
    });

    this.dialogIsOpen = true;
    this.dialogMessage =
      'Are you sure you want to reset your current session? This cannot be ' +
      'undone.';

    this.dialogPromise
      .then(() => {
        this.reset();
        FgmState.reset();
        this.exploreIsReady = false;
        this.router.navigateToRoute('home');
      })
      .catch(() => {
        // Nothing
      });
  }

  /**
   * Resume previous exploration
   */
  resumeExploration () {
    this.router.navigateToRoute('explore');
  }

  /**
   * Publish scroll event
   *
   * @param {object} event - Scroll event object.
   */
  scrollHandler (event) {
    this.event.publish('app.scroll', event);
    // this.event.subscribe
  }

  /**
   * Set HiPiler config for exploration
   *
   * @param {object} config - Configuration.
   */
  setConfig (config) {
    if (validateConfig(config.fgm, config.hgl)) {
      this.store.dispatch(updateConfigs(config));
      this.router.navigateToRoute('explore');
    } else {
      this.showGlobalError('Corrupted Config File', 3000);
    }
  }

  /**
   * Show a global error message.
   *
   * @param {string} msg - Message to be displayed.
   * @param {number} duration - Time in milliseconds the error is to be shown.
   */
  showGlobalError (msg, duration = ERROR_DURATION) {
    if (this.globalErrorDisplay) {
      clearTimeout(this.globalErrorDisplay);
    }

    this.globalError = true;
    this.globalErrorMsg = msg;

    this.globalErrorDisplay = setTimeout(
      this.hideGlobalError.bind(this), duration
    );
  }

  /**
   * Update app after the state changed..
   */
  update () {
    const state = this.store.getState().present;

    try {
      this.exploreIsReady = validateConfig(
        state.explore.fragments.config,
        state.explore.higlass.config
      );
    } catch (e) {
      this.exploreIsReady = false;
    }
  }
}
<|endoftext|>


<commit_before>var BUNGIE_API = {
	ADVISORS: 'http://www.bungie.net/Platform/Destiny/Advisors/',
    MANIFEST: {
        ACTIVITY: 'http://www.bungie.net/platform/Destiny/Manifest/Activity/'
    }
};

var ui = require('ui');
var ajax = require('ajax');
var activityData = false;

var MenuActivities = {
	nightfall: {
		title: 'Nightfall',
		subtitle: 'Loading...'
	},
	weekly: {
		title: 'Weekly',
		subtitle: 'Loading...'
	},
	daily: {
		title: 'Daily',
		subtitle: 'Loading...'
	}
};

function updateActivityMenu(activity, item)
{
	var sections = [];

	if(item)
	{
		console.log('Updating menu for ' + activity);
		MenuActivities[activity] = item;
	}

	console.log('Updating activity menu: ' + JSON.stringify(MenuActivities));

	for(var key in MenuActivities)
	{
		if(MenuActivities.hasOwnProperty(key))
		{
			sections.push(MenuActivities[key]);
		}
	}

	console.log(JSON.stringify(sections));
	MainMenu.section(0, {title: 'Activity', items: sections});
}

var MainMenu = new ui.Menu({
	sections: [{
		title: 'Activities',
		items: [{
			title: 'Weekly Nightfall',
			subtitle: ['NF', 'E', 'AB', 'A', 'LS'].join('*')
	},{
			title: 'Weekly Heroic',
			subtitle: ['H', 'LS'].join('*')
		}]
	}]
});

MainMenu.on('select', function(event){
    console.log(JSON.stringify(event));
});

var waitCard = new ui.Card({
	title: 'Loading',
	subtitle: '.'
});

var today = new Date();
var activityData;

// Check for local activity data
try
{
    activityData = localStorage.getItem('activityData');
	activityData = JSON.parse(activityData);

	if(activityData)
	{
        var nfreset;
        var dailyreset;

		// Reset for Tuesday - weeklies reset together, so we can check against the Nightfall
		if(today.getDay() == 2 && (nfreset = new Date(activityData.Response.data.nightfallResetDate)) && today > nfreset) // Tuesday
		{
			throw "Weekly data is stale, pulling some fresh";
		}

        if((dailyreset = new Date(activityData.Response.data.dailyChapterResetDate)) && today > dailyreset)
		{
			throw "Daily data is stale, pulling some fresh";
		}
	}
}
catch(e) {
	console.log('Tried (unsuccessfully) to grab local data: ' + e);
	activityData = false;
}

/**
 * We didn't get any valid activityData so let's pull
 * fresh data from Bungie
 */
if(!activityData)
{
	AjaxWait(); // AJAX Waiter

	ajax({
		url: BUNGIE_API.ADVISORS,
		type: 'json'
	}, function(data){
		activityData = data;
		localStorage.setItem('activityData', JSON.stringify(data));
		ClearWait();
		console.log('Got remote activity data: ' + JSON.stringify(data));
		updateActivities();
	}, function(error){
		ClearWait();
		console.log('Could not get response from ' +  BUNGIE_API.ADVISORS + ': ' + error);
	});
}
else
{
	console.log('Got locally stored activity data: ' + JSON.stringify(activityData.Response.data.nightfallActivityHash));
	updateActivities();
}

MainMenu.show();

var waitInterval;
var waitTick = 1;

function AjaxWait()
{
	waitCard.show();
	MainMenu.hide();

	waitInterval = setInterval(function() {
		var sub = '.';

		if(waitTick == 10)
			waitTick = 1;

		for(var i = 0; i < waitTick; i++)
			sub += '.';

		waitTick++;

		waitCard.subtitle(sub);
	}, 500);
}

function ClearWait()
{
	clearInterval(waitInterval);
	MainMenu.show();
	waitCard.hide();
}

function updateActivities()
{
	var nightfallHash = 'activity-nightfall-' + activityData.Response.data.nightfallActivityHash;
	var weeklyHash = 'activity-weekly-' + activityData.Response.data.heroicStrikeHashes.join('-');
	var dailyHash = 'activity-daily-' + activityData.Response.data.dailyChapterHashes.join('-');

	getLocalData(nightfallHash, function(data){
		var item = {
			title: data.Response.data.activity.activityName,
			subtitle: data.Response.data.activity.activityDescription,
			icon: 'NODE_STRIKE_FEATURED'
		};

		console.log(item);

		updateActivityMenu('nightfall', item);
	});

	getLocalData(weeklyHash, function(data){
		var item = {
			title: data.Response.data.activity.activityName,
			subtitle: data.Response.data.activity.activityDescription
		};

		updateActivityMenu('weekly', item);
	});

    getLocalData(dailyHash, function(data){
        var item = {
            title: data.Response.data.activity.activityName,
            subtitle: data.Response.data.activity.activityDescription
        };

        updateActivityMenu('daily', item);
    });
}

function getLocalData(hash, callback)
{
	var data;
	callback = callback || function() {};

	console.log('Getting local data for hash: ' + hash);

	try
	{
		data = localStorage.getItem(hash);
		data = JSON.parse(data);

		console.log('Data gathered from localStorage for hash `' + hash + '`: ' + JSON.stringify(data));

		if(!data)
			throw 'No activity data for ' + hash + ', fetching fresh data';
	}
	catch(e) {
		console.log('Tried (unsuccessfully) to grab local data for ' + hash + ': ' + e);
		var activityUrl = BUNGIE_API.MANIFEST.ACTIVITY + hash.split('-')[hash.split('-').length-1];

		AjaxWait();

		ajax({
			url: activityUrl,
			type: 'json'
		}, function(data){
			localStorage.setItem(hash, JSON.stringify(data));
			ClearWait();
			console.log('Got remote activity data: ' + JSON.stringify(data));
			callback(data);
		}, function(error){
			ClearWait();
			console.log('Could not get response from ' +  activityUrl + ': ' + error);
		});
	}

	if(data)
	{
		console.log('Found local data for hash ' + hash + ', executing callback');
		callback(data);
	}
}
<commit_msg>Menu events /Users/phatsk/src/pebble/destiny_pebble/resources/sample_data.json<commit_after>var BUNGIE_API = {
	ADVISORS: 'http://www.bungie.net/Platform/Destiny/Advisors/',
    MANIFEST: {
        ACTIVITY: 'http://www.bungie.net/platform/Destiny/Manifest/Activity/'
    }
};

var ui = require('ui');
var ajax = require('ajax');
var activityData = false;

var MenuActivities = {
	nightfall: {
		title: 'Nightfall',
		subtitle: 'Loading...'
	},
	weekly: {
		title: 'Weekly',
		subtitle: 'Loading...'
	},
	daily: {
		title: 'Daily',
		subtitle: 'Loading...'
	}
};

function updateActivityMenu(activity, item)
{
	var sections = [];

	if(item)
	{
		console.log('Updating menu for ' + activity);
		MenuActivities[activity] = item;
	}

	console.log('Updating activity menu: ' + JSON.stringify(MenuActivities));

	for(var key in MenuActivities)
	{
		if(MenuActivities.hasOwnProperty(key))
		{
			sections.push(MenuActivities[key]);
		}
	}

	console.log(JSON.stringify(sections));
	MainMenu.section(0, {title: 'Activity', items: sections});
}

var MainMenu = new ui.Menu({
	sections: [{
		title: 'Activities',
		items: [{
			title: 'Weekly Nightfall',
			subtitle: ['NF', 'E', 'AB', 'A', 'LS'].join('*')
	},{
			title: 'Weekly Heroic',
			subtitle: ['H', 'LS'].join('*')
		}]
	}]
});

MainMenu.on('select', function(event){
    console.log(event);
});

var waitCard = new ui.Card({
	title: 'Loading',
	subtitle: '.'
});

var today = new Date();
var activityData;

// Check for local activity data
try
{
    activityData = localStorage.getItem('activityData');
	activityData = JSON.parse(activityData);

	if(activityData)
	{
        var nfreset;
        var dailyreset;

		// Reset for Tuesday - weeklies reset together, so we can check against the Nightfall
		if(today.getDay() == 2 && (nfreset = new Date(activityData.Response.data.nightfallResetDate)) && today > nfreset) // Tuesday
		{
			throw "Weekly data is stale, pulling some fresh";
		}

        if((dailyreset = new Date(activityData.Response.data.dailyChapterResetDate)) && today > dailyreset)
		{
			throw "Daily data is stale, pulling some fresh";
		}
	}
}
catch(e) {
	console.log('Tried (unsuccessfully) to grab local data: ' + e);
	activityData = false;
}

/**
 * We didn't get any valid activityData so let's pull
 * fresh data from Bungie
 */
if(!activityData)
{
	AjaxWait(); // AJAX Waiter

	ajax({
		url: BUNGIE_API.ADVISORS,
		type: 'json'
	}, function(data){
		activityData = data;
		localStorage.setItem('activityData', JSON.stringify(data));
		ClearWait();
		console.log('Got remote activity data: ' + JSON.stringify(data));
		updateActivities();
	}, function(error){
		ClearWait();
		console.log('Could not get response from ' +  BUNGIE_API.ADVISORS + ': ' + error);
	});
}
else
{
	console.log('Got locally stored activity data: ' + JSON.stringify(activityData.Response.data.nightfallActivityHash));
	updateActivities();
}

MainMenu.show();

var waitInterval;
var waitTick = 1;

function AjaxWait()
{
	waitCard.show();
	MainMenu.hide();

	waitInterval = setInterval(function() {
		var sub = '.';

		if(waitTick == 10)
			waitTick = 1;

		for(var i = 0; i < waitTick; i++)
			sub += '.';

		waitTick++;

		waitCard.subtitle(sub);
	}, 500);
}

function ClearWait()
{
	clearInterval(waitInterval);
	MainMenu.show();
	waitCard.hide();
}

function updateActivities()
{
	var nightfallHash = 'activity-nightfall-' + activityData.Response.data.nightfallActivityHash;
	var weeklyHash = 'activity-weekly-' + activityData.Response.data.heroicStrikeHashes.join('-');
	var dailyHash = 'activity-daily-' + activityData.Response.data.dailyChapterHashes.join('-');

	getLocalData(nightfallHash, function(data){
		var item = {
			title: data.Response.data.activity.activityName,
			subtitle: data.Response.data.activity.activityDescription,
			icon: 'NODE_STRIKE_FEATURED'
		};

		console.log(item);

		updateActivityMenu('nightfall', item);
	});

	getLocalData(weeklyHash, function(data){
		var item = {
			title: data.Response.data.activity.activityName,
			subtitle: data.Response.data.activity.activityDescription
		};

		updateActivityMenu('weekly', item);
	});

    getLocalData(dailyHash, function(data){
        var item = {
            title: data.Response.data.activity.activityName,
            subtitle: data.Response.data.activity.activityDescription
        };

        updateActivityMenu('daily', item);
    });
}

function getLocalData(hash, callback)
{
	var data;
	callback = callback || function() {};

	console.log('Getting local data for hash: ' + hash);

	try
	{
		data = localStorage.getItem(hash);
		data = JSON.parse(data);

		console.log('Data gathered from localStorage for hash `' + hash + '`: ' + JSON.stringify(data));

		if(!data)
			throw 'No activity data for ' + hash + ', fetching fresh data';
	}
	catch(e) {
		console.log('Tried (unsuccessfully) to grab local data for ' + hash + ': ' + e);
		var activityUrl = BUNGIE_API.MANIFEST.ACTIVITY + hash.split('-')[hash.split('-').length-1];

		AjaxWait();

		ajax({
			url: activityUrl,
			type: 'json'
		}, function(data){
			localStorage.setItem(hash, JSON.stringify(data));
			ClearWait();
			console.log('Got remote activity data: ' + JSON.stringify(data));
			callback(data);
		}, function(error){
			ClearWait();
			console.log('Could not get response from ' +  activityUrl + ': ' + error);
		});
	}

	if(data)
	{
		console.log('Found local data for hash ' + hash + ', executing callback');
		callback(data);
	}
}
<|endoftext|>


<commit_before>import React from "react";
import InlineCss from "react-inline-css";
import Transmit from "lib/react-transmit";

/**
 * @class Story
 */
const Story = React.createClass({
	statics: {
		css: () => `
			& {
				padding: 6px 12px;
				border: 1px solid #e1e1e1;
				border-width: 0 1px;
				background: #f6f7f8;
				clear: both;
				font-size: 12px;
			}
			&:last-child {
				border-radius: 0 0 3px 3px;
			}
			& img {
				float: left;
				border: 1px solid #e1e1e1;
				margin-right: 6px;
				width: 20px;
				height: 20px;
			}
			& h4 {
				display: inline-block;
				margin: 4px 0;
			}`
	},
	render() {
		const story = this.props.story;

		/**
		 * Unlike with Relay, Transmit properties aren't guaranteed.
 		 */
		if (!story) {
			return null;
		}

		return (
			<InlineCss stylesheet={Story.css()} namespace="Story">

{story.user.name}

				{story.text}
			</InlineCss>
		);
	}
});

/**
 * Like Relay, export a Transmit container instead of the React component.
 */
export default Transmit.createContainer(Story, {
	queries: {
		story (queryParams, prevProps) {

			return new Promise(function (resolve, reject) {
				resolve({
					user: {
						name:            queryParams.stargazer.login,
						url:             queryParams.stargazer.url,
						profile_picture: {
							uri: `${queryParams.stargazer.avatar_url}&s=20`
						}
					},
					text:   " likes this."
				});
			});
		}
	}
});
<commit_msg>Link to the correct Github pages.<commit_after>import React from "react";
import InlineCss from "react-inline-css";
import Transmit from "lib/react-transmit";

/**
 * @class Story
 */
const Story = React.createClass({
	statics: {
		css: () => `
			& {
				padding: 6px 12px;
				border: 1px solid #e1e1e1;
				border-width: 0 1px;
				background: #f6f7f8;
				clear: both;
				font-size: 12px;
			}
			&:last-child {
				border-radius: 0 0 3px 3px;
			}
			& img {
				float: left;
				border: 1px solid #e1e1e1;
				margin-right: 6px;
				width: 20px;
				height: 20px;
			}
			& h4 {
				display: inline-block;
				margin: 4px 0;
			}`
	},
	render() {
		const story = this.props.story;

		/**
		 * Unlike with Relay, Transmit properties aren't guaranteed.
 		 */
		if (!story) {
			return null;
		}

		return (
			<InlineCss stylesheet={Story.css()} namespace="Story">

{story.user.name}

				{story.text}
			</InlineCss>
		);
	}
});

/**
 * Like Relay, export a Transmit container instead of the React component.
 */
export default Transmit.createContainer(Story, {
	queries: {
		story (queryParams, prevProps) {

			return new Promise(function (resolve, reject) {
				resolve({
					user: {
						name:            queryParams.stargazer.login,
						url:             queryParams.stargazer.html_url,
						profile_picture: {
							uri: `${queryParams.stargazer.avatar_url}&s=20`
						}
					},
					text:   " likes this."
				});
			});
		}
	}
});
<|endoftext|>


<commit_before>/*
 * Notes :
 * need to figure out if there is a way to continously check if
 * the alarms sets off.
 */

/**
 * Welcome to Pebble.js!
 * Test
 * This is where you write your app.
 */

// Calls in required stuff
var UI = require('ui');
var Vibe = require('ui/vibe');
var Settings = require('settings');
var Accel = require('ui/accel');
var date = new Date();

//var time = require('time.js');
//var Vector2 = require('vector2');

// initialize
Accel.init();

/*
var hours = [];
for (var i = 0; i < 24; i++) {
    hours.push(i + 1);
}
var minutes = [];
for (var i = 0; i < 60; i++) {
    minutes.push(i);
}
*/

var alarms = Settings.data('alarms') || [];
var createAlarmItems = function(alarms) {
    var items = [];
    items.push({
        title: "Add New Alarm"
    });
    console.log("alarm length : " + alarms.length);
    if (alarms.length > 0) {
        for (var i = 0; i < alarms.length; i++) {
            items.push({
                title: alarms[i].time,
                subtitle: alarms[i].enabled ? "Enabled" : "Disabled"
            });
            console.log(i);
        }
    }
    console.log("created item list");
    Settings.data('alarms', alarms);
    console.log('saved item list');
    return items;
};

/*
var createTimeItems = function(time) {
    var items = [];
    for (var i = 0; i < time.length; i++) {
        items.push({
            title : time[i]
        });
    }
    return items;
};
*/

var detectTimeLoop = function() {
    date = new Date();
	for (var i = 0; i < alarms.length; i++) {
		//console.log("alarm " + alarms[i].hour + "h " + alarms[i].minute + "m");
		//console.log("actual " + date.getHours() + "h  " + date.getMinutes() + "m");

		// break if no longer valid alarm(s)
		if ( !alarms[i].hour || !alarms[i].minute ) { break; }

		if ( alarms[i].enabled && alarms[i].allowVib && alarms[i].hour == date.getHours() && alarms[i].minute == date.getMinutes() ) {

			Vibe.vibrate('long');
			console.log(i + ": I vibrated");

            if ( date.getSeconds() === 0 ) {

				var card = new UI.Card();
				card.title('Alarm');
				card.subtitle('Is going off!');
				card.body('Press \'select\' to turn it off.');
                main.hide();
				card.show();

				var index = i;
				var count = 0;

				/*
					Increments the count, disables alarm if 4 combinations detected
				*/

				var checkDisable = function() {

					count++;

					if ( count >= 4 ) {
                        console.log("alarm has stopped");
						alarms[index].allowVib = false;
						card.hide();
						main.show();
					}
                    console.log("count : " + count);
				}

				card.on('click', 'select', function(e) {
					checkDisable();
				});

				card.on('click', 'up', function(e) {
					checkDisable();
				});

				card.on('click', 'down', function(e) {
					checkDisable();
				});

				card.on('accelTap', function(e) {
					checkDisable();
                    console.log("tap tap");
				});
            }
		} else if ( alarms[i].hour !== date.getHours() && alarms[i].minute !== date.getMinutes()
					|| ( alarms[i].hour === date.getHours() && alarms[i].minute !== date.getMinutes() )
					|| ( alarms[i].minute === date.getMinutes() && alarms[i].hour !== date.getHours() ) ) {
			// make sure to allow vibrations after alarm minute has passed..
			if ( !alarms[i].allowVib ) {
				alarms[i].allowVib = true;
			}
		}
    }

	setTimeout(function() {
		detectTimeLoop();
	}, 1000);
};

detectTimeLoop();

/*
	Formats time from the 24-hour clock to 12-hour
*/
var formatTime = function( h, m ) {
	var hour = ( h % 12 !== 0 ? h % 12 : 12 );
    var minute = m < 10 ? "0" + m : m;
	return hour + ":" + minute + " " + ( ( h < 12 ) ? "AM" : "PM" );
};

// Sets up the alarms
var alarmItems = createAlarmItems(alarms);

/*
// Creates a loop to make an array of hours
var createHourItems = function() {
  var items = [];
  for (var i = 0; i hideurs.length; i++) {
    items.push({
      title: hours[i]
    });
  }
  return items;
};
*/

/*
var main = new UI.Menu({
   sections:[{
     items: createItems()
  }]
});

main.show();
*/

// The Splashscreen
var splashScreen = new UI.Card({
    title: 'Alarm48',
    icon: 'images/menu_icon.png',
    subtitle: 'The Alarm Built in 48 Hours',
    body: 'UCSC Hack 2015'
    //banner (future plans)
});

// Makes a menu with New Alarms
var main = new UI.Menu({
    sections: [{
        items: alarmItems
        /*
            [{
            title: 'Add New Alarm',
            subtitle: 'New Alarm'
        }, {
            // Dr. Seuss
            title: 'One Alarm'
        }, {
            title: 'Two Alarm'
        }, {
            title: 'Red Alarm'
        }, {
            title: 'Blue Alarm'
        }]
        */
        //, createAlarmItems(alarms)
    }]
});

// Shows the spashscreen and goes to the menu after 400 ms
splashScreen.show();
setTimeout(function() {
    splashScreen.hide();
    main.show();
}, 3000);

var createAlarm = function(callback) {

	date = new Date();

    alarms.push({
        time: formatTime( date.getHours(), date.getMinutes() + 1 ),
        hour: date.getHours(),
        minute: date.getMinutes() + 1,
        enabled: true,
		allowVib: true
    });
    console.log("hour : " + date.getHours());
    console.log("minute : " + date.getMinutes());
    console.log("time : " + formatTime( date.getHours(), date.getMinutes() ));
    callback();
};

main.on('select', function(e) {
    console.log(e.sectionIndex);
    // If it is on the "New Alarm Option"
    if (e.itemIndex === 0) {
        // Has a random card as a placeholder
        //var wind = new UI.Wind();

        var card = new UI.Card();
        card.title('A Card');
        card.subtitle('Is a Window');
        card.body('The simplest window type in Pebble.js.');
        card.show();
        //wind.show();

        // When click the middle button it makes an alarm
        card.on('click', 'select', function() {
            createAlarm(function() {
                alarmItems = createAlarmItems(alarms);
                console.log('Items done');
                console.log(alarmItems);
                card.hide();
                main.section(0, section = {
                    items: alarmItems
                });
                console.log("success");
                //hourChange = new time.hourChange();
                //time.hourChange.show();
            });
        });
    } else {
        // Otherwise the user selects an alarm
        // Creates the Menu for Alarm Options
        var alarmOptions = new UI.Menu({
            sections : [{
                items: [{
                    title: alarms[e.itemIndex - 1].enabled ? 'Disable' : 'Enable'
                }, {
                    title: 'Edit'
                }, {
                    title: 'Delete'
                }]
            }]
        });
        alarmOptions.show();

        alarmOptions.on('select', function(f) {
            var indexOfAlarm = e.itemIndex;
            console.log('index of alarm : ' + indexOfAlarm);
            switch(f.itemIndex) {
                case 0:
                    // Disable or Enable the Alarm
                    for (var i = 0; i < alarms.length; i++) {
                        console.log(i + " : " + alarms[i].enabled);
                        console.log(e.itemIndex - 1 + " : " + alarms[e.itemIndex - 1].enabled);
                    }
                    alarms[e.itemIndex - 1].enabled = !alarms[e.itemIndex - 1].enabled;
                    break;
                case 1:
                    // Edit the time of the alarm
                    break;
                case 2:
                    // Deletes the alarm
                    alarms.splice(e.itemIndex - 1, 1);
                    console.log("deleted at : " + e.itemIndex - 1);
                    break;
                default:
                    console.log("error");
                    break;
            }
            // Update the alarms and gets rid of the option menu
            alarmOptions.hide();
            alarmItems = createAlarmItems(alarms);
            main.section(0, section = {
                items: alarmItems
            });
            //console.log('updated alarms');
        });
    }
    // Choose an option to chnage alarm
});
<commit_msg>set alarm interface<commit_after>/*
 * Notes :
 * need to figure out if there is a way to continously check if
 * the alarms sets off.
 */

/**
 * Welcome to Pebble.js!
 * Test
 * This is where you write your app.
 */

// Calls in required stuff
var UI = require('ui');
var Vibe = require('ui/vibe');
var Settings = require('settings');
var Accel = require('ui/accel');
var date = new Date();

//var time = require('time.js');
//var Vector2 = require('vector2');

// initialize
Accel.init();

/*
var hours = [];
for (var i = 0; i < 24; i++) {
    hours.push(i + 1);
}
var minutes = [];
for (var i = 0; i < 60; i++) {
    minutes.push(i);
}
*/

var alarms = Settings.data('alarms') || [];
var createAlarmItems = function(alarms) {
    var items = [];
    items.push({
        title: "Add New Alarm"
    });
    console.log("alarm length : " + alarms.length);
    if (alarms.length > 0) {
        for (var i = 0; i < alarms.length; i++) {
            items.push({
                title: alarms[i].time,
                subtitle: alarms[i].enabled ? "Enabled" : "Disabled"
            });
            console.log(i);
        }
    }
    console.log("created item list");
    Settings.data('alarms', alarms);
    console.log('saved item list');
    return items;
};

/*
var createTimeItems = function(time) {
    var items = [];
    for (var i = 0; i < time.length; i++) {
        items.push({
            title : time[i]
        });
    }
    return items;
};
*/

var detectTimeLoop = function() {
    date = new Date();
	for (var i = 0; i < alarms.length; i++) {
		//console.log("alarm " + alarms[i].hour + "h " + alarms[i].minute + "m");
		//console.log("actual " + date.getHours() + "h  " + date.getMinutes() + "m");

		// break if no longer valid alarm(s)
		if ( !alarms[i].hour || !alarms[i].minute ) { break; }

		if ( alarms[i].enabled && alarms[i].allowVib && alarms[i].hour == date.getHours() && alarms[i].minute == date.getMinutes() ) {

			Vibe.vibrate('long');
			console.log(i + ": I vibrated");

            if ( date.getSeconds() === 0 ) {

				var card = new UI.Card();
				card.title('Alarm');
				card.subtitle('Is going off!');
				card.body('Press 3 buttons or shake watch to turn it off.');
                main.hide();
				card.show();

				var index = i;
				var count = 0;

				/*
					Increments the count, disables alarm if 4 combinations detected
				*/

				var checkDisable = function() {

					count++;

					if ( count >= 3 ) {
                        console.log("alarm has stopped");
						alarms[index].allowVib = false;
						card.hide();
						main.show();
					}
                    console.log("count : " + count);
				}

				card.on('click', 'select', function(e) {
					checkDisable();
				});

				card.on('click', 'up', function(e) {
					checkDisable();
				});

				card.on('click', 'down', function(e) {
					checkDisable();
				});

				card.on('accelTap', function(e) {
					checkDisable();
                    console.log("tap tap");
				});
            }
		} else if ( alarms[i].hour !== date.getHours() && alarms[i].minute !== date.getMinutes()
					|| ( alarms[i].hour === date.getHours() && alarms[i].minute !== date.getMinutes() )
					|| ( alarms[i].minute === date.getMinutes() && alarms[i].hour !== date.getHours() ) ) {
			// make sure to allow vibrations after alarm minute has passed..
			if ( !alarms[i].allowVib ) {
				alarms[i].allowVib = true;
			}
		}
    }

	setTimeout(function() {
		detectTimeLoop();
	}, 1000);
};

detectTimeLoop();

/*
	Used in add/edit time
*/

var hours = [];
for (var i = 0; i < 24; i++) {
    hours.push(i + 1);
}
var minutes = [];
for (var i = 0; i < 60; i++) {
    minutes.push(i + 1);
}

/*
	Formats time from the 24-hour clock to 12-hour
*/
var formatTime = function( h, m ) {
	var hour = ( h % 12 !== 0 ? h % 12 : 12 );
    var minute = m < 10 ? "0" + m : m;
	return hour + ":" + minute + " " + ( ( h < 12 ) ? "AM" : "PM" );
};

var formatHour = function( h ) {

	return date.getHours() % 12 != 0 ? date.getHours() % 12 : 12
};

var formatMinute = function( m ) {

	return m < 10 ? "0" + m : m;
};

// Sets up the alarms
var alarmItems = createAlarmItems(alarms);

/*
// Creates a loop to make an array of hours
var createHourItems = function() {
  var items = [];
  for (var i = 0; i hideurs.length; i++) {
    items.push({
      title: hours[i]
    });
  }
  return items;
};
*/

/*
var main = new UI.Menu({
   sections:[{
     items: createItems()
  }]
});

main.show();
*/

// The Splashscreen
var splashScreen = new UI.Card({
    title: 'Alarm48',
    icon: 'images/menu_icon.png',
    subtitle: 'The Alarm Built in 48 Hours',
    body: 'UCSC Hack 2015'
    //banner (future plans)
});

// Makes a menu with New Alarms
var main = new UI.Menu({
    sections: [{
        items: alarmItems
        /*
            [{
            title: 'Add New Alarm',
            subtitle: 'New Alarm'
        }, {
            // Dr. Seuss
            title: 'One Alarm'
        }, {
            title: 'Two Alarm'
        }, {
            title: 'Red Alarm'
        }, {
            title: 'Blue Alarm'
        }]
        */
        //, createAlarmItems(alarms)
    }]
});

// Shows the spashscreen and goes to the menu after 400 ms
splashScreen.show();
setTimeout(function() {
    splashScreen.hide();
    main.show();
}, 3000);

var createAlarm = function(callback) {

	date = new Date();

    alarms.push({
        time: formatTime( date.getHours(), date.getMinutes() + 1 ),
        hour: date.getHours(),
        minute: date.getMinutes() + 1,
        enabled: true,
		allowVib: true
    });
    console.log("hour : " + date.getHours());
    console.log("minute : " + date.getMinutes());
    console.log("time : " + formatTime( date.getHours(), date.getMinutes() ));
    callback();
};

main.on('select', function(e) {

	date = new Date();

    console.log(e.sectionIndex);
    // If it is on the "New Alarm Option"
    if (e.itemIndex === 0) {
        // Has a random card as a placeholder
        //var wind = new UI.Wind();

		var wind = new UI.Window({ fullscreen: true });
		var timeText = new UI.Text({
			text: formatTime( date.getHours(), date.getMinutes() ),
			font: 'gothic-18-bold',
			textAlign: 'center',
		});

		wind.add( timeText );
		wind.show();

		//
		var time = [ date.getHours(), date.getMinutes(), date.getHours() < 12 ? 'AM' : 'PM' ];
		var stage = 1;

		wind.on('click', 'select', function(e) {

			stage++;

			// done
			if ( stage > 3 ) {

				createAlarm(function() {
					alarmItems = createAlarmItems(alarms);
					console.log('Items done');
					console.log(alarmItems);
					card.hide();
					main.section(0, section = {
						items: alarmItems
					});
					console.log("success");
				});

				wind.hide();
				main.show();
			}
		});

		wind.on('click', 'up', function(e) {

			if ( stage === 1 ) {

				time[0] = ( time[0] + 1 ) % 24;
			} else if ( stage === 2 ) {

				time[1] = ( time[1] + 1 ) % 60;
			} else {

				time[2] = ( time[2] === 'PM' ? 'AM' : 'PM' );
			}

			timeText.text( formatHour( time[0] ) + ":" + formatMinute( time[1] ) + " " + time[2] );
		});

		wind.on('click', 'down', function(e) {

			if ( stage === 1 ) {

				time[0] = ( time[0] - 1 ) % 24;
			} else if ( stage === 2 ) {

				time[1] = ( time[1] - 1 ) % 60;
			} else {

				time[2] = ( time[2] === 'PM' ? 'AM' : 'PM' );
			}

			timeText.text( formatHour( time[0] ) + ":" + formatMinute( time[1] ) + " " + time[2] );
		});

		/*
        var card = new UI.Card();
        card.title('A Card');
        card.subtitle('Is a Window');
        card.body('The simplest window type in Pebble.js.');
        card.show();*/
        //wind.show();

        // When click the middle button it makes an alarm
        /*card.on('click', 'select', function() {
            createAlarm(function() {
                alarmItems = createAlarmItems(alarms);
                console.log('Items done');
                console.log(alarmItems);
                card.hide();
                main.section(0, section = {
                    items: alarmItems
                });
                console.log("success");
                //hourChange = new time.hourChange();
                //time.hourChange.show();
            });
        });*/
    } else {
        // Otherwise the user selects an alarm
        // Creates the Menu for Alarm Options
        var alarmOptions = new UI.Menu({
            sections : [{
                items: [{
                    title: alarms[e.itemIndex - 1].enabled ? 'Disable' : 'Enable'
                }, {
                    title: 'Edit'
                }, {
                    title: 'Delete'
                }]
            }]
        });
        alarmOptions.show();

        alarmOptions.on('select', function(f) {
            var indexOfAlarm = e.itemIndex;
            console.log('index of alarm : ' + indexOfAlarm);
            switch(f.itemIndex) {
                case 0:
                    // Disable or Enable the Alarm
                    for (var i = 0; i < alarms.length; i++) {
                        console.log(i + " : " + alarms[i].enabled);
                        console.log(e.itemIndex - 1 + " : " + alarms[e.itemIndex - 1].enabled);
                    }
                    alarms[e.itemIndex - 1].enabled = !alarms[e.itemIndex - 1].enabled;
                    break;
                case 1:
                    // Edit the time of the alarm
                    break;
                case 2:
                    // Deletes the alarm
                    alarms.splice(e.itemIndex - 1, 1);
                    console.log("deleted at : " + e.itemIndex - 1);
                    break;
                default:
                    console.log("error");
                    break;
            }
            // Update the alarms and gets rid of the option menu
            alarmOptions.hide();
            alarmItems = createAlarmItems(alarms);
            main.section(0, section = {
                items: alarmItems
            });
            //console.log('updated alarms');
        });
    }
    // Choose an option to chnage alarm
});
<|endoftext|>


<commit_before>import { Observable } from 'rx';
import { div, button } from '@cycle/dom';
import _ from 'lodash';

import seedGrid from './seed_grid'
import updateGrid from './update_grid'

const grid = _.range(0, 50).map(() => {
  return _.range(0, 50).map(() => ({}))
})

const initialState = {
  grid
}

function renderCell (cell) {
  return (
    div(`.cell ${cell.alive ? '.alive' : ''}`)
  )
}

function renderRow (row) {
  return (
    div('.row', row.map(cell => renderCell(cell)))
  )
}

function renderGrid (grid) {
  return (
    div('.grid', grid.map(row => renderRow(row)))
  )
}

function startGame (e) {
  return function seedGame (state) {
    const seededGrid = seedGrid(grid, 0.05)

    return Object.assign({}, state, { grid: seededGrid })
  }
}

function updateGridReducer (e) {
  return function updateGridState (state) {
    return Object.assign({}, state, {grid: updateGrid(state.grid)})
  }
}

export default function App ({DOM}) {
  const startClick$ = DOM
    .select('.start')
    .events('click')

  const tick$ = DOM
    .select('.step')
    .events('click')

  const startGame$ = startClick$
    .map(e => startGame(e))

  const grid$ = tick$
    .map(e => updateGridReducer(e))

  const reducers$ = Observable.merge(
    startGame$,
    grid$
  )

  const state$ = reducers$
    .startWith(initialState)
    .scan((state, reducer) => reducer(state))
    .do(console.log.bind(console, 'state'))

  return {
    DOM: state$.map(({grid}) => (
      div([
        renderGrid(grid),
        button('.start', 'Start'),
        button('.step', 'Step')
      ])
    ))
  };
}<commit_msg>Remove console log<commit_after>import { Observable } from 'rx';
import { div, button } from '@cycle/dom';
import _ from 'lodash';

import seedGrid from './seed_grid'
import updateGrid from './update_grid'

const grid = _.range(0, 50).map(() => {
  return _.range(0, 50).map(() => ({}))
})

const initialState = {
  grid
}

function renderCell (cell) {
  return (
    div(`.cell ${cell.alive ? '.alive' : ''}`)
  )
}

function renderRow (row) {
  return (
    div('.row', row.map(cell => renderCell(cell)))
  )
}

function renderGrid (grid) {
  return (
    div('.grid', grid.map(row => renderRow(row)))
  )
}

function startGame (e) {
  return function seedGame (state) {
    const seededGrid = seedGrid(grid, 0.05)

    return Object.assign({}, state, { grid: seededGrid })
  }
}

function updateGridReducer (e) {
  return function updateGridState (state) {
    return Object.assign({}, state, {grid: updateGrid(state.grid)})
  }
}

export default function App ({DOM}) {
  const startClick$ = DOM
    .select('.start')
    .events('click')

  const tick$ = DOM
    .select('.step')
    .events('click')

  const startGame$ = startClick$
    .map(e => startGame(e))

  const grid$ = tick$
    .map(e => updateGridReducer(e))

  const reducers$ = Observable.merge(
    startGame$,
    grid$
  )

  const state$ = reducers$
    .startWith(initialState)
    .scan((state, reducer) => reducer(state))

  return {
    DOM: state$.map(({grid}) => (
      div([
        renderGrid(grid),
        button('.start', 'Start'),
        button('.step', 'Step')
      ])
    ))
  };
}<|endoftext|>


<commit_before>import { event, select } from 'd3-selection';
import { slider } from '@scola/d3-slider';

export default class App {
  constructor() {
    this._menus = new Set();

    this._width = null;
    this._height = null;
    this._styles = null;

    this._gesture = null;
    this._media = null;
    this._slider = null;

    this._root = select('body')
      .append('div')
      .classed('scola app', true)
      .styles({
        'position': 'relative',
        'z-index': 0
      });

    this._inner = this._root.append('div')
      .classed('scola inner', true)
      .styles({
        'height': '100%',
        'left': 0,
        'position': 'absolute',
        'right': 0
      });
  }

  destroy() {
    this._menus.forEach((menu) => menu.destroy());
    this._menus.clear();

    if (this._gesture) {
      this._gesture.destroy();
      this._gesture = null;
    }

    if (this._media) {
      this._media.destroy();
      this._media = null;
    }

    if (this._slider) {
      this._slider.destroy();
      this._slider = null;
    }

    this._root.dispatch('destroy');
    this._root.remove();
    this._root = null;
  }

  height() {
    return this._height;
  }

  root() {
    return this._root;
  }

  styles() {
    return this._styles;
  }

  width() {
    return this._width;
  }

  append(menu, action = true) {
    if (action === true) {
      this._appendMenu(menu);
    } else if (action === false) {
      this._removeMenu(menu);
    }

    return this;
  }

  gesture(action) {
    if (typeof action === 'undefined') {
      return this._gesture;
    }

    if (action === false) {
      this._gesture.destroy();
      this._gesture = null;

      return this;
    }

    this._gesture = this._root
      .gesture()
      .on('tap', () => this._change())
      .on('swiperight', () => this._change('left'))
      .on('swipeleft', () => this._change('right'));

    return this;
  }

  media(width = '64em', height = '48em', styles = {}) {
    if (width === null) {
      return this._media;
    }

    if (width === false) {
      this._media.destroy();
      this._media = null;

      return this;
    }

    this._width = width;
    this._height = height;
    this._styles = styles;

    this._media = this._root
      .media(`(min-height: ${height}) and (min-width: ${width})`)
      .styles(styles)
      .media(`(min-height: ${height})`)
      .style('height', height)
      .media(`not all and (min-height: ${height})`)
      .style('height', '100%')
      .media(`(min-width: ${width})`)
      .style('width', width)
      .media(`not all and (min-width: ${width})`)
      .styles({
        'width': '100%',
        'height': '100%'
      })
      .start();

    return this;
  }

  slider(action) {
    if (typeof action === 'undefined') {
      return this._slider;
    }

    if (action === false) {
      this._slider.destroy();
      this._slider = null;

      return this;
    }

    this._slider = slider()
      .remove(true)
      .rotate(false);

    this._inner.node()
      .appendChild(this._slider.root().node());

    return this;
  }

  _appendMenu(menu) {
    this._root.node().appendChild(menu.root().node());
    this._menus.add(menu);
    this._bindMenu(menu);
    this._fixMenu();
  }

  _removeMenu(menu) {
    menu.root().remove();
    this._menus.delete(menu);
    this._unbindMenu(menu);
  }

  _bindMenu(menu) {
    menu.root().on('fix.scola-app', this._fixMenu.bind(this));
    menu.root().on('unfix.scola-app', this._fixMenu.bind(this));
    menu.root().on('show.scola-app', this._showMenu.bind(this));
    menu.root().on('hide.scola-app', this._hideMenu.bind(this));
  }

  _unbindMenu(menu) {
    menu.root().on('fix.scola-app', null);
    menu.root().on('unfix.scola-app', null);
    menu.root().on('show.scola-app', null);
    menu.root().on('hide.scola-app', null);
  }

  _fixMenu() {
    const style = {
      left: 0,
      right: 0
    };

    this._menus.forEach((menu) => {
      if (menu.fixed()) {
        style[menu.position()] = menu.width();
      } else {
        menu.hide();
      }
    });

    this._inner.styles(style);

    return this;
  }

  _showMenu() {
    if (event.detail.menu.mode() === 'over') {
      return this;
    }

    const opposite = this._opposite(event.detail.menu.position());
    let oppositePosition = '-' + event.detail.menu.width();

    this._menus.forEach((menu) => {
      if (menu.position() === opposite && menu.fixed()) {
        oppositePosition = '0';
      }
    });

    this._inner
      .transition()
      .style(event.detail.menu.position(), event.detail.menu.width())
      .style(opposite, oppositePosition);

    return this;
  }

  _hideMenu() {
    if (event.detail.menu.mode() === 'over') {
      return this;
    }

    const opposite = this._opposite(event.detail.menu.position());
    let oppositePosition = '0';

    this._menus.forEach((menu) => {
      if (menu.position() === opposite && menu.fixed()) {
        oppositePosition = menu.width();
      }
    });

    this._inner
      .transition()
      .style(event.detail.menu.position(), '0')
      .style(opposite, oppositePosition);

    return this;
  }

  _change(position) {
    let found = false;

    this._menus.forEach((menu) => {
      if (menu.position() === position) {
        return;
      }

      found = found || menu.hide();
    });

    if (found) {
      return;
    }

    this._menus.forEach((menu) => {
      if (found || menu.position() !== position) {
        return;
      }

      found = menu.show();
    });
  }

  _opposite(position) {
    return position === 'left' ? 'right' : 'left';
  }
}
<commit_msg>Bind listeners with arrow functions<commit_after>import { event, select } from 'd3-selection';
import { slider } from '@scola/d3-slider';

export default class App {
  constructor() {
    this._menus = new Set();

    this._width = null;
    this._height = null;
    this._styles = null;

    this._gesture = null;
    this._media = null;
    this._slider = null;

    this._root = select('body')
      .append('div')
      .classed('scola app', true)
      .styles({
        'position': 'relative',
        'z-index': 0
      });

    this._inner = this._root.append('div')
      .classed('scola inner', true)
      .styles({
        'height': '100%',
        'left': 0,
        'position': 'absolute',
        'right': 0
      });
  }

  destroy() {
    this._menus.forEach((menu) => menu.destroy());
    this._menus.clear();

    if (this._gesture) {
      this._gesture.destroy();
      this._gesture = null;
    }

    if (this._media) {
      this._media.destroy();
      this._media = null;
    }

    if (this._slider) {
      this._slider.destroy();
      this._slider = null;
    }

    this._root.dispatch('destroy');
    this._root.remove();
    this._root = null;
  }

  height() {
    return this._height;
  }

  root() {
    return this._root;
  }

  styles() {
    return this._styles;
  }

  width() {
    return this._width;
  }

  append(menu, action = true) {
    if (action === true) {
      this._appendMenu(menu);
    } else if (action === false) {
      this._removeMenu(menu);
    }

    return this;
  }

  gesture(action) {
    if (typeof action === 'undefined') {
      return this._gesture;
    }

    if (action === false) {
      this._gesture.destroy();
      this._gesture = null;

      return this;
    }

    this._gesture = this._root
      .gesture()
      .on('tap', () => this._change())
      .on('swiperight', () => this._change('left'))
      .on('swipeleft', () => this._change('right'));

    return this;
  }

  media(width = '64em', height = '48em', styles = {}) {
    if (width === null) {
      return this._media;
    }

    if (width === false) {
      this._media.destroy();
      this._media = null;

      return this;
    }

    this._width = width;
    this._height = height;
    this._styles = styles;

    this._media = this._root
      .media(`(min-height: ${height}) and (min-width: ${width})`)
      .styles(styles)
      .media(`(min-height: ${height})`)
      .style('height', height)
      .media(`not all and (min-height: ${height})`)
      .style('height', '100%')
      .media(`(min-width: ${width})`)
      .style('width', width)
      .media(`not all and (min-width: ${width})`)
      .styles({
        'width': '100%',
        'height': '100%'
      })
      .start();

    return this;
  }

  slider(action) {
    if (typeof action === 'undefined') {
      return this._slider;
    }

    if (action === false) {
      this._slider.destroy();
      this._slider = null;

      return this;
    }

    this._slider = slider()
      .remove(true)
      .rotate(false);

    this._inner.node()
      .appendChild(this._slider.root().node());

    return this;
  }

  _appendMenu(menu) {
    this._root.node().appendChild(menu.root().node());
    this._menus.add(menu);
    this._bindMenu(menu);
    this._fixMenu();
  }

  _removeMenu(menu) {
    menu.root().remove();
    this._menus.delete(menu);
    this._unbindMenu(menu);
  }

  _bindMenu(menu) {
    menu.root().on('fix.scola-app', () => this._fixMenu());
    menu.root().on('unfix.scola-app', () => this._fixMenu());
    menu.root().on('show.scola-app', () => this._showMenu());
    menu.root().on('hide.scola-app', () => this._hideMenu());
  }

  _unbindMenu(menu) {
    menu.root().on('fix.scola-app', null);
    menu.root().on('unfix.scola-app', null);
    menu.root().on('show.scola-app', null);
    menu.root().on('hide.scola-app', null);
  }

  _fixMenu() {
    const style = {
      left: 0,
      right: 0
    };

    this._menus.forEach((menu) => {
      if (menu.fixed()) {
        style[menu.position()] = menu.width();
      } else {
        menu.hide();
      }
    });

    this._inner.styles(style);

    return this;
  }

  _showMenu() {
    if (event.detail.menu.mode() === 'over') {
      return this;
    }

    const opposite = this._opposite(event.detail.menu.position());
    let oppositePosition = '-' + event.detail.menu.width();

    this._menus.forEach((menu) => {
      if (menu.position() === opposite && menu.fixed()) {
        oppositePosition = '0';
      }
    });

    this._inner
      .transition()
      .style(event.detail.menu.position(), event.detail.menu.width())
      .style(opposite, oppositePosition);

    return this;
  }

  _hideMenu() {
    if (event.detail.menu.mode() === 'over') {
      return this;
    }

    const opposite = this._opposite(event.detail.menu.position());
    let oppositePosition = '0';

    this._menus.forEach((menu) => {
      if (menu.position() === opposite && menu.fixed()) {
        oppositePosition = menu.width();
      }
    });

    this._inner
      .transition()
      .style(event.detail.menu.position(), '0')
      .style(opposite, oppositePosition);

    return this;
  }

  _change(position) {
    let found = false;

    this._menus.forEach((menu) => {
      if (menu.position() === position) {
        return;
      }

      found = found || menu.hide();
    });

    if (found) {
      return;
    }

    this._menus.forEach((menu) => {
      if (found || menu.position() !== position) {
        return;
      }

      found = menu.show();
    });
  }

  _opposite(position) {
    return position === 'left' ? 'right' : 'left';
  }
}
<|endoftext|>


<commit_before>(function($, pm) {

	pm.factory('API', function(UI) {

		return {
            get: get,
            post: post,
            put: put
		};

        function handleError( jqXHR ) {
            var responseText = $.parseJSON(jqXHR.responseText);
            UI.printErrors( responseText.error.error_stack );
        }

        function get( url, onSuccess, onError ) {

            if( !!onSuccess ) onSuccess = function(response) {};
            if( !!onError ) onError = handleError;

            return $.ajax(
                url,
                {
                    type:       'GET',
                    dataType:   'json',
                    success:    onSuccess,
                    error:      onError
                }
            );

        }

        function post( url, data, onSuccess, onError ) {

            if( !!onSuccess ) onSuccess = function(response) {};
            if( !!onError ) onError = handleError;

            return $.ajax(
                url,
                {
                    type:       'POST',
                    data:       JSON.stringify(data),
                    dataType:   'json',
                    success:    onSuccess,
                    error:      onError
                }
            );
        }

        function put( url, data, onSuccess, onError ) {

            if( !!onSuccess ) onSuccess = function(response) {};
            if( !!onError ) onError = handleError;

            return $.ajax(
                url,
                {
                    type:       'PUT',
                    data:       JSON.stringify(data),
                    dataType:   'json',
                    success:    onSuccess,
                    error:      onError
                }
            );

        }

    }, ['UI']);
}(jQuery, PlentyFramework));<commit_msg>Change API's signatures. get(), post() and put() now don't expect callback functions for successful or failed requests. use .done() and .fail() for specifying deferred behaviour<commit_after>(function($, pm) {

	pm.factory('API', function(UI) {

		return {
            get: get,
            post: post,
            put: put
		};

        function handleError( jqXHR ) {
            var responseText = $.parseJSON(jqXHR.responseText);
            UI.printErrors( responseText.error.error_stack );
        }

        function get( url ) {

            return $.ajax(
                url,
                {
                    type:       'GET',
                    dataType:   'json',
                    error:      handleError
                }
            );

        }

        function post( url, data ) {

            return $.ajax(
                url,
                {
                    type:       'POST',
                    data:       JSON.stringify(data),
                    dataType:   'json',
                    error:      handleError
                }
            );
        }

        function put( url, data ) {

            return $.ajax(
                url,
                {
                    type:       'PUT',
                    data:       JSON.stringify(data),
                    dataType:   'json',
                    error:      handleError
                }
            );

        }

    }, ['UI']);
}(jQuery, PlentyFramework));<|endoftext|>


<commit_before>import {createStore, combineReducers} from 'redux';
import React from 'react';

const ENTER_KEY_CODE = 13;

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case 'SHOW_ALL':
      return todos;
    case 'SHOW_COMPLETED':
      return todos.filter(t => t.completed);
    case 'SHOW_INCOMPLETED':
      return todos.filter(t => !t.completed);
    default:
      return todos;
  }
};

const todo = (state, action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        id: action.id,
        text: action.text,
        completed: action.completed
      };
    case 'TOGGLE_TODO':
      if(state.id !== action.id){
        return state;
      }
      return Object.assign({}, state, {completed: !state.completed });
    default:
      return state;
  }
};

const todos = (state = [], action) => {
  const isNotEmpty = (text) => text.replace(/\s/g,'').length > 0;

  switch (action.type) {
    case 'ADD_TODO':
      return isNotEmpty(action.text) ? [...state, todo(undefined, action)] : state;
    case 'REMOVE_TODO':
      return state.filter( t => t.id !== action.id );
    case 'TOGGLE_TODO':
      return state.map( t => todo(t, action));
    default:
      return state;
  }
};

const visibilityFilter = (state = 'SHOW_ALL', action) => {
  switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
      return state = action.filter;
    default:
      return state;
  }
};

const FilterLink = ({filter, children, currentFilter, onClick}) => {
  if (currentFilter === filter) {
    return {children};
  }
  return (
     {
      e.preventDefault();
      onClick(filter);
    }}>{children}
  );
};

const Todo = ({text, completed, onClick}) => (

    {text}

);

const TodoList = ({todos, onTodoClick}) => (

    {todos.map(todo =>
      <Todo
        key={todo.id}
        text={todo.text}
        completed={todo.completed}
        onClick={() => { onTodoClick(todo.id); }} />
    )}

);

const AddTodo = ({addTodoHandler}) => {
  let input;
  return (

      <input
        ref={node => { input = node; }}
        onKeyUp={(e) => {
          if(e.keyCode === ENTER_KEY_CODE) {
            addTodoHandler(input.value);
            input.value = '';
          }
        }}
      />
      <button
        onClick={() => {
          addTodoHandler(input.value);
          input.value = '';
        }}
        >Add</button>

  );
};

const Footer = ({visibilityFilter, onFilterClick}) => (

    Show:
    <FilterLink filter='SHOW_ALL' currentFilter={visibilityFilter} onClick={onFilterClick}>All</FilterLink>,
    <FilterLink filter='SHOW_COMPLETED' currentFilter={visibilityFilter} onClick={onFilterClick}>Completed</FilterLink>,
    <FilterLink filter='SHOW_INCOMPLETED' currentFilter={visibilityFilter} onClick={onFilterClick}>Incompleted</FilterLink>

);

const todosApp = combineReducers({ todos, visibilityFilter });

let nextTodoId = 0;
const TodoApp = ({todos, visibilityFilter}) => (

    <AddTodo addTodoHandler={(text) => {
      store.dispatch({type: 'ADD_TODO', text, id: nextTodoId++});
    }}/>
    <TodoList
      todos={getVisibleTodos(todos, visibilityFilter)}
      onTodoClick={(id) => {
        store.dispatch({type: 'TOGGLE_TODO', id: id});
      }} />

      store.dispatch({ type: 'SET_VISIBILITY_FILTER', filter })
    } />

);

const store = createStore(todosApp);

export { todos, store, TodoApp };
<commit_msg>extract FilterLink container component<commit_after>import {createStore, combineReducers} from 'redux';
import React from 'react';

const ENTER_KEY_CODE = 13;

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case 'SHOW_ALL':
      return todos;
    case 'SHOW_COMPLETED':
      return todos.filter(t => t.completed);
    case 'SHOW_INCOMPLETED':
      return todos.filter(t => !t.completed);
    default:
      return todos;
  }
};

const todo = (state, action) => {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        id: action.id,
        text: action.text,
        completed: action.completed
      };
    case 'TOGGLE_TODO':
      if(state.id !== action.id){
        return state;
      }
      return Object.assign({}, state, {completed: !state.completed });
    default:
      return state;
  }
};

const todos = (state = [], action) => {
  const isNotEmpty = (text) => text.replace(/\s/g,'').length > 0;

  switch (action.type) {
    case 'ADD_TODO':
      return isNotEmpty(action.text) ? [...state, todo(undefined, action)] : state;
    case 'REMOVE_TODO':
      return state.filter( t => t.id !== action.id );
    case 'TOGGLE_TODO':
      return state.map( t => todo(t, action));
    default:
      return state;
  }
};

const visibilityFilter = (state = 'SHOW_ALL', action) => {
  switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
      return state = action.filter;
    default:
      return state;
  }
};

const Link = ({children, active, onClick}) => {
  if (active) {
    return {children};
  }
  return (
     {
      e.preventDefault();
      onClick();
    }}>{children}
  );
};

class FilterLink extends React.Component {
  componentDidMount(){
    this.unsubscribe = store.subscribe(() => this.forceUpdate());
  }
  componentWillUnmount(){
    this.unsubscribe();
  }
  render() {
    const props = this.props;
    const state = store.getState();

    return (
      <Link active={props.filter === state.visibilityFilter} onClick={() => {
        store.dispatch({type: 'SET_VISIBILITY_FILTER', filter: props.filter});
      }}>
        {props.children}
      </Link>
    );
  }
};

const Todo = ({text, completed, onClick}) => (

    {text}

);

const TodoList = ({todos, onTodoClick}) => (

    {todos.map(todo =>
      <Todo
        key={todo.id}
        text={todo.text}
        completed={todo.completed}
        onClick={() => { onTodoClick(todo.id); }} />
    )}

);

const AddTodo = ({addTodoHandler}) => {
  let input;
  return (

      <input
        ref={node => { input = node; }}
        onKeyUp={(e) => {
          if(e.keyCode === ENTER_KEY_CODE) {
            addTodoHandler(input.value);
            input.value = '';
          }
        }}
      />
      <button
        onClick={() => {
          addTodoHandler(input.value);
          input.value = '';
        }}
        >Add</button>

  );
};

const Footer = () => (

    Show:
    <FilterLink filter='SHOW_ALL'>All</FilterLink>,
    <FilterLink filter='SHOW_COMPLETED'>Completed</FilterLink>,
    <FilterLink filter='SHOW_INCOMPLETED'>Incompleted</FilterLink>

);

const todosApp = combineReducers({ todos, visibilityFilter });

let nextTodoId = 0;
const TodoApp = ({todos, visibilityFilter}) => (

    <AddTodo addTodoHandler={(text) => {
      store.dispatch({type: 'ADD_TODO', text, id: nextTodoId++});
    }}/>
    <TodoList
      todos={getVisibleTodos(todos, visibilityFilter)}
      onTodoClick={(id) => {
        store.dispatch({type: 'TOGGLE_TODO', id: id});
      }} />

);

const store = createStore(todosApp);

export { todos, store, TodoApp };
<|endoftext|>


<commit_before>var fs = require('fs')
var assert = require('assert')

function readFile (fp, opts, cb) {
  if (arguments.length === 1) return fs.readFileSync(fp, 'utf8')

  if (arguments.length === 2 && typeof opts === 'function') {
    cb = opts
    opts = 'utf8'
  } else {
    return fs.readFileSync(fp, opts)
  }

  fs.readFile(fp, opts, function (err, data) {
    assert.ifError(err)
    cb(null, data)
  })
}

module.exports = readFile
<commit_msg>update file/readFile.js<commit_after>var fs = require('fs')
var assert = require('assert')

function readFile (fp, opts, cb) {
  if (arguments.length === 1) return fs.readFileSync(fp, 'utf8')

  if (arguments.length === 2 && typeof opts === 'function') {
    cb = opts
    opts = 'utf8'
  } else {
    return fs.readFileSync(fp, opts)
  }

  fs.readFile(fp, opts, function (err, data) {
    assert.ifError(err)
    cb(null, data)
  })
}

function readStream (fp, opts) {
  return fs.createReadStream(fp, opts)
}

module.exports = readFile
module.exports.stream = readStream
<|endoftext|>


<commit_before>// Use new ES6 modules syntax for everything.
import { remote } from 'electron'; // native electron module
import jetpack from 'fs-jetpack'; // module loaded from npm
import $ from "jquery";
import selectize from 'selectize'; // module loaded from npm
import env from './env';
import child_process from "child_process";
import settings from "./helpers/settings";

console.log('Loaded environment variables:', env);
var app = remote.app;
var appDir = jetpack.cwd(app.getAppPath());

console.log('The author of this app is:', appDir.read('package.json', 'json').author);

document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('env-name').innerHTML = env.name;

    $('#select-users').selectize({
        plugins: ['remove_button','restore_on_backspace'],
        delimiter: ',',
        persist: false,
        create: function(input) {
            return {
                value: input,
                text: input
            }
        }
    });

    var buttons = document.getElementsByTagName('button');
    Array.from(buttons).forEach(button => {
        button.addEventListener('click', buttonHandler);
    });

    settings.get().then(val => {
        console.log(val);
    });

});

function buttonHandler(event){
    switch(event.target.id){
        case('get-user-details'):
            getUserDetails();
            break;
        case('start-groupmembership-script'):
            startGroupMembershipScript();
            //TODO start powershell process with group manager tool
            break;
        case('open-email'):
            //TODO email with recipients form user selection
            break;
        default:
            alert('Button handler not implemented for this button')
    }
}

function startGroupMembershipScript() {
    var spawn =  child_process.spawn,child;
    child = spawn("powershell.exe",["powershell.exe -ExecutionPolicy Bypass c:\\temp\\test.ps1"]);
    child.stdout.on("data",function(data){
        console.log("Powershell Data: " + data);
    });
    child.stderr.on("data",function(data){
        console.log("Powershell Errors: " + data);
    });
    child.on("exit",function(){
        console.log("Powershell Script finished");
    });
    child.stdin.end(); //end input
}

function createTextElement(className, content) {
    var newLogEntry = document.createElement('p');
    newLogEntry.innerHTML = content;
    newLogEntry.className = className;
    return newLogEntry;
}

function getUserDetails() {
    var userList = document.getElementById("select-users").value;

    var psADFinderPath = app.getAppPath();

    $('#get-user-details-log').parent().toggleClass('hidden');

    var getUserDetailsButton = document.getElementById("get-user-details");

    //TODO: Refactor this (-->UI handling function)
    getUserDetailsButton.className += "processing";
    getUserDetailsButton.disabled = true;

    psADFinderPath = psADFinderPath+"\\resources\\powershell\\ps-aduser-export-xml\\adUserFinder.ps1";

    var exportFilePath = settings.getSync("findUser.exportFilePath"); //Use the non async method to grantee that exportFilePath is filled

    var unlockButton = function () {
        var getUserDetailsButton = document.getElementById("get-user-details");
        getUserDetailsButton.disabled = false;
        getUserDetailsButton.classList.remove("processing");
    };

    startFindUserScript(psADFinderPath,userList,exportFilePath,unlockButton);

   function startFindUserScript(psADFinderPath, userList, exportFilePath, callback) {
        var executionFile= "powershell.exe -ExecutionPolicy Bypass " + psADFinderPath;
        var executionArguments = " -Users " + userList + " -FilePath " + exportFilePath;

        console.log(executionFile + executionArguments);

        var spawn = child_process.spawn, child;
        child = spawn("powershell.exe", [executionFile + executionArguments]);
        child.stdout.on("data", function (data) {
            console.log("Powershell Data: " + data);
        });
        child.stderr.on("data", function (data) {
            console.log("Powershell Errors: " + data);

            var newLogEntry = createTextElement("log-error", data);
            document.getElementById("get-user-details-log").appendChild(newLogEntry);
        });
        child.on("exit", function () {
            console.log("Powershell Script finished");
            callback();
        });
        child.stdin.end(); //end input

    }

}
<commit_msg>add note about where to continue<commit_after>// Use new ES6 modules syntax for everything.
import { remote } from 'electron'; // native electron module
import jetpack from 'fs-jetpack'; // module loaded from npm
import $ from "jquery";
import selectize from 'selectize'; // module loaded from npm
import env from './env';
import child_process from "child_process";
import settings from "./helpers/settings";

console.log('Loaded environment variables:', env);
var app = remote.app;
var appDir = jetpack.cwd(app.getAppPath());

console.log('The author of this app is:', appDir.read('package.json', 'json').author);

document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('env-name').innerHTML = env.name;

    $('#select-users').selectize({
        plugins: ['remove_button','restore_on_backspace'],
        delimiter: ',',
        persist: false,
        create: function(input) {
            return {
                value: input,
                text: input
            }
        }
    });

    var buttons = document.getElementsByTagName('button');
    Array.from(buttons).forEach(button => {
        button.addEventListener('click', buttonHandler);
    });

    settings.get().then(val => {
        console.log(val);
    });

});

function buttonHandler(event){
    switch(event.target.id){
        case('get-user-details'):
            getUserDetails();
            break;
        case('start-groupmembership-script'):
            startGroupMembershipScript();
            //TODO start powershell process with group manager tool
            break;
        case('open-email'):
            //TODO email with recipients form user selection
            break;
        default:
            alert('Button handler not implemented for this button')
    }
}

function startGroupMembershipScript() {
    var spawn =  child_process.spawn,child;
    child = spawn("powershell.exe",["powershell.exe -ExecutionPolicy Bypass c:\\temp\\test.ps1"]);
    child.stdout.on("data",function(data){
        console.log("Powershell Data: " + data);
    });
    child.stderr.on("data",function(data){
        console.log("Powershell Errors: " + data);
    });
    child.on("exit",function(){
        console.log("Powershell Script finished");
    });
    child.stdin.end(); //end input
}

function createTextElement(className, content) {
    var newLogEntry = document.createElement('p');
    newLogEntry.innerHTML = content;
    newLogEntry.className = className;
    return newLogEntry;
}

function getUserDetails() {
    var userList = document.getElementById("select-users").value;

    if( !userList ){
      alert("please specify users!");
      return
    }
    var psADFinderPath = app.getAppPath();

    $('#get-user-details-log').parent().toggleClass('hidden');

    var getUserDetailsButton = document.getElementById("get-user-details");

    //TODO: Refactor this (-->UI handling function)
    getUserDetailsButton.className += "processing";
    getUserDetailsButton.disabled = true;

    psADFinderPath = psADFinderPath+"\\resources\\powershell\\ps-aduser-export-xml\\adUserFinder.ps1";

    var exportFilePath = settings.getSync("findUser.exportFilePath"); //Use the non async method to grantee that exportFilePath is filled

    var unlockButton = function () {
        var getUserDetailsButton = document.getElementById("get-user-details");
        getUserDetailsButton.disabled = false;
        getUserDetailsButton.classList.remove("processing");
    };

    startFindUserScript(psADFinderPath,userList,exportFilePath,unlockButton);

   function startFindUserScript(psADFinderPath, userList, exportFilePath, callback) {

        //TODO: make string into @() array

        var executionFile = "powershell.exe -ExecutionPolicy Bypass " + psADFinderPath;
        var executionArguments = " -Users " + userList + " -FilePath " + exportFilePath;

        console.log(executionFile + executionArguments);

        var spawn = child_process.spawn, child;
        child = spawn("powershell.exe", [executionFile + executionArguments]);
        child.stdout.on("data", function (data) {
            console.log("Powershell Data: " + data);

        });
        child.stderr.on("data", function (data) {
            console.log("Powershell Errors: " + data);

            var newLogEntry = createTextElement("log-error", data);
            document.getElementById("get-user-details-log").appendChild(newLogEntry);
        });
        child.on("exit", function () {
            console.log("Powershell Script finished");
            callback();
        });
        child.stdin.end(); //end input

    }

}
<|endoftext|>