<commit_before>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2015  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import React from 'react';
import { connect } from 'react-redux';
import request from 'superagent';
import _ from 'lodash';

import Header from '../components/header';
import Footer from '../components/footer';
import River from '../components/river_of_posts';
import Followed from '../components/most_followed_people';
import Tags from '../components/popular_tags'
import Sidebar from '../components/sidebar'
import {API_HOST} from '../config';
import {getStore, addUser, setUserPosts, addError} from '../store';

class FollowButton extends React.Component {
  async followUser(event) {
    event.preventDefault();

    let user = this.props.page_user;

    try {
      let res = await request.post(`${API_HOST}/api/v1/user/${user.username}/follow`);

      if ('user' in res.body) {
        getStore().dispatch(addUser(res.body.user));
      }
    } catch (e) {
      getStore().dispatch(addError(e.message));
    }
  };

  async unfollowUser(event) {
    event.preventDefault();

    let user = this.props.page_user;

    try {
      let res = await request.post(`${API_HOST}/api/v1/user/${user.username}/unfollow`);

      if ('user' in res.body) {
        getStore().dispatch(addUser(res.body.user));
      }
    } catch (e) {
      getStore().dispatch(addError(e.message));
    }
  };

  render() {
    if (_.isUndefined(this.props.current_user)) {
      return


<commit_before>import React from 'react'
import classnames from 'classnames'
//
// import _ from './utils'

const defaultButton = (props) => (
  <button {...props} className='-btn'>{props.children}</button>
)

export default React.createClass({
  getInitialState () {
    return {
      page: this.props.currentPage
    }
  },
  componentWillReceiveProps (nextProps) {
    this.setState({page: nextProps.currentPage})
  },
  getSafePage (page) {
    return Math.min(Math.max(page, 0), this.props.pagesLength - 1)
  },
  changePage (page) {
    page = this.getSafePage(page)
    this.setState({page})
    this.props.onChange(page)
  },
  applyPage (e) {
    e && e.preventDefault()
    const page = this.state.page
    this.changePage(page === '' ? this.props.currentPage : page)
  },
  render () {
    const {
      currentPage,
      pagesLength,
      showPageSizeOptions,
      pageSizeOptions,
      pageSize,
      showPageJump,
      canPrevious,
      canNext,
      onPageSizeChange
    } = this.props

    const PreviousComponent = this.props.PreviousComponent || defaultButton
    const NextComponent = this.props.NextComponent || defaultButton

    return (

          <PreviousComponent
            onClick={(e) => {
              if (!canPrevious) return
              this.changePage(currentPage - 1)
            }}
            disabled={!canPrevious}
          >
            {this.props.previousText}
          </PreviousComponent>

            Page {showPageJump ? (
              <form className='-pageJump'
                onSubmit={this.applyPage}
              >
                <input
                  type={this.state.page === '' ? 'text' : 'number'}
                  onChange={e => {
                    const val = e.target.value
                    const page = val - 1
                    if (val === '') {
                      return this.setState({page: val})
                    }
                    this.setState({page: this.getSafePage(page)})
                  }}
                  value={this.state.page === '' ? '' : this.state.page + 1}
                  onBlur={this.applyPage}
                />
              </form>
              ) : (
                {currentPage + 1}
            )} of {pagesLength}

          {showPageSizeOptions && (

              <select
                onChange={(e) => onPageSizeChange(Number(e.target.value))}
                value={pageSize}
              >
                {pageSizeOptions.map((option, i) => {
                  return (
                    <option
                      key={i}
                      value={option}>
                      {option} rows
                    </option>
                  )
                })}
              </select>

          )}

          <NextComponent
            onClick={(e) => {
              if (!canNext) return
              this.changePage(currentPage + 1)
            }}
            disabled={!canNext}
          >
            {this.props.nextText}
          </NextComponent>

    )
  }
})
<commit_msg>Fix typo when overriding pagination components (#17)<commit_after>import React from 'react'
import classnames from 'classnames'
//
// import _ from './utils'

const defaultButton = (props) => (
  <button {...props} className='-btn'>{props.children}</button>
)

export default React.createClass({
  getInitialState () {
    return {
      page: this.props.currentPage
    }
  },
  componentWillReceiveProps (nextProps) {
    this.setState({page: nextProps.currentPage})
  },
  getSafePage (page) {
    return Math.min(Math.max(page, 0), this.props.pagesLength - 1)
  },
  changePage (page) {
    page = this.getSafePage(page)
    this.setState({page})
    this.props.onChange(page)
  },
  applyPage (e) {
    e && e.preventDefault()
    const page = this.state.page
    this.changePage(page === '' ? this.props.currentPage : page)
  },
  render () {
    const {
      currentPage,
      pagesLength,
      showPageSizeOptions,
      pageSizeOptions,
      pageSize,
      showPageJump,
      canPrevious,
      canNext,
      onPageSizeChange
    } = this.props

    const PreviousComponent = this.props.previousComponent || defaultButton
    const NextComponent = this.props.nextComponent || defaultButton

    return (

          <PreviousComponent
            onClick={(e) => {
              if (!canPrevious) return
              this.changePage(currentPage - 1)
            }}
            disabled={!canPrevious}
          >
            {this.props.previousText}
          </PreviousComponent>

            Page {showPageJump ? (
              <form className='-pageJump'
                onSubmit={this.applyPage}
              >
                <input
                  type={this.state.page === '' ? 'text' : 'number'}
                  onChange={e => {
                    const val = e.target.value
                    const page = val - 1
                    if (val === '') {
                      return this.setState({page: val})
                    }
                    this.setState({page: this.getSafePage(page)})
                  }}
                  value={this.state.page === '' ? '' : this.state.page + 1}
                  onBlur={this.applyPage}
                />
              </form>
              ) : (
                {currentPage + 1}
            )} of {pagesLength}

          {showPageSizeOptions && (

              <select
                onChange={(e) => onPageSizeChange(Number(e.target.value))}
                value={pageSize}
              >
                {pageSizeOptions.map((option, i) => {
                  return (
                    <option
                      key={i}
                      value={option}>
                      {option} rows
                    </option>
                  )
                })}
              </select>

          )}

          <NextComponent
            onClick={(e) => {
              if (!canNext) return
              this.changePage(currentPage + 1)
            }}
            disabled={!canNext}
          >
            {this.props.nextText}
          </NextComponent>

    )
  }
})
<|endoftext|>


<commit_before>import alloc from './alloc.js';
import bigEndianByteArrayParser from './bigEndianByteArrayParser.js';
import ByteStream from './byteStream.js';
import DataSet from './dataSet.js';
import littleEndianByteArrayParser from './littleEndianByteArrayParser.js';
import readPart10Header from './readPart10Header.js';
import sharedCopy from './sharedCopy.js';
import * as byteArrayParser from './byteArrayParser.js';
import * as parseDicomDataSet from './parseDicomDataSet.js';

/**
 * Parses a DICOM P10 byte array and returns a DataSet object with the parsed elements.
 * If the options argument is supplied and it contains the untilTag property, parsing
 * will stop once that tag is encoutered.  This can be used to parse partial byte streams.
 *
 * @param byteArray the byte array
 * @param options object to control parsing behavior (optional)
 * @returns {DataSet}
 * @throws error if an error occurs while parsing.  The exception object will contain a
 *         property dataSet with the elements successfully parsed before the error.
 */

export default function parseDicom (byteArray, options) {
  if (byteArray === undefined) {
    throw 'dicomParser.parseDicom: missing required parameter \'byteArray\'';
  }

  function readTransferSyntax (metaHeaderDataSet) {
    if (metaHeaderDataSet.elements.x00020010 === undefined) {
      throw 'dicomParser.parseDicom: missing required meta header attribute 0002,0010';
    }

    const transferSyntaxElement = metaHeaderDataSet.elements.x00020010;

    return byteArrayParser.readFixedString(byteArray, transferSyntaxElement.dataOffset, transferSyntaxElement.length);
  }

  function isExplicit (transferSyntax) {
    // implicit little endian
    if (transferSyntax === '1.2.840.10008.1.2') {
      return false;
    }

    // all other transfer syntaxes should be explicit
    return true;
  }

  function getDataSetByteStream (transferSyntax, position) {
    if (transferSyntax === '1.2.840.10008.1.2.1.99') {
      // if an infalter callback is registered, use it
      if (options && options.inflater) {
        const fullByteArrayCallback = options.inflater(byteArray, position);

        return new ByteStream(littleEndianByteArrayParser, fullByteArrayCallback, 0);
      }
      // if running on node, use the zlib library to inflate
      // http://stackoverflow.com/questions/4224606/how-to-check-whether-a-script-is-running-under-node-js
      else if (typeof module !== 'undefined' && this.module !== module) {
        // inflate it
        const zlib = require('zlib');
        const deflatedBuffer = sharedCopy(byteArray, position, byteArray.length - position);
        const inflatedBuffer = zlib.inflateRawSync(deflatedBuffer);

        // create a single byte array with the full header bytes and the inflated bytes
        const fullByteArrayBuffer = alloc(byteArray, inflatedBuffer.length + position);

        byteArray.copy(fullByteArrayBuffer, 0, 0, position);
        inflatedBuffer.copy(fullByteArrayBuffer, position);

        return new ByteStream(littleEndianByteArrayParser, fullByteArrayBuffer, 0);
      }
      // if pako is defined - use it.  This is the web browser path
      // https://github.com/nodeca/pako
      else if (typeof pako !== 'undefined') {
        // inflate it
        const deflated = byteArray.slice(position);
        const inflated = pako.inflateRaw(deflated);

        // create a single byte array with the full header bytes and the inflated bytes
        const fullByteArray = alloc(byteArray, inflated.length + position);

        fullByteArray.set(byteArray.slice(0, position), 0);
        fullByteArray.set(inflated, position);

        return new ByteStream(littleEndianByteArrayParser, fullByteArray, 0);
      }

      // throw exception since no inflater is available
      throw 'dicomParser.parseDicom: no inflater available to handle deflate transfer syntax';
    }

    // explicit big endian
    if (transferSyntax === '1.2.840.10008.1.2.2') {
      return new ByteStream(bigEndianByteArrayParser, byteArray, position);
    }

    // all other transfer syntaxes are little endian; only the pixel encoding differs
    // make a new stream so the metaheader warnings don't come along for the ride
    return new ByteStream(littleEndianByteArrayParser, byteArray, position);
  }

  function mergeDataSets (metaHeaderDataSet, instanceDataSet) {
    for (const propertyName in metaHeaderDataSet.elements) {
      if (metaHeaderDataSet.elements.hasOwnProperty(propertyName)) {
        instanceDataSet.elements[propertyName] = metaHeaderDataSet.elements[propertyName];
      }
    }

    if (metaHeaderDataSet.warnings !== undefined) {
      instanceDataSet.warnings = metaHeaderDataSet.warnings.concat(instanceDataSet.warnings);
    }

    return instanceDataSet;
  }

  function readDataSet (metaHeaderDataSet) {
    const transferSyntax = readTransferSyntax(metaHeaderDataSet);
    const explicit = isExplicit(transferSyntax);
    const dataSetByteStream = getDataSetByteStream(transferSyntax, metaHeaderDataSet.position);

    const elements = {};
    const dataSet = new DataSet(dataSetByteStream.byteArrayParser, dataSetByteStream.byteArray, elements);

    dataSet.warnings = dataSetByteStream.warnings;

    try {
      if (explicit) {
        parseDicomDataSet.parseDicomDataSetExplicit(dataSet, dataSetByteStream, dataSetByteStream.byteArray.length, options);
      } else {
        parseDicomDataSet.parseDicomDataSetImplicit(dataSet, dataSetByteStream, dataSetByteStream.byteArray.length, options);
      }
    } catch (e) {
      const ex = {
        exception: e,
        dataSet
      };

      throw ex;
    }

    return dataSet;
  }

  // main function here
  function parseTheByteStream () {
    const metaHeaderDataSet = readPart10Header(byteArray, options);
    const dataSet = readDataSet(metaHeaderDataSet);

    return mergeDataSets(metaHeaderDataSet, dataSet);
  }

  // This is where we actually start parsing
  return parseTheByteStream();
}
<commit_msg>fix: prevent undefined module error when checking if we are in a browser or node.js environment (#176)<commit_after>import alloc from './alloc.js';
import bigEndianByteArrayParser from './bigEndianByteArrayParser.js';
import ByteStream from './byteStream.js';
import DataSet from './dataSet.js';
import littleEndianByteArrayParser from './littleEndianByteArrayParser.js';
import readPart10Header from './readPart10Header.js';
import sharedCopy from './sharedCopy.js';
import * as byteArrayParser from './byteArrayParser.js';
import * as parseDicomDataSet from './parseDicomDataSet.js';

/**
 * Parses a DICOM P10 byte array and returns a DataSet object with the parsed elements.
 * If the options argument is supplied and it contains the untilTag property, parsing
 * will stop once that tag is encoutered.  This can be used to parse partial byte streams.
 *
 * @param byteArray the byte array
 * @param options object to control parsing behavior (optional)
 * @returns {DataSet}
 * @throws error if an error occurs while parsing.  The exception object will contain a
 *         property dataSet with the elements successfully parsed before the error.
 */

export default function parseDicom (byteArray, options) {
  if (byteArray === undefined) {
    throw 'dicomParser.parseDicom: missing required parameter \'byteArray\'';
  }

  function readTransferSyntax (metaHeaderDataSet) {
    if (metaHeaderDataSet.elements.x00020010 === undefined) {
      throw 'dicomParser.parseDicom: missing required meta header attribute 0002,0010';
    }

    const transferSyntaxElement = metaHeaderDataSet.elements.x00020010;

    return byteArrayParser.readFixedString(byteArray, transferSyntaxElement.dataOffset, transferSyntaxElement.length);
  }

  function isExplicit (transferSyntax) {
    // implicit little endian
    if (transferSyntax === '1.2.840.10008.1.2') {
      return false;
    }

    // all other transfer syntaxes should be explicit
    return true;
  }

  function getDataSetByteStream (transferSyntax, position) {
    // Detect whether we are inside a browser or Node.js
    const isNode = (typeof window === 'undefined');

    if (transferSyntax === '1.2.840.10008.1.2.1.99') {
      // if an infalter callback is registered, use it
      if (options && options.inflater) {
        const fullByteArrayCallback = options.inflater(byteArray, position);

        return new ByteStream(littleEndianByteArrayParser, fullByteArrayCallback, 0);
      }
      // if running on node, use the zlib library to inflate
      // http://stackoverflow.com/questions/4224606/how-to-check-whether-a-script-is-running-under-node-js
      else if (isNode === true) {
        // inflate it
        const zlib = require('zlib');
        const deflatedBuffer = sharedCopy(byteArray, position, byteArray.length - position);
        const inflatedBuffer = zlib.inflateRawSync(deflatedBuffer);

        // create a single byte array with the full header bytes and the inflated bytes
        const fullByteArrayBuffer = alloc(byteArray, inflatedBuffer.length + position);

        byteArray.copy(fullByteArrayBuffer, 0, 0, position);
        inflatedBuffer.copy(fullByteArrayBuffer, position);

        return new ByteStream(littleEndianByteArrayParser, fullByteArrayBuffer, 0);
      }
      // if pako is defined - use it.  This is the web browser path
      // https://github.com/nodeca/pako
      else if (typeof pako !== 'undefined') {
        // inflate it
        const deflated = byteArray.slice(position);
        const inflated = pako.inflateRaw(deflated);

        // create a single byte array with the full header bytes and the inflated bytes
        const fullByteArray = alloc(byteArray, inflated.length + position);

        fullByteArray.set(byteArray.slice(0, position), 0);
        fullByteArray.set(inflated, position);

        return new ByteStream(littleEndianByteArrayParser, fullByteArray, 0);
      }

      // throw exception since no inflater is available
      throw 'dicomParser.parseDicom: no inflater available to handle deflate transfer syntax';
    }

    // explicit big endian
    if (transferSyntax === '1.2.840.10008.1.2.2') {
      return new ByteStream(bigEndianByteArrayParser, byteArray, position);
    }

    // all other transfer syntaxes are little endian; only the pixel encoding differs
    // make a new stream so the metaheader warnings don't come along for the ride
    return new ByteStream(littleEndianByteArrayParser, byteArray, position);
  }

  function mergeDataSets (metaHeaderDataSet, instanceDataSet) {
    for (const propertyName in metaHeaderDataSet.elements) {
      if (metaHeaderDataSet.elements.hasOwnProperty(propertyName)) {
        instanceDataSet.elements[propertyName] = metaHeaderDataSet.elements[propertyName];
      }
    }

    if (metaHeaderDataSet.warnings !== undefined) {
      instanceDataSet.warnings = metaHeaderDataSet.warnings.concat(instanceDataSet.warnings);
    }

    return instanceDataSet;
  }

  function readDataSet (metaHeaderDataSet) {
    const transferSyntax = readTransferSyntax(metaHeaderDataSet);
    const explicit = isExplicit(transferSyntax);
    const dataSetByteStream = getDataSetByteStream(transferSyntax, metaHeaderDataSet.position);

    const elements = {};
    const dataSet = new DataSet(dataSetByteStream.byteArrayParser, dataSetByteStream.byteArray, elements);

    dataSet.warnings = dataSetByteStream.warnings;

    try {
      if (explicit) {
        parseDicomDataSet.parseDicomDataSetExplicit(dataSet, dataSetByteStream, dataSetByteStream.byteArray.length, options);
      } else {
        parseDicomDataSet.parseDicomDataSetImplicit(dataSet, dataSetByteStream, dataSetByteStream.byteArray.length, options);
      }
    } catch (e) {
      const ex = {
        exception: e,
        dataSet
      };

      throw ex;
    }

    return dataSet;
  }

  // main function here
  function parseTheByteStream () {
    const metaHeaderDataSet = readPart10Header(byteArray, options);
    const dataSet = readDataSet(metaHeaderDataSet);

    return mergeDataSets(metaHeaderDataSet, dataSet);
  }

  // This is where we actually start parsing
  return parseTheByteStream();
}
<|endoftext|>


<commit_before>/**
 * Patterns slides - Automatic and customised slideshows.
 *
 * Copyright 2013 Simplon B.V. - Wichert Akkerman
 */
define([
    "jquery",
    "../registry",
    "shower"
], function($, patterns) {
    var slides = {
        name: "slides",

        init: function($el) {
            return $el;
        }
    };

    patterns.register(slides);
    return slides;
});
<commit_msg>Slides: re-init shower after injection has happened.<commit_after>/**
 * Patterns slides - Automatic and customised slideshows.
 *
 * Copyright 2013 Simplon B.V. - Wichert Akkerman
 */
define([
    "jquery",
    "../registry",
    "shower"
], function($, patterns) {
    var slides = {
        name: "slides",

        init: function($el) {
            return $el;
        }
    };

    $(document).on("patterns-injected", function() {
        shower.init();
    });

    patterns.register(slides);
    return slides;
});
<|endoftext|>


<commit_before>/**
 * Main AngularJS Web Application
 */
var app = angular.module('tutorialWebApp', [
  'ngRoute'
]);
/**
 * Configure the Routes
 */
app.config(['$routeProvider', function ($routeProvider) {
  $routeProvider
    // Home
    .when("/", {templateUrl: "partials/login.html", controller: "PageCtrl"})
    // Pages

      .when("/about", {templateUrl: "partials/about.html", controller: "PageCtrl"})
      .when("/ActiveC", {templateUrl: "partials/about.html", controller: "PageCtrl"})
      .when("/login", {templateUrl: "partials/login.html", controller: "PageCtrl"})
      .when("/faq", {templateUrl: "partials/faq.html", controller: "PageCtrl"})
      .when("/main", {templateUrl: "partials/main.php", controller: "PageCtrl"})
      .when("/forgot", {templateUrl: "partials/forgot.html", controller: "PageCtrl"})
	  //.when("/services", {templateUrl: "partials/services.html", controller: "PageCtrl"})
      .when("/contact", {templateUrl: "partials/contact.php", controller: "PageCtrl"})
	  .when("/404", {templateUrl: "partials/404.html", controller: "PageCtrl"})
      .when("/signout", {templateUrl: "partials/signout.php", controller: "PageCtrl"})
      //.when("/blog", {templateUrl: "partials/blog.html", controller: "BlogCtrl"})
      .when("/blog/post", {templateUrl: "partials/blog_item.html", controller: "BlogCtrl"})
      .when("/reset", {templateUrl: "partials/reset_password.php", controller: "PageCtrl"})

  // else 404
    .otherwise({redirectTo: "404"});
}]);

/**
 * Controls the Blog
 */
app.controller('BlogCtrl', function (/* $scope, $location, $http */) {
  console.log("Blog Controller reporting for duty.");
});

/**
 * Controls all other Pages
 */
app.controller('PageCtrl', function ( $location /* $scope, $location, $http */) {
  console.log("Page Controller reporting for duty."+" "+$location.path());

  // Activates the Carousel
  $('.carousel').carousel({
    interval: 5000
  });
  $("#main_wrap").ready( function () {
    $("#show_stud").toggle();
  });
  $("#show_all").click(function(){
   /* $("#show_std").toggle("slow", function() {
      // Animation complete.
    });*/
  });
  // Activates Tooltips for Social Links
  $('.tooltip-social').tooltip({
    selector: "a[data-toggle=tooltip]"
  })
});<commit_msg>students-companies integration<commit_after>/**
 * Main AngularJS Web Application
 */
var app = angular.module('tutorialWebApp', [
  'ngRoute'
]);
/**
 * Configure the Routes
 */
app.config(['$routeProvider', function ($routeProvider) {
  $routeProvider
    // Home
    .when("/", {templateUrl: "partials/login.html", controller: "PageCtrl"})
    // Pages

      .when("/about", {templateUrl: "partials/about.html", controller: "PageCtrl"})
      .when("/ActiveC", {templateUrl: "job.madeinjlm.org/MadeinJLM-students/mockup/companies", controller: "PageCtrl"})
      .when("/login", {templateUrl: "partials/login.html", controller: "PageCtrl"})
      .when("/faq", {templateUrl: "partials/faq.html", controller: "PageCtrl"})
      .when("/main", {templateUrl: "partials/main.php", controller: "PageCtrl"})
      .when("/forgot", {templateUrl: "partials/forgot.html", controller: "PageCtrl"})
	  //.when("/services", {templateUrl: "partials/services.html", controller: "PageCtrl"})
      .when("/contact", {templateUrl: "partials/contact.php", controller: "PageCtrl"})
	  .when("/404", {templateUrl: "partials/404.html", controller: "PageCtrl"})
      .when("/signout", {templateUrl: "partials/signout.php", controller: "PageCtrl"})
      //.when("/blog", {templateUrl: "partials/blog.html", controller: "BlogCtrl"})
      .when("/blog/post", {templateUrl: "partials/blog_item.html", controller: "BlogCtrl"})
      .when("/reset", {templateUrl: "partials/reset_password.php", controller: "PageCtrl"})

  // else 404
    .otherwise({redirectTo: "404"});
}]);

/**
 * Controls the Blog
 */
app.controller('BlogCtrl', function (/* $scope, $location, $http */) {
  console.log("Blog Controller reporting for duty.");
});

/**
 * Controls all other Pages
 */
app.controller('PageCtrl', function ( $location /* $scope, $location, $http */) {
  console.log("Page Controller reporting for duty."+" "+$location.path());

  // Activates the Carousel
  $('.carousel').carousel({
    interval: 5000
  });
  $("#main_wrap").ready( function () {
    $("#show_stud").toggle();
  });
  $("#show_all").click(function(){
   /* $("#show_std").toggle("slow", function() {
      // Animation complete.
    });*/
  });
  // Activates Tooltips for Social Links
  $('.tooltip-social').tooltip({
    selector: "a[data-toggle=tooltip]"
  })
});<|endoftext|>


<commit_before>import _ from 'lodash';
import Promise from 'bluebird'
import Stream from 'stream';

import { scopeHandlers } from './scope';

export class Projection extends Stream.Writable {
    constructor(scope, handlers, queries, store, stamp = 0) {
        super({ objectMode: true });

        this._scope = scope;
        this._handlers = _.reduce(handlers, (handlers, events, scope) =>
            _.defaults(handlers, scopeHandlers(scope, events)), {});
        this._queries = scopeHandlers(scope, queries);

        this._store = store;
        this._stamp = stamp;
    }

    get stamp() { return this._stamp; }
    get scope() { return this._scope; }
    get events() { return _.keys(this._handlers); }
    get queries() { return _.keys(this._queries); }

    project(stream) {
        return new Promise((resolve, reject) => {
            const projection = new Stream.Writable({
                objectMode: true,
                write: (event, encoding, done) =>
                    this.handle(event)
                        .then(() => done())
                        .catch((err) => done(err))
            });
            projection
                .once('error', reject)
                .once('finish', resolve);
            stream.pipe(projection);
        });
    }

    handle(event) {
        if (event.stamp <= this._stamp)
            return Promise.resolve();
        const handler = this._handlers[event.name];
        if (!handler)
            return Promise.resolve();
        return handler(this._store.collection, event.aggregate, event.payload, event.date)
            .then(() => this._store.set('stamp', event.stamp))
            .then(() => this._stamp = event.stamp);
    }

    query(name, payload) {
        return new Promise((resolve, reject) => {
            const handler = this._queries[name];
            if  (!handler)
                return reject(new Error(`there is no handler with name [${name}] to process the query`));
            return resolve(handler(this._store.collection, payload));
        });
    }
}
<commit_msg>projection stream fix<commit_after>import _ from 'lodash';
import Promise from 'bluebird'
import Stream from 'stream';

import { scopeHandlers } from './scope';

export class Projection {
    constructor(scope, handlers, queries, store, stamp = 0) {
        this._scope = scope;
        this._handlers = _.reduce(handlers, (handlers, events, scope) =>
            _.defaults(handlers, scopeHandlers(scope, events)), {});
        this._queries = scopeHandlers(scope, queries);

        this._store = store;
        this._stamp = stamp;
    }

    get stamp() { return this._stamp; }
    get scope() { return this._scope; }
    get events() { return _.keys(this._handlers); }
    get queries() { return _.keys(this._queries); }

    project(stream) {
        return new Promise((resolve, reject) => {
            const projection = new Stream.Writable({
                objectMode: true,
                write: (event, encoding, done) =>
                    this.handle(event)
                        .then(() => done())
                        .catch((err) => done(err))
            });
            projection
                .once('error', reject)
                .once('finish', resolve);
            stream.pipe(projection);
        });
    }

    handle(event) {
        if (event.stamp <= this._stamp)
            return Promise.resolve();
        const handler = this._handlers[event.name];
        if (!handler)
            return Promise.resolve();
        return handler(this._store.collection, event.aggregate, event.payload, event.date)
            .then(() => this._store.set('stamp', event.stamp))
            .then(() => this._stamp = event.stamp);
    }

    query(name, payload) {
        return new Promise((resolve, reject) => {
            const handler = this._queries[name];
            if  (!handler)
                return reject(new Error(`there is no handler with name [${name}] to process the query`));
            return resolve(handler(this._store.collection, payload));
        });
    }
}
<|endoftext|>


<commit_before>/// Copyright by Erik Weitnauer, 2012.

/// The point class represents a point or vector in R^2. The interpretations as
/// vector or point are used interchangingly below.

/// Construct point with coordinates x, y. Default is 0, 0.
Point = function(x, y) {
  this.x = x || 0;
  this.y = y || 0;
}

/// Sets x and y to passed values and returns this.
Point.prototype.set = function(x, y) {
  this.x = x; this.y = y;
  return this;
}

/// Return distance to other point.
Point.prototype.dist = function(other) {
  var dx = this.x-other.x, dy = this.y-other.y;
  return Math.sqrt(dx*dx + dy*dy);
}

/// Return quadratic distance to other point.
Point.prototype.dist2 = function(other) {
  var dx = this.x-other.x, dy = this.y-other.y;
  return dx*dx + dy*dy;
}

/// Return distance to (0, 0).
Point.prototype.length = function() {
  return Math.sqrt(this.x*this.x+this.y*this.y);
}

/// Return quadratic distance to (0, 0).
Point.prototype.length2 = function() {
  return this.x*this.x+this.y*this.y;
}

/// Return new point that is the sum of this and other point.
Point.prototype.add = function(other) {
  return new Point(this.x+other.x, this.y+other.y);
}

/// Add the other point to this and return this.
Point.prototype.Add = function(other) {
  this.x += other.x; this.y += other.y;
  return this;
}

/// Return new point that is the other point subtracted from this.
Point.prototype.sub = function(other) {
  return new Point(this.x-other.x, this.y-other.y);
}

/// Subtract other point from this and return this.
Point.prototype.Sub = function(other) {
  this.x -= other.x; this.y -= other.y;
  return this;
}

/// Return the scalar product of this and the passed vector.
Point.prototype.mul = function(other) {
  return this.x*other.x+this.y*other.y;
}

/// Return last component of cross product of this and other vector.
Point.prototype.cross = function(other) {
  return this.x*other.y-this.y*other.x;
}

/// Return true if x and y components of this do not differ more than eps from other.
Point.prototype.equals = function(other, eps) {
  return (Math.abs(this.x-other.x) < eps) && (Math.abs(this.y-other.y) < eps);
}

/// Returns a new vector with same direction as this but length of 1. Not defined
/// for vector (0, 0).
Point.prototype.normalize = function() {
  var l = 1/this.length();
  return new Point(this.x*l, this.y*l);
}

/// Scales this vector to a length of 1 and returns this.
Point.prototype.Normalize = function() {
  var l = 1/this.length();
  this.x *= l; this.y *= l;
  return this;
}

/// Returns a scaled version of this vector as a new vector.
Point.prototype.scale = function(s) {
  return new Point(this.x*s, this.y*s);
}

/// Scales this vector and returns this.
Point.prototype.Scale = function(s) {
  this.x *= s; this.y *= s;
  return this;
}

/// Returns "(x, y)".
Point.prototype.toString = function() {
  return "(" + this.x + "," + this.y + ")";
}

/// Returns a copy of this point.
Point.prototype.copy = function() {
  return new Point(this.x, this.y);
}

/// To points closer than EPS are considered equal in several algorithms below.
Point.EPS = 1e-6;

/// Returns the closest point on a line segment to a given point.
Point.get_closest_point_on_segment = function(A, B, P) {
  var AB = B.sub(A), ABn = AB.normalize();
  var k = ABn.mul(P.sub(A));
  if (k<0) return A;
  if (k>AB.length()) return B;
  return A.add(ABn.scale(k));
}

/// Calculates the intersection point between a ray and a line segment.
/** The ray is passed as origin and direction vector, the line segment
 * as its two end points A and B. If an intersection is found, the method
 * writes it to the passed intersection point and returns true. If no
 * intersection is found, the method returns false.
 *
 * If there is more than one intersection point (might happen when ray and line
 * segment are parallel), the first intersection point is returned.
 *
 * In order not to miss an intersection with the ray and one of the end points
 * of AB, the method will regard very close misses (which are closer than
 * margin) as collisions, too.
 *
 * Params:
 *   R: start of ray (Point)
 *   v: direction vector of ray (Point)
 *   A, B: start and end point of line segment (Point)
 *   intersection: intersection point is written into this (Point)!!
 *   margin: if ray misses the segment by 'margin' or less, it is regarded as hit (default is Point.EPS)
 */
Point.intersect_ray_with_segment = function(R, v, A, B, intersection, margin) {
  // if there is an intersection, it is at A+l*(B-A)
  // where l = (A-R) x v / (v x (B-A))
  // with a x b ... cross product (applied to 2D) between a and b
  if (typeof(intersection) == 'undefined') var intersection = new Point();
  if (typeof(margin) == 'undefined') var margin = Point.EPS;
  // so we start with calculating the divisor
  var AB = B.sub(A);
  var divisor = v.cross(AB);
  if (Math.abs(divisor) > Point.EPS) {
    // divisor is not zero -- no parallel lines!
    // now calculate l
    var l = (A.sub(R)).cross(v) / divisor;
    // check if we have an intersection
    if (l < -margin || l-1. > margin) return false;
    var hit = A.add(AB.scale(l));
    intersection.x = hit.x; intersection.y = hit.y;
  } else {
    // devisor is zero so first check check for A!=B and v!=0
    if (v.length2() < Point.EPS || AB.length2() < Point.EPS)
      return false;
    // okay, A!=B and v!=0 so this means the lines are parallel
    // we project R onto AB to get its relative position k: R' = A + k*(B-A)
    var k = R.sub(A).mul(AB) / AB.mul(AB);
    // now first check, whether v and AB are colinear
    if (A.add(AB.scale(k)).dist(R) > Point.EPS) return false;
    // they are colinear so there might be an intersection, but it depends where
    // R is relative to AB
    if (k < -margin) { intersection.x = A.x; intersection.y = A.y}
    else if (k - 1. > margin) { intersection.x = B.x; intersection.y = B.y}
    else {intersection.x = R.x; intersection.y = R.y}
  }
  // direction check
  if (intersection.sub(R).mul(v) >= 0.) return true;
  else return false;
}

/// This line is for the automated tests with node.js
if (typeof(exports) != 'undefined') { exports.Point = Point }
<commit_msg>added rotate() and Rotate() methods to point class. Still need to write a test for it.<commit_after>/// Copyright by Erik Weitnauer, 2012.

/// The point class represents a point or vector in R^2. The interpretations as
/// vector or point are used interchangingly below.

/// Construct point with coordinates x, y. Default is 0, 0.
Point = function(x, y) {
  this.x = x || 0;
  this.y = y || 0;
}

/// Returns a new point which is this rotated about (0, 0) by angle.
Point.prototype.rotate = function(angle) {
  return new Point(this.x*Math.cos(angle) - this.y*Math.sin(angle),
                   this.y*Math.cos(angle) + this.x*Math.sin(angle));
}

/// Rotates this about (0, 0) by angle and returns this.
Point.prototype.Rotate = function(angle) {
  return this.set(this.x*Math.cos(angle) - this.y*Math.sin(angle),
                  this.y*Math.cos(angle) + this.x*Math.sin(angle));
}

/// Sets x and y to passed values and returns this.
Point.prototype.set = function(x, y) {
  this.x = x; this.y = y;
  return this;
}

/// Return distance to other point.
Point.prototype.dist = function(other) {
  var dx = this.x-other.x, dy = this.y-other.y;
  return Math.sqrt(dx*dx + dy*dy);
}

/// Return quadratic distance to other point.
Point.prototype.dist2 = function(other) {
  var dx = this.x-other.x, dy = this.y-other.y;
  return dx*dx + dy*dy;
}

/// Return distance to (0, 0).
Point.prototype.length = function() {
  return Math.sqrt(this.x*this.x+this.y*this.y);
}

/// Return quadratic distance to (0, 0).
Point.prototype.length2 = function() {
  return this.x*this.x+this.y*this.y;
}

/// Return new point that is the sum of this and other point.
Point.prototype.add = function(other) {
  return new Point(this.x+other.x, this.y+other.y);
}

/// Add the other point to this and return this.
Point.prototype.Add = function(other) {
  this.x += other.x; this.y += other.y;
  return this;
}

/// Return new point that is the other point subtracted from this.
Point.prototype.sub = function(other) {
  return new Point(this.x-other.x, this.y-other.y);
}

/// Subtract other point from this and return this.
Point.prototype.Sub = function(other) {
  this.x -= other.x; this.y -= other.y;
  return this;
}

/// Return the scalar product of this and the passed vector.
Point.prototype.mul = function(other) {
  return this.x*other.x+this.y*other.y;
}

/// Return last component of cross product of this and other vector.
Point.prototype.cross = function(other) {
  return this.x*other.y-this.y*other.x;
}

/// Return true if x and y components of this do not differ more than eps from other.
Point.prototype.equals = function(other, eps) {
  return (Math.abs(this.x-other.x) < eps) && (Math.abs(this.y-other.y) < eps);
}

/// Returns a new vector with same direction as this but length of 1. Not defined
/// for vector (0, 0).
Point.prototype.normalize = function() {
  var l = 1/this.length();
  return new Point(this.x*l, this.y*l);
}

/// Scales this vector to a length of 1 and returns this.
Point.prototype.Normalize = function() {
  var l = 1/this.length();
  this.x *= l; this.y *= l;
  return this;
}

/// Returns a scaled version of this vector as a new vector.
Point.prototype.scale = function(s) {
  return new Point(this.x*s, this.y*s);
}

/// Scales this vector and returns this.
Point.prototype.Scale = function(s) {
  this.x *= s; this.y *= s;
  return this;
}

/// Returns "(x, y)".
Point.prototype.toString = function() {
  return "(" + this.x + "," + this.y + ")";
}

/// Returns a copy of this point.
Point.prototype.copy = function() {
  return new Point(this.x, this.y);
}

/// To points closer than EPS are considered equal in several algorithms below.
Point.EPS = 1e-6;

/// Returns the closest point on a line segment to a given point.
Point.get_closest_point_on_segment = function(A, B, P) {
  var AB = B.sub(A), ABn = AB.normalize();
  var k = ABn.mul(P.sub(A));
  if (k<0) return A;
  if (k>AB.length()) return B;
  return A.add(ABn.scale(k));
}

/// Calculates the intersection point between a ray and a line segment.
/** The ray is passed as origin and direction vector, the line segment
 * as its two end points A and B. If an intersection is found, the method
 * writes it to the passed intersection point and returns true. If no
 * intersection is found, the method returns false.
 *
 * If there is more than one intersection point (might happen when ray and line
 * segment are parallel), the first intersection point is returned.
 *
 * In order not to miss an intersection with the ray and one of the end points
 * of AB, the method will regard very close misses (which are closer than
 * margin) as collisions, too.
 *
 * Params:
 *   R: start of ray (Point)
 *   v: direction vector of ray (Point)
 *   A, B: start and end point of line segment (Point)
 *   intersection: intersection point is written into this (Point)!!
 *   margin: if ray misses the segment by 'margin' or less, it is regarded as hit (default is Point.EPS)
 */
Point.intersect_ray_with_segment = function(R, v, A, B, intersection, margin) {
  // if there is an intersection, it is at A+l*(B-A)
  // where l = (A-R) x v / (v x (B-A))
  // with a x b ... cross product (applied to 2D) between a and b
  if (typeof(intersection) == 'undefined') var intersection = new Point();
  if (typeof(margin) == 'undefined') var margin = Point.EPS;
  // so we start with calculating the divisor
  var AB = B.sub(A);
  var divisor = v.cross(AB);
  if (Math.abs(divisor) > Point.EPS) {
    // divisor is not zero -- no parallel lines!
    // now calculate l
    var l = (A.sub(R)).cross(v) / divisor;
    // check if we have an intersection
    if (l < -margin || l-1. > margin) return false;
    var hit = A.add(AB.scale(l));
    intersection.x = hit.x; intersection.y = hit.y;
  } else {
    // devisor is zero so first check check for A!=B and v!=0
    if (v.length2() < Point.EPS || AB.length2() < Point.EPS)
      return false;
    // okay, A!=B and v!=0 so this means the lines are parallel
    // we project R onto AB to get its relative position k: R' = A + k*(B-A)
    var k = R.sub(A).mul(AB) / AB.mul(AB);
    // now first check, whether v and AB are colinear
    if (A.add(AB.scale(k)).dist(R) > Point.EPS) return false;
    // they are colinear so there might be an intersection, but it depends where
    // R is relative to AB
    if (k < -margin) { intersection.x = A.x; intersection.y = A.y}
    else if (k - 1. > margin) { intersection.x = B.x; intersection.y = B.y}
    else {intersection.x = R.x; intersection.y = R.y}
  }
  // direction check
  if (intersection.sub(R).mul(v) >= 0.) return true;
  else return false;
}

/// This line is for the automated tests with node.js
if (typeof(exports) != 'undefined') { exports.Point = Point }
<|endoftext|>


<commit_before>function getCurrentTabUrl(callback) {
  var queryInfo = {
    active: true,
    currentWindow: true
  };
  chrome.tabs.query(queryInfo, function(tabs) {
    var tab = tabs[0];
    var url = tab.url;
    callback(url);
  });
}

$(document).ready(function () {
  $("#navBtn").hide();
  getCurrentTabUrl(function (url) {
    var tempIndex = url.indexOf("/wiki/");
    if (tempIndex < 0){
      $("#msgText").text("Not a valid wiki page.");
      $("#portBtn").hide();
      $("#loadingImg").hide();
      return;
    }
    $("#msgText").text();
    $("#portBtn").show();
    $("#portBtn").text("Port to " + TARGET_WIKI_URL);
    $("#loadingImg").hide();

    $("#portBtn").click(function () {
      $("#loadingImg").show();
      $("#portBtn").hide();

      var title = url.substring(tempIndex + 6);
      $("#navBtn").click(function () {
        chrome.tabs.create({ url: TARGET_WIKI_URL + "/wiki/" + title});
      })
      var requestUrl = url.replace("/wiki/", "/api.php?action=query&prop=revisions&rvprop=content&format=json&titles=");
      $.ajax({
        url: requestUrl
      }).done(function (params) {
        var pagesNode = params.query.pages;
        var pageNode = getFirstChildInObject(pagesNode);
        var wikitext = getFirstChildInObject(pageNode.revisions[0]);
        console.log(wikitext);
        $.ajax({
          url: TARGET_WIKI_API_URL + "?action=query&meta=tokens&format=json",
        }).done(function(tokensParam){
          console.log(tokensParam);
          var token = tokensParam.query.tokens.csrftoken;
          console.log(token);
          var editRequestUrl = TARGET_WIKI_API_URL + "?action=edit&format=json&createonly&summary=port&title=" + title;
          var postWikitext = getWikiTextPrefix(url) + wikitext;
          var postBody = {
            "token" : token,
            "text" : postWikitext
          };
          console.log(editRequestUrl);
          $.ajax({
            url: editRequestUrl,
            type: "POST",
            data: postBody,
          }).done(function (params2){
            $("#msgText").text("Done!");
            $("#targetLink").text("See it");
            $("#msgText").show();
            $("#navBtn").show();
            $("#loadingImg").hide();
          }).error(function( jqXHR, textStatus, errorThrown){
            console.log(jqXHR);
            console.log(textStatus);
            console.log(errorThrown);
            $("#msgText").text("error, see log.");
            $("#msgText").show();
            $("#loadingImg").hide();
          });
        });
      });
    });
  });
});<commit_msg>vs code settings<commit_after>/// <reference path="typings/jquery/jquery.d.ts"/>
function getCurrentTabUrl(callback) {
  var queryInfo = {
    active: true,
    currentWindow: true
  };
  chrome.tabs.query(queryInfo, function(tabs) {
    var tab = tabs[0];
    var url = tab.url;
    callback(url);
  });
}

$(document).ready(function () {
  $("#navBtn").hide();
  getCurrentTabUrl(function (url) {
    var tempIndex = url.indexOf("/wiki/");
    if (tempIndex < 0){
      $("#msgText").text("Not a valid wiki page.");
      $("#portBtn").hide();
      $("#loadingImg").hide();
      return;
    }
    $("#msgText").text();
    $("#portBtn").show();
    $("#portBtn").text("Port to " + TARGET_WIKI_URL);
    $("#loadingImg").hide();

    $("#portBtn").click(function () {
      $("#loadingImg").show();
      $("#portBtn").hide();

      var title = url.substring(tempIndex + 6);
      $("#navBtn").click(function () {
        chrome.tabs.create({ url: TARGET_WIKI_URL + "/wiki/" + title});
      })
      var requestUrl = url.replace("/wiki/", "/api.php?action=query&prop=revisions&rvprop=content&format=json&titles=");
      $.ajax({
        url: requestUrl
      }).done(function (params) {
        var pagesNode = params.query.pages;
        var pageNode = getFirstChildInObject(pagesNode);
        var wikitext = getFirstChildInObject(pageNode.revisions[0]);
        console.log(wikitext);
        $.ajax({
          url: TARGET_WIKI_API_URL + "?action=query&meta=tokens&format=json",
        }).done(function(tokensParam){
          console.log(tokensParam);
          var token = tokensParam.query.tokens.csrftoken;
          console.log(token);
          var editRequestUrl = TARGET_WIKI_API_URL + "?action=edit&format=json&createonly&summary=port&title=" + title;
          var postWikitext = getWikiTextPrefix(url) + wikitext;
          var postBody = {
            "token" : token,
            "text" : postWikitext
          };
          console.log(editRequestUrl);
          $.ajax({
            url: editRequestUrl,
            type: "POST",
            data: postBody,
          }).done(function (params2){
            $("#msgText").text("Done!");
            $("#targetLink").text("See it");
            $("#msgText").show();
            $("#navBtn").show();
            $("#loadingImg").hide();
          }).error(function( jqXHR, textStatus, errorThrown){
            console.log(jqXHR);
            console.log(textStatus);
            console.log(errorThrown);
            $("#msgText").text("error, see log.");
            $("#msgText").show();
            $("#loadingImg").hide();
          });
        });
      });
    });
  });
});<|endoftext|>


<commit_before>var groups = [];

var defaultGroup = {
  name:"Default Group",
  tabs:[],
  open:false,
  active:true
}

var refreshUI = function(){
  for(var i = 0;i<groups.length;i++){
      $(".container").append("

"+groups[i].name+"

");

      $(".group"+i).click({groupnum:i},function(event){
	var i = event.data.groupnum;
	if(groups[i].open===false){
 	  groups[i].open=true;
	  for(var j = 0;j<groups[i].tabs.length;j++){
	    $(".group"+i).append("

"+groups[i].tabs[j].title+"

");
	  }
	}
	else{
	  groups[i].open=false;
	  $(".tab"+i).remove();
	}
      });

    }
};

$(document).ready(function(){
  chrome.tabs.query({currentWindow:true},function(tabarray){
    defaultGroup.tabs = tabarray;
    groups.push(defaultGroup);
    refreshUI();
  });
});

// IMPORTANT:  this could be totally wrong.
// I have no idea how to test.  Plz help.
//
// Intended to move tab from one group to another
// If the source or dest group is open, modifies tab state
// Does nothing with the UI at this time
function moveTab(tabID, destGroupID){
  var destGroup, sourceGroup, tab;
  for(var i = 0; i<groups.length;i++){
    if(groups[i].id===destGroupID){
      destGroup = groups[i];
    }
    for(var j = 0; j<groups[i].tabs.length;j++){
      if(groups[i].tabs[j].id===tabID){
        tab = groups[i].tabs[j];
        sourceGroup = groups[i];
        sourceGroup.tabs.splice(j,1);
        break;
      }
    }
    destGroup.tabs.push(tab);
    if(sourceGroup.active){
      chrome.tabs.remove(tabID);
    }
    if(destGroup.active){
      chrome.tabs.create({url:tab.url,selected:false});
    }
  }
}

//Used for switching in between groups
//Check me on this
//Can be used to switch in between groups using a keyboard shortcut
function switchGroup(groupID) {
  var destGroup;
  for (var i = 0; i < groups.length; i++) {
    if  (groups[i] == groupID) {
	destGroup = groups[i];
    }
    if (groups[i].active) {
        groups[i].active = false;
        var tabs = groups[i].tabs;
        //Removes Tabs
	for (var j = 0; j < tabs.length; j++){
	    chrome.tabs.remove(tabs[j].id);
	}
    }
  }
  destGroup.active = true
  //Creates tabs and selects the first tab
  for (var k = 0; k < destGroups.tabs.length; k++) {
      if (k = 0) chrome.tabs.create({url:destGroups.tabs[k].url,selected:true})
      else chrome.tabs.create({url:destGroups.tabs[k].url,selected:false})
  }
}

//Um. I probably have to fix everything here.
//Used for creating a group
function createGroup(groupName){
  var newGroup = {
  name: groupName,
  tabs:[],
  open:false,
  active:true
  }
  groups.push(newGroup);
}

//Used for deleting a group
function deleteGroup(groupID){
  for (var i = array.length - 1; i>=0; i--){
    if (groups[i] === groupID){
    	array.splice(i,1);
    }
  }
}

//Used for naming a group
function nameGroup(groupID){
  for (var i = array.length - 1; i--){
    if (groups[i] === groupID){
      groups[id].name=label;
    }
  }
}
<commit_msg>Added boilerplate storage, minor bugfix<commit_after>var groups = [];

var defaultGroup = {
  name:"Default Group",
  tabs:[],
  open:false,
  active:true
}

var refreshUI = function(){
  for(var i = 0;i<groups.length;i++){
      $(".container").append("

"+groups[i].name+"

");

      $(".group"+i).click({groupnum:i},function(event){
	var i = event.data.groupnum;
	if(groups[i].open===false){
 	  groups[i].open=true;
	  for(var j = 0;j<groups[i].tabs.length;j++){
	    $(".group"+i).append("

"+groups[i].tabs[j].title+"

");
	  }
	}
	else{
	  groups[i].open=false;
	  $(".tab"+i).remove();
	}
      });

    }
};

$(document).ready(function(){
  chrome.tabs.query({currentWindow:true},function(tabarray){
    getGroups();
    defaultGroup.tabs = tabarray;
    groups.push(defaultGroup);
    refreshUI();
  });
});

function storeGroups(){
  chrome.storage.local.set({'groups': groups});
}

function getGroups(){
  chrome.storage.local.get('groups',function(items){
    if(items.groups){
      groups = items.groups;
    } else {
      groups = [];
    }
  });
}

// IMPORTANT:  this could be totally wrong.
// I have no idea how to test.  Plz help.
//
// Intended to move tab from one group to another
// If the source or dest group is open, modifies tab state
// Does nothing with the UI at this time
function moveTab(tabID, destGroupID){
  var destGroup, sourceGroup, tab;
  for(var i = 0; i<groups.length;i++){
    if(groups[i].id===destGroupID){
      destGroup = groups[i];
    }
    for(var j = 0; j<groups[i].tabs.length;j++){
      if(groups[i].tabs[j].id===tabID){
        tab = groups[i].tabs[j];
        sourceGroup = groups[i];
        sourceGroup.tabs.splice(j,1);
        break;
      }
    }
    storeGroups();
    destGroup.tabs.push(tab);
    if(sourceGroup.active){
      chrome.tabs.remove(tabID);
    }
    if(destGroup.active){
      chrome.tabs.create({url:tab.url,selected:false});
    }
  }
}

//Used for switching in between groups
//Check me on this
//Can be used to switch in between groups using a keyboard shortcut
function switchGroup(groupID) {
  var destGroup;
  for (var i = 0; i < groups.length; i++) {
    if  (groups[i] == groupID) {
	destGroup = groups[i];
    }
    if (groups[i].active) {
        groups[i].active = false;
        var tabs = groups[i].tabs;
        //Removes Tabs
	for (var j = 0; j < tabs.length; j++){
	    chrome.tabs.remove(tabs[j].id);
	}
    }
  }
  destGroup.active = true
  //Creates tabs and selects the first tab
  for (var k = 0; k < destGroups.tabs.length; k++) {
      if (k = 0) chrome.tabs.create({url:destGroups.tabs[k].url,selected:true})
      else chrome.tabs.create({url:destGroups.tabs[k].url,selected:false})
  }
}

//Um. I probably have to fix everything here.
//Used for creating a group
function createGroup(groupName){
  var newGroup = {
  name: groupName,
  tabs:[],
  open:false,
  active:true
  }
  groups.push(newGroup);
}

//Used for deleting a group
function deleteGroup(groupID){
  for (var i = array.length - 1; i>=0; i--){
    if (groups[i] === groupID){
    	array.splice(i,1);
    }
  }
}

//Used for naming a group
function nameGroup(groupID){
  for (var i = array.length - 1; i>=0; i--){
    if (groups[i] === groupID){
      groups[id].name=label;
    }
  }
}
<|endoftext|>


<commit_before>/*
** Sonnarr Extention
** Shows upcoming and missed episodes.
*/

var sonarr = {
  settings: {
    wanted : "api/wanted/missing?page=1&pageSize={wantedItems}&sortKey=airDateUtc&sortDir=desc&apikey={apikey}",
    history : "api/history?page=1&pageSize={historyItems}&sortKey=date&sortDir=desc&apikey={apikey}"
  },
  getData : function (mode, callback) {
    var url = "";
    url = app.settings.url + sonarr.settings[mode];

    url = url.replace("{wantedItems}", app.settings.wantedItems);
	url = url.replace("{historyItems}", app.settings.historyItems);
    url = url.replace("{apikey}", app.settings.apiKey);

    $.getJSON( url , function( data ) {
      if (callback && typeof(callback) === "function")
      {
        callback(data);
        //store data
        if(mode === "wanted"){
          localStorage.setItem("wanted", JSON.stringify(data));
        }
        if(mode === "history"){
          localStorage.setItem("history", JSON.stringify(data));
        }
      }
    });
  }
}

var getupcomingEpisodes = {
  connect: function(){

  },
  generate: function(){

  }
}

var getHistory = {
  connect: function(){
    if(localStorage.getItem("history") !== 'undefined'){
      var historyData = $.parseJSON(localStorage.getItem("history"));
      getHistory.generate(historyData);
    }
    sonarr.getData("history", getHistory.generate);
  },
  generate: function(data){
    data = data.records;
    app.cleanList();
    $.each(data, function (index, value) {
      getHistory.add(value);
    });
  },
  add : function (episode) {
    var template = $('.templates #history');
    var event = {
      "downloadFolderImported" : 'Imported',
      "grabbed" : 'grabbed',
      "episodeFileDeleted" : 'deleted file',
    }
    template.find('#title').html(episode.series.title);
    template.find('#episodeNum').html(episode.episode.seasonNumber + "x"  + episode.episode.episodeNumber);

    template.find('#event').html(event[episode.eventType]);

    template.attr("data-episodeId", episode.episode.id);
    template.clone().appendTo( ".list" );
  }
}

var getWantedEpisodes = {
  connect: function(){
    if(localStorage.getItem("wanted") !== 'undefined'){
      var wantedData = $.parseJSON(localStorage.getItem('wanted'));
      getWantedEpisodes.generate(wantedData);
    }
    sonarr.getData("wanted", getWantedEpisodes.generate);
  },
  generate: function(data){
    var totalRecords = data.totalRecords;
    data = data.records;
    app.cleanList();
    $.each(data, function (index, value) {
      getWantedEpisodes.add(value);
    });
    //set num items in button
    $('.menu .wanted .num').html(totalRecords.toString());
    getWantedEpisodes.click();
  },
  add : function(episode){
    var template = $('.templates #wanted');
    var date = {
      day : episode.airDate.substring(8, 10),
      month : episode.airDate.substring(5, 7)
    }
    var month = {
      '01': 'jan',
      '02': 'feb',
      '03': 'mar',
      '04': 'apr',
      '05': 'may',
      '06': 'jun',
      '07': 'jul',
      '08': 'aug',
      '09': 'sep',
      '10': 'okt',
      '11': 'nov',
      '12': 'dec',
    }
    template.find('#title').html(episode.series.title);
    template.find('#episodeName').html(episode.title);
    template.find('#episodeNum').html("download
" + episode.seasonNumber + "x"  + episode.episodeNumber );

    template.attr("data-episodeId", episode.id);

    template.find('#day').html(date.day);
    template.find('#month').html(month[date.month]);
    template.clone().appendTo( ".list" );
  },
  searchEpisode : function (episodeId) {
    if(episodeId < 1){
      return false;
    }
    var url = app.settings.url + "api/Command?apikey=" + app.settings.apiKey;
    console.log(url);
    $.ajax({
      type: "get",
      url: url,
      data: {
        name: "episodesearch",
        episodeIds: episodeId
      }
    });
  },
  click : function() {
    $( ".wanted .button" ).click(function() {
      var episodeId = $(this).parentsUntil('.wanted').attr("data-episodeId");
      $(this).parentsUntil('.wanted').animate({'opacity': '0.5'});
      getWantedEpisodes.searchEpisode(episodeId);
    });
  }
}

//set variable from chrome storage option fields
// stored in chrome.storage.
function getOptions() {
  chrome.storage.sync.get({
    apiKey: app.settings.apiKey,
    url: app.settings.url,
    historyItems: app.settings.historyItems,
  }, function(items){
    app.settings.apiKey = items.apiKey;
    app.settings.url = items.url;
    app.settings.mode = "wanted";
    app.settings.historyItems = items.historyItems;
    app.run();
    console.log('get options from chrome storage');
  });
}

var menu =  {
  bind : function (){
    $('.menu .item').unbind( "click" ).click(function(){
      var mode = $(this).attr('data-mode');
      if(app.settings.mode !== mode){
        //change active item
        $('.menu .item').removeClass('active');
        $(this).addClass('active');
        //change mode
        app.settings.mode = mode;
        console.log(mode);
        //rerun app
        app.run();
      }
    });
  }
}

function setLocalStorage () {
  if (localStorage.getItem('wanted') === null) {
    localStorage.setItem('wanted', undefined);
  }
  if (localStorage.getItem('history') === null) {
    localStorage.setItem('history', undefined);
  }
}

var app = {
  settings : {
    apiKey : '',
    url: '',
    mode : 'getOptions',
    historyItems: 15
  },
  run : function(){
    //prepare local storage
    setLocalStorage();

    if(app.settings.mode == 'getOptions' || app.settings.apiKey === '' || app.settings.url === '')
    {
      getOptions();
      return false;
    }
    if (app.settings.mode === "upcoming")
    {
      getupcomingEpisodes.connect();
    }
    else if (app.settings.mode === "wanted")
    {
      getWantedEpisodes.connect();
    }
    else if (app.settings.mode === "history")
    {
      getHistory.connect();
    }
    //bind actions to the menu
    menu.bind();
  },
  cleanList : function() {
    //clean list
    $( ".list > div" ).remove();
  }
}
app.run();<commit_msg>add missing variable<commit_after>/*
** Sonnarr Extention
** Shows upcoming and missed episodes.
*/

var sonarr = {
  settings: {
    wanted : "api/wanted/missing?page=1&pageSize={wantedItems}&sortKey=airDateUtc&sortDir=desc&apikey={apikey}",
    history : "api/history?page=1&pageSize={historyItems}&sortKey=date&sortDir=desc&apikey={apikey}"
  },
  getData : function (mode, callback) {
    var url = "";
    url = app.settings.url + sonarr.settings[mode];

    url = url.replace("{wantedItems}", app.settings.wantedItems);
	url = url.replace("{historyItems}", app.settings.historyItems);
    url = url.replace("{apikey}", app.settings.apiKey);

    $.getJSON( url , function( data ) {
      if (callback && typeof(callback) === "function")
      {
        callback(data);
        //store data
        if(mode === "wanted"){
          localStorage.setItem("wanted", JSON.stringify(data));
        }
        if(mode === "history"){
          localStorage.setItem("history", JSON.stringify(data));
        }
      }
    });
  }
}

var getupcomingEpisodes = {
  connect: function(){

  },
  generate: function(){

  }
}

var getHistory = {
  connect: function(){
    if(localStorage.getItem("history") !== 'undefined'){
      var historyData = $.parseJSON(localStorage.getItem("history"));
      getHistory.generate(historyData);
    }
    sonarr.getData("history", getHistory.generate);
  },
  generate: function(data){
    data = data.records;
    app.cleanList();
    $.each(data, function (index, value) {
      getHistory.add(value);
    });
  },
  add : function (episode) {
    var template = $('.templates #history');
    var event = {
      "downloadFolderImported" : 'Imported',
      "grabbed" : 'grabbed',
      "episodeFileDeleted" : 'deleted file',
    }
    template.find('#title').html(episode.series.title);
    template.find('#episodeNum').html(episode.episode.seasonNumber + "x"  + episode.episode.episodeNumber);

    template.find('#event').html(event[episode.eventType]);

    template.attr("data-episodeId", episode.episode.id);
    template.clone().appendTo( ".list" );
  }
}

var getWantedEpisodes = {
  connect: function(){
    if(localStorage.getItem("wanted") !== 'undefined'){
      var wantedData = $.parseJSON(localStorage.getItem('wanted'));
      getWantedEpisodes.generate(wantedData);
    }
    sonarr.getData("wanted", getWantedEpisodes.generate);
  },
  generate: function(data){
    var totalRecords = data.totalRecords;
    data = data.records;
    app.cleanList();
    $.each(data, function (index, value) {
      getWantedEpisodes.add(value);
    });
    //set num items in button
    $('.menu .wanted .num').html(totalRecords.toString());
    getWantedEpisodes.click();
  },
  add : function(episode){
    var template = $('.templates #wanted');
    var date = {
      day : episode.airDate.substring(8, 10),
      month : episode.airDate.substring(5, 7)
    }
    var month = {
      '01': 'jan',
      '02': 'feb',
      '03': 'mar',
      '04': 'apr',
      '05': 'may',
      '06': 'jun',
      '07': 'jul',
      '08': 'aug',
      '09': 'sep',
      '10': 'okt',
      '11': 'nov',
      '12': 'dec',
    }
    template.find('#title').html(episode.series.title);
    template.find('#episodeName').html(episode.title);
    template.find('#episodeNum').html("download
" + episode.seasonNumber + "x"  + episode.episodeNumber );

    template.attr("data-episodeId", episode.id);

    template.find('#day').html(date.day);
    template.find('#month').html(month[date.month]);
    template.clone().appendTo( ".list" );
  },
  searchEpisode : function (episodeId) {
    if(episodeId < 1){
      return false;
    }
    var url = app.settings.url + "api/Command?apikey=" + app.settings.apiKey;
    console.log(url);
    $.ajax({
      type: "get",
      url: url,
      data: {
        name: "episodesearch",
        episodeIds: episodeId
      }
    });
  },
  click : function() {
    $( ".wanted .button" ).click(function() {
      var episodeId = $(this).parentsUntil('.wanted').attr("data-episodeId");
      $(this).parentsUntil('.wanted').animate({'opacity': '0.5'});
      getWantedEpisodes.searchEpisode(episodeId);
    });
  }
}

//set variable from chrome storage option fields
// stored in chrome.storage.
function getOptions() {
  chrome.storage.sync.get({
    apiKey: app.settings.apiKey,
    url: app.settings.url,
	wantedItems : app.settings.wantedItems
    historyItems: app.settings.historyItems,
  }, function(items){
    app.settings.apiKey = items.apiKey;
    app.settings.url = items.url;
    app.settings.mode = "wanted";
	app.settings.wantedItems = "historyItems";
    app.settings.historyItems = items.historyItems;
    app.run();
    console.log('get options from chrome storage');
  });
}

var menu =  {
  bind : function (){
    $('.menu .item').unbind( "click" ).click(function(){
      var mode = $(this).attr('data-mode');
      if(app.settings.mode !== mode){
        //change active item
        $('.menu .item').removeClass('active');
        $(this).addClass('active');
        //change mode
        app.settings.mode = mode;
        console.log(mode);
        //rerun app
        app.run();
      }
    });
  }
}

function setLocalStorage () {
  if (localStorage.getItem('wanted') === null) {
    localStorage.setItem('wanted', undefined);
  }
  if (localStorage.getItem('history') === null) {
    localStorage.setItem('history', undefined);
  }
}

var app = {
  settings : {
    apiKey : '',
    url: '',
    mode : 'getOptions',
    historyItems: 15
  },
  run : function(){
    //prepare local storage
    setLocalStorage();

    if(app.settings.mode == 'getOptions' || app.settings.apiKey === '' || app.settings.url === '')
    {
      getOptions();
      return false;
    }
    if (app.settings.mode === "upcoming")
    {
      getupcomingEpisodes.connect();
    }
    else if (app.settings.mode === "wanted")
    {
      getWantedEpisodes.connect();
    }
    else if (app.settings.mode === "history")
    {
      getHistory.connect();
    }
    //bind actions to the menu
    menu.bind();
  },
  cleanList : function() {
    //clean list
    $( ".list > div" ).remove();
  }
}
app.run();<|endoftext|>


<commit_before>pref("javascript.options.showInConsole", true);
pref("toolkit.defaultChromeURI", "chrome://zotero/content/standalone.xul");<commit_msg>disable link prefetching in Z standalone<commit_after>pref("javascript.options.showInConsole", true);
pref("toolkit.defaultChromeURI", "chrome://zotero/content/standalone.xul");
pref("network.prefetch-next", false);<|endoftext|>


<commit_before>"use strict";

import http from 'http';
import { Router } from 'express';
import list from './list';
import post from './post';
import put from './put';
import del from './delete';
import patch from './patch';
import get from './get';

const getRouter = (mongooseModel, { url, hooks, actions, options }) => {
  let resourceListURL = `/${url}`;
  let resourceURL = `${resourceListURL}\\(:id\\)`;

  let routes = [
    {
      method: 'post',
      url: resourceListURL,
      ctrl: post,
      hook: hooks.post,
    },
    {
      method: 'put',
      url: resourceURL,
      ctrl: put,
      hook: hooks.put,
    },
    {
      method: 'patch',
      url: resourceURL,
      controller: patch,
      config: hooks.patch,
    },
    {
      method: 'delete',
      url: resourceURL,
      ctrl: del,
      hook: hooks.delete,
    },
    {
      method: 'get',
      url: resourceURL,
      ctrl: get,
      hook: hooks.get,
    },
    {
      method: 'get',
      url: resourceListURL,
      ctrl: list,
      hook: hooks.list,
    },
  ];

  let router = Router();

  // add REST routes.
  routes.map((route) => {
    let { method, url, ctrl, hook } = route;
    router[method](url, (req, res, next) => {
      authorizePipe(req, res, hook.auth)
      .then(function() { return beforePipe(req, res, hook.before); })
      .then(function() { return ctrl(req, mongooseModel, options); })
      .then(function(result) { return respondPipe(req, res, result); })
      .then(function(data) { return afterPipe(req, res, hook.after, data); })
      .catch(function(result) { errorPipe(req, res, result); });
    });
  });

  // add ACTION routes.
  Object.keys(actions).map(function(url) {
    let action = actions[url];
    router.post(`${resourceURL}${url}`, (req, res, next) => {
      authorizePipe(req, res, action.auth).then(function() {
        action(req, res, next);
      }).catch(function(result) { errorPipe(req, res, result); });
    });
  });

  return router;
};

function authorizePipe(req, res, auth) {
  return new Promise((resolve, reject) => {
    if (auth !== undefined) {
      if (!auth(req, res)) {
        return reject({ status: 401 });
      }
    }
    resolve();
  });
}

function beforePipe(req, res, before) {
  return new Promise((resolve, reject) => {
    if (before) {
      before(req.body, req, res);
    }
    resolve();
  });
}

function respondPipe(req, res, result) {
  return new Promise((resolve, reject) => {
    let status = result.status || 200;
    let data = result.entity;
    res.status(status).jsonp(data);
    resolve(data);
  });
}

function afterPipe(req, res, after, data) {
  return new Promise((resolve, reject) => {
    if (after) {
      after(data, req.body, req, res);
    }
    resolve();
  });
}

function errorPipe(req, res, result) {
  return new Promise((resolve, reject) => {
    let status = result.status || 200;
    let text = result.text || http.STATUS_CODES[status];
    res.status(status).send(text);
  });
}

export default { getRouter };
<commit_msg>fixed #45, http state code not be correct when mongodb throw a internal error.<commit_after>"use strict";

import http from 'http';
import { Router } from 'express';
import list from './list';
import post from './post';
import put from './put';
import del from './delete';
import patch from './patch';
import get from './get';

const getRouter = (mongooseModel, { url, hooks, actions, options }) => {
  let resourceListURL = `/${url}`;
  let resourceURL = `${resourceListURL}\\(:id\\)`;

  let routes = [
    {
      method: 'post',
      url: resourceListURL,
      ctrl: post,
      hook: hooks.post,
    },
    {
      method: 'put',
      url: resourceURL,
      ctrl: put,
      hook: hooks.put,
    },
    {
      method: 'patch',
      url: resourceURL,
      controller: patch,
      config: hooks.patch,
    },
    {
      method: 'delete',
      url: resourceURL,
      ctrl: del,
      hook: hooks.delete,
    },
    {
      method: 'get',
      url: resourceURL,
      ctrl: get,
      hook: hooks.get,
    },
    {
      method: 'get',
      url: resourceListURL,
      ctrl: list,
      hook: hooks.list,
    },
  ];

  let router = Router();

  // add REST routes.
  routes.map((route) => {
    let { method, url, ctrl, hook } = route;
    router[method](url, (req, res, next) => {
      authorizePipe(req, res, hook.auth)
      .then(function() { return beforePipe(req, res, hook.before); })
      .then(function() { return ctrl(req, mongooseModel, options); })
      .then(function(result) { return respondPipe(req, res, result); })
      .then(function(data) { return afterPipe(req, res, hook.after, data); })
      .catch(function(err) { errorPipe(req, res, err); });
    });
  });

  // add ACTION routes.
  Object.keys(actions).map(function(url) {
    let action = actions[url];
    router.post(`${resourceURL}${url}`, (req, res, next) => {
      authorizePipe(req, res, action.auth).then(function() {
        action(req, res, next);
      }).catch(function(result) { errorPipe(req, res, result); });
    });
  });

  return router;
};

function authorizePipe(req, res, auth) {
  return new Promise((resolve, reject) => {
    if (auth !== undefined) {
      if (!auth(req, res)) {
        return reject({ status: 401 });
      }
    }
    resolve();
  });
}

function beforePipe(req, res, before) {
  return new Promise((resolve, reject) => {
    if (before) {
      before(req.body, req, res);
    }
    resolve();
  });
}

function respondPipe(req, res, result) {
  return new Promise((resolve, reject) => {
    let status = result.status || 200;
    let data = result.entity;
    res.status(status).jsonp(data);
    resolve(data);
  });
}

function afterPipe(req, res, after, data) {
  return new Promise((resolve, reject) => {
    if (after) {
      after(data, req.body, req, res);
    }
    resolve();
  });
}

function errorPipe(req, res, err) {
  return new Promise((resolve, reject) => {
    let status = err.status || 500;
    let text = err.text || err.message || http.STATUS_CODES[status];
    res.status(status).send(text);
  });
}

export default { getRouter };
<|endoftext|>


<commit_before>import firebase from 'firebase'

import {
  GET_LIST,
  GET_ONE,
  GET_MANY,
  GET_MANY_REFERENCE,
  CREATE,
  UPDATE,
  DELETE
} from 'admin-on-rest'

/**
 * @param {string[]|Object[]} trackedResources Array of resource names or array of Objects containing name and
 * optional path properties (path defaults to name)
 * @param {Object} firebaseConfig Optiona Firebase configuration
 */

const timestampFieldNames = {
  createdAt: 'created_at',
  updatedAt: 'updated_at'
}

export const methodUpload = async (fieldName, submitedData, id, resourceName, resourcePath) => {
  const file = submitedData[fieldName] ? submitedData[fieldName][0].rawFile : {}
  const result = {}
  if (file && file.name) {
    const ref = firebase.storage().ref().child(`${resourcePath}/${id}/${fieldName}`)
    const snapshot = await ref.put(file)
    result[fieldName] = [{}]
    result[fieldName][0].uploadedAt = Date.now()
    result[fieldName][0].src = snapshot.downloadURL.split('?').shift() + '?alt=media'
    return result
  }
  return false
}

export const methodSave = async (id, newData, currentData, resourceName, resourcePath, resolve, reject, uploadResults) => {
  try {
    if (uploadResults) {
      uploadResults.map(result => result ? Object.assign(newData, result) : false)
    }
    newData = Object.assign({ [timestampFieldNames.updatedAt]: Date.now() },
      currentData,
      newData)
    await firebase.database().ref(resourcePath + '/' + id).update(newData)
    resolve({ data: newData })
    return newData
  } catch (e) {
    reject(e)
  }
  return false
}

export const methodDelete = async (id, resourceName, resourcePath, resolve, reject) => {
  try {
    await firebase.database().ref(resourcePath + '/' + id).remove()
    resolve({ data: id })
    return { data: id }
  } catch (e) {
    reject(e)
  }
  return false
}

export const methodGetItemID = (params, type, resourceName, resourcePath, resourceData, resolve, reject) => {
  let itemId = params.data.id || params.id
  if (!itemId) {
    itemId = firebase.database().ref().child(resourcePath).push().key
  }
  if (!itemId) {
    reject(new Error('ID is required'))
    return 0
  }
  if (resourceData && resourceData[itemId] && type === CREATE) {
    reject(new Error('ID already in use'))
    return
  }
  return itemId
}

export default (trackedResources = [], firebaseConfig = {}, options = {}) => {
  Object.assign(timestampFieldNames, options.timestampFieldNames)

  /** TODO Move this to the Redux Store */
  const resourcesStatus = {}
  const resourcesReferences = {}
  const resourcesData = {}
  const resourcesPaths = {}
  const resourcesUploadFields = {}

  if (firebase.apps.length === 0) {
    firebase.initializeApp(firebaseConfig)
  }

  /* Functions */
  const upload = options.methodUpload || methodUpload
  const save = options.methodSave || methodSave
  const del = options.methodUpload || methodUpload
  const getItemID = options.getItemID || methodGetItemID

  trackedResources.map(resource => {
    if (typeof resource === 'object') {
      if (!resource.name) {
        throw new Error(`name is missing from resource ${resource}`)
      }

      const name = resource.name
      const path = resource.path || resource.name
      const uploadFields = resource.uploadFields || []

      // Check path ends with name so the initial children can be loaded from on 'value' below.
      const pattern = path.indexOf('/') >= 0 ? `/${name}$` : `${name}$`
      if (!path.match(pattern)) {
        throw new Error(`path ${path} must match ${pattern}`)
      }

      resourcesUploadFields[name] = uploadFields
      resourcesPaths[name] = path
      resource = name
    } else {
      resourcesPaths[resource] = resource
    }

    resourcesData[resource] = {}
    resourcesStatus[resource] = new Promise(resolve => {
      let ref = resourcesReferences[resource] = firebase.database().ref(resourcesPaths[resource])

      ref.on('value', function (childSnapshot) {
        /** Uses "value" to fetch initial data. Avoid the AOR to show no results */
        if (childSnapshot.key === resource) { resourcesData[resource] = childSnapshot.val() || [] }
        Object.keys(resourcesData[resource]).forEach(key => { resourcesData[resource][key].id = key })
        ref.on('child_added', function (childSnapshot) {
          resourcesData[resource][childSnapshot.key] = childSnapshot.val()
          resourcesData[resource][childSnapshot.key].id = childSnapshot.key
        })
        ref.on('child_removed', function (oldChildSnapshot) {
          console.log('child_removed', resource, oldChildSnapshot.key)
          if (resourcesData[resource][oldChildSnapshot.key]) { delete resourcesData[resource][oldChildSnapshot.key] }
        })
        ref.on('child_changed', function (childSnapshot) {
          resourcesData[resource][childSnapshot.key] = childSnapshot.val()
        })
        resolve()
      })
    })

    return true
  })

  /**
   * @param {string} type Request type, e.g GET_LIST
   * @param {string} resourceName Resource name, e.g. "posts"
   * @param {Object} payload Request parameters. Depends on the request type
   * @returns {Promise} the Promise for a REST response
   */

  return (type, resourceName, params) => {
    return new Promise((resolve, reject) => {
      resourcesStatus[resourceName].then(() => {
        switch (type) {
          case GET_LIST:
          case GET_MANY:
          case GET_MANY_REFERENCE:

            let ids = []
            let data = []
            let total = 0

            if (params.ids) {
              /** GET_MANY */
              params.ids.map(key => {
                if (resourcesData[resourceName][key]) {
                  ids.push(key)
                  data.push(resourcesData[resourceName][key])
                  total++
                }
                return total
              })
            } else if (params.pagination) {
              /** GET_LIST / GET_MANY_REFERENCE */
              let values = []

              // Copy the filter params so we can modify for GET_MANY_REFERENCE support.
              const filter = Object.assign({}, params.filter)

              if (params.target && params.id) {
                filter[params.target] = params.id
              }

              const filterKeys = Object.keys(filter)
              /* TODO Must have a better way */
              if (filterKeys.length) {
                Object.values(resourcesData[resourceName]).map(value => {
                  let filterIndex = 0
                  while (filterIndex < filterKeys.length) {
                    let property = filterKeys[filterIndex]
                    if (property !== 'q' && value[property] !== filter[property]) {
                      return filterIndex
                    } else if (property === 'q') {
                      if (JSON.stringify(value).indexOf(filter['q']) === -1) {
                        return filterIndex
                      }
                    }
                    filterIndex++
                  }
                  values.push(value)
                  return filterIndex
                })
              } else {
                values = Object.values(resourcesData[resourceName])
              }

              const {page, perPage} = params.pagination
              const _start = (page - 1) * perPage
              const _end = page * perPage
              data = values.slice(_start, _end)
              ids = Object.keys(resourcesData[resourceName]).slice(_start, _end)
              total = values.length
            } else {
              console.error('Unexpected parameters: ', params, type)
              reject(new Error('Error processing request'))
            }
            resolve({ data, ids, total })
            return

          case GET_ONE:
            const key = params.id
            if (key && resourcesData[resourceName][key]) {
              resolve({ data: resourcesData[resourceName][key] })
            } else {
              reject(new Error('Key not found'))
            }
            return

          case DELETE:
            del(params.id, resourceName, resourcesPaths[resourceName], resolve, reject)
            return

          case UPDATE:
          case CREATE:
            let itemId = getItemID(params, type, resourceName, resourcesPaths[resourceName], resourcesData[resourceName], resolve, reject)

            try {
              const uploads = resourcesUploadFields[resourceName] ? resourcesUploadFields[resourceName]
                .map(field => upload(field, params.data, itemId, resourceName)) : []
              const currentData = resourcesData[resourceName][itemId] || {}
              Promise.all(uploads).then(uploadResults =>
                save(itemId, params.data, currentData, resourceName, resolve, reject, uploadResults))
            } catch (e) {
              reject(e)
            }

            return

          default:
            console.error('Undocumented method: ', type)
            return {data: []}
        }
      })
    })
  }
}
<commit_msg>Delete uploads<commit_after>import firebase from 'firebase'

import {
  GET_LIST,
  GET_ONE,
  GET_MANY,
  GET_MANY_REFERENCE,
  CREATE,
  UPDATE,
  DELETE
} from 'admin-on-rest'

/**
 * @param {string[]|Object[]} trackedResources Array of resource names or array of Objects containing name and
 * optional path properties (path defaults to name)
 * @param {Object} firebaseConfig Optiona Firebase configuration
 */

const timestampFieldNames = {
  createdAt: 'created_at',
  updatedAt: 'updated_at'
}

export const methodUpload = async (fieldName, submitedData, id, resourceName, resourcePath) => {
  const file = submitedData[fieldName] ? submitedData[fieldName][0].rawFile : {}
  const result = {}
  if (file && file.name) {
    const ref = firebase.storage().ref().child(`${resourcePath}/${id}/${fieldName}`)
    const snapshot = await ref.put(file)
    result[fieldName] = [{}]
    result[fieldName][0].uploadedAt = Date.now()
    result[fieldName][0].src = snapshot.downloadURL.split('?').shift() + '?alt=media'
    return result
  }
  return false
}

export const methodSave = async (id, newData, currentData, resourceName, resourcePath, resolve, reject, uploadResults) => {
  try {
    if (uploadResults) {
      uploadResults.map(result => result ? Object.assign(newData, result) : false)
    }
    newData = Object.assign({ [timestampFieldNames.updatedAt]: Date.now() },
      currentData,
      newData)
    await firebase.database().ref(resourcePath + '/' + id).update(newData)
    resolve({ data: newData })
    return newData
  } catch (e) {
    reject(e)
  }
  return false
}

export const methodDelete = async (id, resourceName, resourcePath, uploadFields, resolve, reject) => {
  try {
    if (uploadFields.length) {
      uploadFields.map(fieldName =>
        firebase.storage().ref().child(`${resourcePath}/${id}/${fieldName}`).delete())
    }
    await firebase.database().ref(resourcePath + '/' + id).remove()
    resolve({ data: id })
    return { data: id }
  } catch (e) {
    reject(e)
  }
  return false
}

export const methodGetItemID = (params, type, resourceName, resourcePath, resourceData, resolve, reject) => {
  let itemId = params.data.id || params.id
  if (!itemId) {
    itemId = firebase.database().ref().child(resourcePath).push().key
  }
  if (!itemId) {
    reject(new Error('ID is required'))
    return 0
  }
  if (resourceData && resourceData[itemId] && type === CREATE) {
    reject(new Error('ID already in use'))
    return
  }
  return itemId
}

export default (trackedResources = [], firebaseConfig = {}, options = {}) => {
  Object.assign(timestampFieldNames, options.timestampFieldNames)

  /** TODO Move this to the Redux Store */
  const resourcesStatus = {}
  const resourcesReferences = {}
  const resourcesData = {}
  const resourcesPaths = {}
  const resourcesUploadFields = {}

  if (firebase.apps.length === 0) {
    firebase.initializeApp(firebaseConfig)
  }

  /* Functions */
  const upload = options.methodUpload || methodUpload
  const save = options.methodSave || methodSave
  const del = options.methodUpload || methodUpload
  const getItemID = options.getItemID || methodGetItemID

  trackedResources.map(resource => {
    if (typeof resource === 'object') {
      if (!resource.name) {
        throw new Error(`name is missing from resource ${resource}`)
      }

      const name = resource.name
      const path = resource.path || resource.name
      const uploadFields = resource.uploadFields || []

      // Check path ends with name so the initial children can be loaded from on 'value' below.
      const pattern = path.indexOf('/') >= 0 ? `/${name}$` : `${name}$`
      if (!path.match(pattern)) {
        throw new Error(`path ${path} must match ${pattern}`)
      }

      resourcesUploadFields[name] = uploadFields
      resourcesPaths[name] = path
      resource = name
    } else {
      resourcesPaths[resource] = resource
    }

    resourcesData[resource] = {}
    resourcesStatus[resource] = new Promise(resolve => {
      let ref = resourcesReferences[resource] = firebase.database().ref(resourcesPaths[resource])

      ref.on('value', function (childSnapshot) {
        /** Uses "value" to fetch initial data. Avoid the AOR to show no results */
        if (childSnapshot.key === resource) { resourcesData[resource] = childSnapshot.val() || [] }
        Object.keys(resourcesData[resource]).forEach(key => { resourcesData[resource][key].id = key })
        ref.on('child_added', function (childSnapshot) {
          resourcesData[resource][childSnapshot.key] = childSnapshot.val()
          resourcesData[resource][childSnapshot.key].id = childSnapshot.key
        })
        ref.on('child_removed', function (oldChildSnapshot) {
          console.log('child_removed', resource, oldChildSnapshot.key)
          if (resourcesData[resource][oldChildSnapshot.key]) { delete resourcesData[resource][oldChildSnapshot.key] }
        })
        ref.on('child_changed', function (childSnapshot) {
          resourcesData[resource][childSnapshot.key] = childSnapshot.val()
        })
        resolve()
      })
    })

    return true
  })

  /**
   * @param {string} type Request type, e.g GET_LIST
   * @param {string} resourceName Resource name, e.g. "posts"
   * @param {Object} payload Request parameters. Depends on the request type
   * @returns {Promise} the Promise for a REST response
   */

  return (type, resourceName, params) => {
    return new Promise((resolve, reject) => {
      resourcesStatus[resourceName].then(() => {
        switch (type) {
          case GET_LIST:
          case GET_MANY:
          case GET_MANY_REFERENCE:

            let ids = []
            let data = []
            let total = 0

            if (params.ids) {
              /** GET_MANY */
              params.ids.map(key => {
                if (resourcesData[resourceName][key]) {
                  ids.push(key)
                  data.push(resourcesData[resourceName][key])
                  total++
                }
                return total
              })
            } else if (params.pagination) {
              /** GET_LIST / GET_MANY_REFERENCE */
              let values = []

              // Copy the filter params so we can modify for GET_MANY_REFERENCE support.
              const filter = Object.assign({}, params.filter)

              if (params.target && params.id) {
                filter[params.target] = params.id
              }

              const filterKeys = Object.keys(filter)
              /* TODO Must have a better way */
              if (filterKeys.length) {
                Object.values(resourcesData[resourceName]).map(value => {
                  let filterIndex = 0
                  while (filterIndex < filterKeys.length) {
                    let property = filterKeys[filterIndex]
                    if (property !== 'q' && value[property] !== filter[property]) {
                      return filterIndex
                    } else if (property === 'q') {
                      if (JSON.stringify(value).indexOf(filter['q']) === -1) {
                        return filterIndex
                      }
                    }
                    filterIndex++
                  }
                  values.push(value)
                  return filterIndex
                })
              } else {
                values = Object.values(resourcesData[resourceName])
              }

              const {page, perPage} = params.pagination
              const _start = (page - 1) * perPage
              const _end = page * perPage
              data = values.slice(_start, _end)
              ids = Object.keys(resourcesData[resourceName]).slice(_start, _end)
              total = values.length
            } else {
              console.error('Unexpected parameters: ', params, type)
              reject(new Error('Error processing request'))
            }
            resolve({ data, ids, total })
            return

          case GET_ONE:
            const key = params.id
            if (key && resourcesData[resourceName][key]) {
              resolve({ data: resourcesData[resourceName][key] })
            } else {
              reject(new Error('Key not found'))
            }
            return

          case DELETE:
            const uploadFields = resourcesUploadFields[resourceName] ? resourcesUploadFields[resourceName] : []
            del(params.id, resourceName, resourcesPaths[resourceName], uploadFields, resolve, reject)
            return

          case UPDATE:
          case CREATE:
            let itemId = getItemID(params, type, resourceName, resourcesPaths[resourceName], resourcesData[resourceName], resolve, reject)

            try {
              const uploads = resourcesUploadFields[resourceName] ? resourcesUploadFields[resourceName]
                .map(field => upload(field, params.data, itemId, resourceName)) : []
              const currentData = resourcesData[resourceName][itemId] || {}
              Promise.all(uploads).then(uploadResults =>
                save(itemId, params.data, currentData, resourceName, resolve, reject, uploadResults))
            } catch (e) {
              reject(e)
            }

            return

          default:
            console.error('Undocumented method: ', type)
            return {data: []}
        }
      })
    })
  }
}
<|endoftext|>


<commit_before>const router = require('express').Router();
const db = require('../middleware/db');

router.use(function(req, res, next){
  if(!req.signedCookies || !req.signedCookies[global.config.Cookie.Name]){
    res.locals.user = null;
    return next();
  }
  else{
    var a_sess = req.signedCookies[global.config.Cookie.Name];
    db.query('Select `users`.* from `sessions` join `users` on `users`.`ID` = `sessions`.`User_ID` Where `Session_ID`=? and `Expires`>?;', [a_sess, ~~(new Date()/1000)], function(err, results){
      if(err){
        console.log('Error connecting to auth service');
        return res.send({Success: false, Error: 'Could not retrieve session'});
      }
      if(results.length<1){
        res.locals.user = null;
        return next();
      }
      else{
        res.locals.user = results[0];
        delete res.locals.user.PasswordHash;
        delete res.locals.user.Salt;
        delete res.locals.user.Confirm;
        return next();
      }
    });
  }
});

router.use('/auth', require('./auth'));
router.use('/files', require('./files'));

module.exports=router;
<commit_msg>Require authentication before accessing files<commit_after>const router = require('express').Router();
const db = require('../middleware/db');

router.use(function(req, res, next){
  if(!req.signedCookies || !req.signedCookies[global.config.Cookie.Name]){
    res.locals.user = null;
    return next();
  }
  else{
    var a_sess = req.signedCookies[global.config.Cookie.Name];
    db.query('Select `users`.* from `sessions` join `users` on `users`.`ID` = `sessions`.`User_ID` Where `Session_ID`=? and `Expires`>?;', [a_sess, ~~(new Date()/1000)], function(err, results){
      if(err){
        console.log('Error connecting to auth service');
        return res.send({Success: false, Error: 'Could not retrieve session'});
      }
      if(results.length<1){
        res.locals.user = null;
        return next();
      }
      else{
        res.locals.user = results[0];
        delete res.locals.user.PasswordHash;
        delete res.locals.user.Salt;
        delete res.locals.user.Confirm;
        return next();
      }
    });
  }
});

router.use('/auth', require('./auth'));

router.use(function(req, res, next){
  if(!res.locals.user){
    return res.send({Success: false, Error:'Unauthenticated!'});
  }
  else {
    return next();
  }
});

router.use('/files', require('./files'));

module.exports=router;
<|endoftext|>