<commit_before>/* global __DEV__ HAS_CLIENT_LOADING ROC_CLIENT_LOADING ROC_PATH HAS_REDUX_REDUCERS */

import React from 'react';
import ReactDOM from 'react-dom';

import Router from 'react-router/lib/Router';
import useRouterHistory from 'react-router/lib/useRouterHistory';
import { createHistory } from 'history';

import debug from 'debug';

import { RedialContext } from 'react-router-redial';
import { rocConfig } from '../shared/universal-config';

const clientDebug = debug('roc:client');

const basename = ROC_PATH === '/' ? '' : ROC_PATH;

/**
 * Client entry point for React applications.
 *
 * @example
 * import { createClient } from 'roc-web-react/app/client';
 *
 * const server = createClient({
 *     createRoutes: routes,
 *     createStore: store,
 *     mountNode: 'application'
 * });
 *
 * @param {rocClientOptions} options - Options for the client
 */
export default function createClient({ createRoutes, createStore, mountNode }) {
    if (!createRoutes) {
        throw new Error(`createRoutes needs to be defined`);
    }

    if (!mountNode) {
        throw new Error(`mountNode needs to be defined`);
    }

    if (rocConfig) {
        debug.enable(rocConfig.runtime.debug.client);
    }

    if (__DEV__ && rocConfig.dev.a11y) {
        if (rocConfig.runtime.ssr) {
            clientDebug('You will see a "Warning: React attempted to reuse markup in a container but the checksum was' +
                ' invalid." message. That\'s because a11y is enabled.');
        }

        require('react-a11y')(React, {
            ReactDOM,
            // These needs to be added for Redux Devtools to be ignored by A11Y
            filterFn: (name) => [
                'LogMonitorButton',
                'LogMonitorAction',
                'JSONValueNode',
                'JSONNestedNode',
                'JSONArrow'
            ].indexOf(name) === -1
        });
    }

    const render = () => {
        const node = document.getElementById(mountNode);

        let history = useRouterHistory(createHistory)({
            basename
        });

        let initialLoading = null;
        if (HAS_CLIENT_LOADING) {
            initialLoading = require(ROC_CLIENT_LOADING).default;
        }

        let routes;
        let locals = {};
        let createComponent = [(component) => component];
        let createDevComponent = [(component) => component];

        if (HAS_REDUX_REDUCERS && createStore) {
            const { Provider } = require('react-redux');
            const { syncHistoryWithStore } = require('react-router-redux');

            const store = createStore(history, window.FLUX_STATE);
            history = syncHistoryWithStore(history, store);

            routes = createRoutes(store);
            locals = {
                dispatch: store.dispatch,
                getState: store.getState
            };

            createComponent.push((component) => (
                <Provider store={ store }>
                    { component }
                </Provider>
            ));

            if (__DEV__) {
                if (rocConfig.dev.reduxDevtools.enabled && !window.devToolsExtension) {
                    const DevTools = require('./dev-tools').default;

                    createDevComponent.push((component) => (
                        <Provider store={ store }>

                                { component }
                                <DevTools />

                        </Provider>
                    ));
                } else if (rocConfig.dev.reduxDevtools.enabled) {
                    console.log('Found Redux Devtools Chrome extension, will use that over default one.');
                }
            }
        } else {
            routes = createRoutes();
        }

        if (__DEV__ && rocConfig.dev.yellowbox.enabled) {
            const YellowBox = require('yellowbox-react').default;

            /* eslint-disable no-console */
            console.ignoredYellowBox = rocConfig.dev.yellowbox.ignore;
            /* eslint-enable */

            createDevComponent.push((component) => (

                    { component }
                    <YellowBox />

            ));
        }

        const finalComponent = compose(createComponent)(
            <Router
                history={ history }
                routes={ routes }
                render={ (props) => (
                    <RedialContext
                        { ...props }
                        locals={ locals }
                        blocking={ rocConfig.runtime.fetch.client.blocking }
                        defer={ rocConfig.runtime.fetch.client.defer }
                        parallel={ rocConfig.runtime.fetch.client.parallel }
                        initialLoading={ initialLoading }
                    />
                )}
            />
        );

        ReactDOM.render(finalComponent, node);

        if (__DEV__) {
            const devNode = document.createElement('div');
            node.parentNode.insertBefore(devNode, node.nextSibling);
            ReactDOM.render(compose(createDevComponent)(null), devNode);
        }
    };

    render();
}

function compose(funcs) {
    if (funcs.length === 0) {
        return (arg) => arg;
    }

    const last = funcs[funcs.length - 1];
    const rest = funcs.slice(0, -1);
    return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args));
}
<commit_msg>Only sync the url using react-router-redux if the browser supports it<commit_after>/* global __DEV__ HAS_CLIENT_LOADING ROC_CLIENT_LOADING ROC_PATH HAS_REDUX_REDUCERS */

import React from 'react';
import ReactDOM from 'react-dom';

import Router from 'react-router/lib/Router';
import useRouterHistory from 'react-router/lib/useRouterHistory';
import { createHistory } from 'history';
import { supportsHistory } from 'history/lib/DOMUtils';

import debug from 'debug';

import { RedialContext } from 'react-router-redial';
import { rocConfig } from '../shared/universal-config';

const clientDebug = debug('roc:client');

const basename = ROC_PATH === '/' ? '' : ROC_PATH;

/**
 * Client entry point for React applications.
 *
 * @example
 * import { createClient } from 'roc-web-react/app/client';
 *
 * const server = createClient({
 *     createRoutes: routes,
 *     createStore: store,
 *     mountNode: 'application'
 * });
 *
 * @param {rocClientOptions} options - Options for the client
 */
export default function createClient({ createRoutes, createStore, mountNode }) {
    if (!createRoutes) {
        throw new Error(`createRoutes needs to be defined`);
    }

    if (!mountNode) {
        throw new Error(`mountNode needs to be defined`);
    }

    if (rocConfig) {
        debug.enable(rocConfig.runtime.debug.client);
    }

    if (__DEV__ && rocConfig.dev.a11y) {
        if (rocConfig.runtime.ssr) {
            clientDebug('You will see a "Warning: React attempted to reuse markup in a container but the checksum was' +
                ' invalid." message. That\'s because a11y is enabled.');
        }

        require('react-a11y')(React, {
            ReactDOM,
            // These needs to be added for Redux Devtools to be ignored by A11Y
            filterFn: (name) => [
                'LogMonitorButton',
                'LogMonitorAction',
                'JSONValueNode',
                'JSONNestedNode',
                'JSONArrow'
            ].indexOf(name) === -1
        });
    }

    const render = () => {
        const node = document.getElementById(mountNode);

        let history = useRouterHistory(createHistory)({
            basename
        });

        let initialLoading = null;
        if (HAS_CLIENT_LOADING) {
            initialLoading = require(ROC_CLIENT_LOADING).default;
        }

        let routes;
        let locals = {};
        let createComponent = [(component) => component];
        let createDevComponent = [(component) => component];

        if (HAS_REDUX_REDUCERS && createStore) {
            const { Provider } = require('react-redux');
            const { syncHistoryWithStore } = require('react-router-redux');

            const store = createStore(history, window.FLUX_STATE);
            history = syncHistoryWithStore(history, store, {
                // We do not want to use adjustUrlOnReplay if the browser does
                // not support the history API with pushState since this can lead
                // to redirect loops https://github.com/reactjs/react-router-redux/issues/285
                adjustUrlOnReplay: supportsHistory()
            });

            routes = createRoutes(store);
            locals = {
                dispatch: store.dispatch,
                getState: store.getState
            };

            createComponent.push((component) => (
                <Provider store={ store }>
                    { component }
                </Provider>
            ));

            if (__DEV__) {
                if (rocConfig.dev.reduxDevtools.enabled && !window.devToolsExtension) {
                    const DevTools = require('./dev-tools').default;

                    createDevComponent.push((component) => (
                        <Provider store={ store }>

                                { component }
                                <DevTools />

                        </Provider>
                    ));
                } else if (rocConfig.dev.reduxDevtools.enabled) {
                    console.log('Found Redux Devtools Chrome extension, will use that over default one.');
                }
            }
        } else {
            routes = createRoutes();
        }

        if (__DEV__ && rocConfig.dev.yellowbox.enabled) {
            const YellowBox = require('yellowbox-react').default;

            /* eslint-disable no-console */
            console.ignoredYellowBox = rocConfig.dev.yellowbox.ignore;
            /* eslint-enable */

            createDevComponent.push((component) => (

                    { component }
                    <YellowBox />

            ));
        }

        const finalComponent = compose(createComponent)(
            <Router
                history={ history }
                routes={ routes }
                render={ (props) => (
                    <RedialContext
                        { ...props }
                        locals={ locals }
                        blocking={ rocConfig.runtime.fetch.client.blocking }
                        defer={ rocConfig.runtime.fetch.client.defer }
                        parallel={ rocConfig.runtime.fetch.client.parallel }
                        initialLoading={ initialLoading }
                    />
                )}
            />
        );

        ReactDOM.render(finalComponent, node);

        if (__DEV__) {
            const devNode = document.createElement('div');
            node.parentNode.insertBefore(devNode, node.nextSibling);
            ReactDOM.render(compose(createDevComponent)(null), devNode);
        }
    };

    render();
}

function compose(funcs) {
    if (funcs.length === 0) {
        return (arg) => arg;
    }

    const last = funcs[funcs.length - 1];
    const rest = funcs.slice(0, -1);
    return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args));
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import GraphiQL from 'graphiql';
import fetch from 'isomorphic-fetch';
import Schema from './schema.js';
window.a = require('graphql');

export default class App extends Component {
  fetchData({query, variables}) {
    return window.a.graphql(Schema, query, null, JSON.parse(variables));
  }

  render() {
    return (
      <GraphiQL fetcher={this.fetchData} />
    );
  }
}
<commit_msg>Change logo<commit_after>import React, { Component } from 'react';
import GraphiQL from 'graphiql';
import fetch from 'isomorphic-fetch';
import Schema from './schema.js';

GraphiQL.Logo = class Logo extends Component {
  render() {
    let style = {
      fontWeight: 800,
      fontSize: 16,
      color: "#252525"
    };

    return (
      Learn GraphQL Sandbox
    );
  }
}

export default class App extends Component {
  fetchData({query, variables}) {
    return window.a.graphql(Schema, query, null, JSON.parse(variables));
  }

  render() {
    return (
      <GraphiQL fetcher={this.fetchData} />
    );
  }
}
<|endoftext|>


<commit_before>import every from 'lodash.every';

const props = ['type', 'next', 'prev', 'parent', 'children'];

export default (target) =>
  typeof target === 'object' && target !== null &&
    every(props, p => p in target);
<commit_msg>Prevent infinite loop when processing text dom node<commit_after>import every from 'lodash.every';

const props = ['type', 'next', 'prev', 'parent'];

export default (target) =>
  typeof target === 'object' && target !== null &&
    every(props, p => p in target);
<|endoftext|>


<commit_before>"use strict";
"use babel";

const $$ = require("atom-space-pen-views").$$;

const editorAction = require("./common/editor_action");
const prefs = require("./common/userPref_model");
const SelectListView = require("./select_list_view");
const utils = require("./utils");

var FollowView = function (me, users) {
  this.items_ = {};
  this.users = users;
  this.me = me;
  SelectListView.call(this);
};

utils.inherits(FollowView, SelectListView);

FollowView.prototype.initialize = function () {
  SelectListView.prototype.initialize.apply(this, arguments);
  this.addClass("modal overlay from-top");
  let myUsername = this.me.username;
  let items = this.users.map(function (u) {
    let username = u.username;
    this.items_[username] = prefs.followUsers.indexOf(username) !== -1;
    return u.username;
  }, this).filter(function (username) {
    return username !== myUsername;
  });
  items.unshift("all changes");
  this.items_.floobits = prefs.following;
  this.setItems(items);
};

FollowView.prototype.viewForItem = function (name) {
  var items = this.items_;
  return $$(function () {
    var that = this;
    this.li({"class": ""}, function () {
      that.div({"class": "primary-line icon icon-" + (items[name] ? "mute" : "unmute")}, (items[name] ? "Unfollow " : "Follow ") + name);
    });
  });
};

FollowView.prototype.confirmed = function (name) {
  SelectListView.prototype.confirmed.call(this, name);

  if (name === "floobits") {
    prefs.following = !prefs.following;
  } else {
    prefs.followUsers.toggle(name);
  }

  if (prefs.following || prefs.isFollowing(name)) {
    editorAction.jump_to_user(name);
  }
};

module.exports = FollowView;
<commit_msg>Whoops. Didn't see I had to change the name here.<commit_after>"use strict";
"use babel";

const $$ = require("atom-space-pen-views").$$;

const editorAction = require("./common/editor_action");
const prefs = require("./common/userPref_model");
const SelectListView = require("./select_list_view");
const utils = require("./utils");

var FollowView = function (me, users) {
  this.items_ = {};
  this.users = users;
  this.me = me;
  SelectListView.call(this);
};

utils.inherits(FollowView, SelectListView);

FollowView.prototype.initialize = function () {
  SelectListView.prototype.initialize.apply(this, arguments);
  this.addClass("modal overlay from-top");
  let myUsername = this.me.username;
  let items = this.users.map(function (u) {
    let username = u.username;
    this.items_[username] = prefs.followUsers.indexOf(username) !== -1;
    return u.username;
  }, this).filter(function (username) {
    return username !== myUsername;
  });
  items.unshift("all changes");
  this.items_.floobits = prefs.following;
  this.setItems(items);
};

FollowView.prototype.viewForItem = function (name) {
  var items = this.items_;
  return $$(function () {
    var that = this;
    this.li({"class": ""}, function () {
      that.div({"class": "primary-line icon icon-" + (items[name] ? "mute" : "unmute")}, (items[name] ? "Unfollow " : "Follow ") + name);
    });
  });
};

FollowView.prototype.confirmed = function (name) {
  SelectListView.prototype.confirmed.call(this, name);

  if (name === "all changes") {
    prefs.following = !prefs.following;
  } else {
    prefs.followUsers.toggle(name);
  }

  if (prefs.following || prefs.isFollowing(name)) {
    editorAction.jump_to_user(name);
  }
};

module.exports = FollowView;
<|endoftext|>


<commit_before>import {SpotLight as SpotLightNative, SpotLightHelper} from 'three';
import {LightComponent} from '../../core/LightComponent';

class SpotLight extends LightComponent {
  static helpers = {
    default: [SpotLightHelper]
  };

  constructor(params = {}) {
    super(params);
    this.wrapShadow();
  }

  build(params = {}) {
    return new SpotLightNative(
      params.light.color,
      params.light.intensity,
      params.light.distance,
      params.light.angle,
      params.light.exponent,
      params.light.decay
    );
  }
}

export {
  SpotLight
};
<commit_msg>Updates defaults for spot light<commit_after>import {SpotLight as SpotLightNative, SpotLightHelper} from 'three';
import {LightComponent} from '../../core/LightComponent';

class SpotLight extends LightComponent {
  static defaults = {
    ...LightComponent.defaults,

    light: {
      color: 0xffffff,
      intensity: 1,
      distance: 100,
      angle: Math.PI / 3,
      exponent: 0,
      decay: 1
    }
  };

  static helpers = {
    default: [SpotLightHelper]
  };

  constructor(params = {}) {
    super(params);
    this.wrapShadow();
  }

  build(params = {}) {
    return new SpotLightNative(
      params.light.color,
      params.light.intensity,
      params.light.distance,
      params.light.angle,
      params.light.exponent,
      params.light.decay
    );
  }
}

export {
  SpotLight
};
<|endoftext|>


<commit_before>/**
 * Copyright 2015 IBM Corp. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* global Cookies:true, nextHour, currentPage, setupUse */

'use strict';

$(document).ready(function() {
  $('._training--example').click(function() {
    $('.showing div._examples--class__selected button').click();
    var kind = $(this).data('kind');
    if ($('._examples[data-kind=' + kind + ']').hasClass('showing')) {
      $('.showing').removeClass('showing');
      $('._container--bundle-form').removeClass('active');
    } else {
      $('.showing').removeClass('showing');
      $('._examples[data-kind=' + kind + ']').removeClass('removed');
      $('._container--bundle-form input[type=submit]').addClass('disabled');
      $('._container--bundle-form input[type=submit]').prop('disabled', true);
      setTimeout(function() {
        $('.showing').addClass('removed');
        $('._examples[data-kind=' + kind + ']').addClass('showing');
        $('._container--bundle-form').addClass('active');
      }, 100);
    }
  });

  $('._examples--class button').click(function() {
    if ($(this).parent().hasClass('_examples--class__selected')) {
      $(this).data('selected', 0);
      $(this).html('Select');
    } else {
      $(this).data('selected', 1);
      $(this).html('Selected');
    }
    $(this).parent().toggleClass('_examples--class__selected');

    if ($('.showing ._examples--class__selected._positive').length >= 2) {
      $('.train--train-button.base--button').removeClass('disabled');
      $('.train--train-button.base--button').prop('disabled', false);
    } else {
      $('.train--train-button.base--button').addClass('disabled');
      $('.train--train-button.base--button').prop('disabled', true);
    }
    return false;
  });

  $('._examples--class img').click(function() {
    $(this).data('name');
    $('._examples--contact-sheet[data-kind=' + $(this).data('kind') + '] img').attr('src', '/images/bundles/' + $(this).data('kind') + '/' + $(this).data('name') + '-contact.jpg');
    $('._examples--contact-sheet[data-kind=' + $(this).data('kind') + ']').css('display', 'flex');
  });

  $('._examples--contact-sheet img').click(function() {
    $(this).attr('src', '');
    $(this).parent().css('display', 'none');
  });

  $('a.select_all').click(function() {
    if ($('.showing div._examples--class:not(._examples--class__selected)').length > 0) {
      $('.showing div._examples--class:not(._examples--class__selected) button').click();
    } else {
      $('.showing div._examples--class__selected button').click();
    }
    $(this).text($(this).text() === 'Select All' ? 'Unselect All' : 'Select All');
  });

  var $loading = $('.train--loading');
  var $error = $('.train--error');
  var $errorMsg = $('.train--error-message');
  var $trainButton = $('.train--train-button');
  var $trainInput = $('._container--training');

  function resetPage() {
    $trainInput.show();
    $loading.hide();
    $error.hide();
  }

  function showTrainingError(err) {
    $loading.hide();
    $trainInput.hide();
    $error.show();
    var message = 'Error creating the classifier';
    if (err.responseJSON) {
      message = err.responseJSON.error;
    }
    $errorMsg.html(message);
  }

  function lookupName(token) {
    return {
      moleskine: 'Moleskine Types',
      dogs: 'Dogs',
      insurance: 'Insurance Claims',
      omniearth: 'Satellite Images'
    }[token];
  }

  $trainButton.click(function() {
    $trainInput.hide();
    $loading.show();
    $error.hide();

    var data = $('.showing div._examples--class__selected')
    .map(function(idx, item) {
      return {
        name: $(item).data('name'),
        realname: $(item).data('realname'),
        kind: $(item).data('kind')
      };
    })
    .toArray().reduce(function(k, v) {
      k.bundles.push(v.name);
      if (v.realname) {
        k.names.push(v.realname);
      }
      k.kind = v.kind;
      return k;
    }, { bundles: [], names: []});

    data.name = lookupName(data.kind);

    $.ajax({
      type: 'POST',
      url: '/api/classifiers',
      data: JSON.stringify(data),
      contentType: 'application/json; charset=utf-8',
      dataType: 'json',
      success: function(classifier) {
        checkClassifier(classifier.classifier_id, function done() {
          Cookies.set('bundle', data, { expires: nextHour()});
          Cookies.set('classifier', classifier, { expires: nextHour()});
          resetPage();
          window.location.href = '/test';
        });
      },
      error: showTrainingError
    });
  });

  var classifierCheckPollInterval = 5000;
  var totalWaitingTime = 0;
  function checkClassifier(classifierId, done) {
    totalWaitingTime += classifierCheckPollInterval;
    $.get('/api/classifiers/' + classifierId)
    .success(function(data) {
      if (data.status === 'ready') {
        done(classifier);
      } else if (data.status === 'failed') {
        showTrainingError();
      } else {
        setTimeout(checkClassifier, classifierCheckPollInterval, classifierId, done);
      }
    })
    .fail(showTrainingError);
  }

  // init pages
  setupUse({ panel: 'use' });
  setupUse({ panel: 'test'});

  var classifier = Cookies.get('classifier');
  // enable test if there is trained classifier
  if (classifier) {
    $('.tab-panels--tab[href="/test"]').removeClass('disabled');
  }
  // send the user to train if they hit /test without a trained classifier
  if (currentPage() === '/test') {
    if (!classifier) {
      $('.tab-panels--tab[href="/train"]').trigger('click');
    }
  }
});
<commit_msg>fixed selected bundles<commit_after>/**
 * Copyright 2015 IBM Corp. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* global Cookies:true, nextHour, currentPage, setupUse */

'use strict';

$(document).ready(function() {
  $('._training--example').click(function() {
    $('.showing div._examples--class__selected button').click();
    var kind = $(this).data('kind');
    if ($('._examples[data-kind=' + kind + ']').hasClass('showing')) {
      $('.showing').removeClass('showing');
      $('._container--bundle-form').removeClass('active');
    } else {
      $('.showing').removeClass('showing');
      $('._examples[data-kind=' + kind + ']').removeClass('removed');
      $('._container--bundle-form input[type=submit]').addClass('disabled');
      $('._container--bundle-form input[type=submit]').prop('disabled', true);
      setTimeout(function() {
        $('.showing').addClass('removed');
        $('._examples[data-kind=' + kind + ']').addClass('showing');
        $('._container--bundle-form').addClass('active');
      }, 100);
    }
  });

  $('._examples--class button').click(function() {
    if ($(this).parent().hasClass('_examples--class__selected')) {
      $(this).data('selected', 0);
      $(this).html('Select');
    } else {
      $(this).data('selected', 1);
      $(this).html('Selected');
    }
    $(this).parent().toggleClass('_examples--class__selected');

    if ($('.showing ._examples--class__selected._positive').length > 2 ||
      ($('.showing ._examples--class__selected._positive').length > 0 && $('.showing ._examples--class__selected._negative').length === 1 )
     ) {
      $('.train--train-button.base--button').removeClass('disabled');
      $('.train--train-button.base--button').prop('disabled', false);
    } else {
      $('.train--train-button.base--button').addClass('disabled');
      $('.train--train-button.base--button').prop('disabled', true);
    }
    return false;
  });

  $('._examples--class img').click(function() {
    $(this).data('name');
    $('._examples--contact-sheet[data-kind=' + $(this).data('kind') + '] img').attr('src', '/images/bundles/' + $(this).data('kind') + '/' + $(this).data('name') + '-contact.jpg');
    $('._examples--contact-sheet[data-kind=' + $(this).data('kind') + ']').css('display', 'flex');
  });

  $('._examples--contact-sheet img').click(function() {
    $(this).attr('src', '');
    $(this).parent().css('display', 'none');
  });

  $('a.select_all').click(function() {
    if ($('.showing div._examples--class:not(._examples--class__selected)').length > 0) {
      $('.showing div._examples--class:not(._examples--class__selected) button').click();
    } else {
      $('.showing div._examples--class__selected button').click();
    }
    $(this).text($(this).text() === 'Select All' ? 'Unselect All' : 'Select All');
  });

  var $loading = $('.train--loading');
  var $error = $('.train--error');
  var $errorMsg = $('.train--error-message');
  var $trainButton = $('.train--train-button');
  var $trainInput = $('._container--training');

  function resetPage() {
    $trainInput.show();
    $loading.hide();
    $error.hide();
  }

  function showTrainingError(err) {
    $loading.hide();
    $trainInput.hide();
    $error.show();
    var message = 'Error creating the classifier';
    if (err.responseJSON) {
      message = err.responseJSON.error;
    }
    $errorMsg.html(message);
  }

  function lookupName(token) {
    return {
      moleskine: 'Moleskine Types',
      dogs: 'Dogs',
      insurance: 'Insurance Claims',
      omniearth: 'Satellite Images'
    }[token];
  }

  $trainButton.click(function() {
    $trainInput.hide();
    $loading.show();
    $error.hide();

    var data = $('.showing div._examples--class__selected')
    .map(function(idx, item) {
      return {
        name: $(item).data('name'),
        realname: $(item).data('realname'),
        kind: $(item).data('kind')
      };
    })
    .toArray().reduce(function(k, v) {
      k.bundles.push(v.name);
      if (v.realname) {
        k.names.push(v.realname);
      }
      k.kind = v.kind;
      return k;
    }, { bundles: [], names: []});

    data.name = lookupName(data.kind);

    $.ajax({
      type: 'POST',
      url: '/api/classifiers',
      data: JSON.stringify(data),
      contentType: 'application/json; charset=utf-8',
      dataType: 'json',
      success: function(classifier) {
        checkClassifier(classifier.classifier_id, function done() {
          Cookies.set('bundle', data, { expires: nextHour()});
          Cookies.set('classifier', classifier, { expires: nextHour()});
          resetPage();
          window.location.href = '/test';
        });
      },
      error: showTrainingError
    });
  });

  var classifierCheckPollInterval = 5000;
  var totalWaitingTime = 0;
  function checkClassifier(classifierId, done) {
    totalWaitingTime += classifierCheckPollInterval;
    $.get('/api/classifiers/' + classifierId)
    .success(function(data) {
      if (data.status === 'ready') {
        done(classifier);
      } else if (data.status === 'failed') {
        showTrainingError();
      } else {
        setTimeout(checkClassifier, classifierCheckPollInterval, classifierId, done);
      }
    })
    .fail(showTrainingError);
  }

  // init pages
  setupUse({ panel: 'use' });
  setupUse({ panel: 'test'});

  var classifier = Cookies.get('classifier');
  // enable test if there is trained classifier
  if (classifier) {
    $('.tab-panels--tab[href="/test"]').removeClass('disabled');
  }
  // send the user to train if they hit /test without a trained classifier
  if (currentPage() === '/test') {
    if (!classifier) {
      $('.tab-panels--tab[href="/train"]').trigger('click');
    }
  }
});
<|endoftext|>


<commit_before>/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/packs and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb

// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

console.log('Hello World from Webpacker')
<commit_msg>Illustrate how to use Active Storage<commit_after>/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/packs and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb

// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

// Activate Active Storage
// import * as ActiveStorage from "@rails/activestorage"
// ActiveStorage.start()
<|endoftext|>


<commit_before>/*!
 * EventEmitter v4.2.11 - git.io/ee
 * Unlicense - http://unlicense.org/
 * Oliver Caldwell - http://oli.me.uk/
 * @preserve
 */
(function(){"use strict";function t(){}function i(t,n){for(var e=t.length;e--;)if(t[e].listener===n)return e;return-1}function n(e){return function(){return this[e].apply(this,arguments)}}var e=t.prototype,r=this,s=r.EventEmitter;e.getListeners=function(n){var r,e,t=this._getEvents();if(n instanceof RegExp){r={};for(e in t)t.hasOwnProperty(e)&&n.test(e)&&(r[e]=t[e])}else r=t[n]||(t[n]=[]);return r},e.flattenListeners=function(t){var e,n=[];for(e=0;e<t.length;e+=1)n.push(t[e].listener);return n},e.getListenersAsObject=function(n){var e,t=this.getListeners(n);return t instanceof Array&&(e={},e[n]=t),e||t},e.addListener=function(r,e){var t,n=this.getListenersAsObject(r),s="object"==typeof e;for(t in n)n.hasOwnProperty(t)&&-1===i(n[t],e)&&n[t].push(s?e:{listener:e,once:!1});return this},e.on=n("addListener"),e.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},e.once=n("addOnceListener"),e.defineEvent=function(e){return this.getListeners(e),this},e.defineEvents=function(t){for(var e=0;e<t.length;e+=1)this.defineEvent(t[e]);return this},e.removeListener=function(r,s){var n,e,t=this.getListenersAsObject(r);for(e in t)t.hasOwnProperty(e)&&(n=i(t[e],s),-1!==n&&t[e].splice(n,1));return this},e.off=n("removeListener"),e.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},e.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},e.manipulateListeners=function(r,t,i){var e,n,s=r?this.removeListener:this.addListener,o=r?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(e=i.length;e--;)s.call(this,t,i[e]);else for(e in t)t.hasOwnProperty(e)&&(n=t[e])&&("function"==typeof n?s.call(this,e,n):o.call(this,e,n));return this},e.removeEvent=function(e){var t,r=typeof e,n=this._getEvents();if("string"===r)delete n[e];else if(e instanceof RegExp)for(t in n)n.hasOwnProperty(t)&&e.test(t)&&delete n[t];else delete this._events;return this},e.removeAllListeners=n("removeEvent"),e.emitEvent=function(r,o){var e,i,t,s,n=this.getListenersAsObject(r);for(t in n)if(n.hasOwnProperty(t))for(i=n[t].length;i--;)e=n[t][i],e.once===!0&&this.removeListener(r,e.listener),s=e.listener.apply(this,o||[]),s===this._getOnceReturnValue()&&this.removeListener(r,e.listener);return this},e.trigger=n("emitEvent"),e.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},e.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},e._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},e._getEvents=function(){return this._events||(this._events={})},t.noConflict=function(){return r.EventEmitter=s,t},"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:r.EventEmitter=t}).call(this);<commit_msg>Minify new version<commit_after>/*!
 * EventEmitter v4.2.11 - git.io/ee
 * Unlicense - http://unlicense.org/
 * Oliver Caldwell - http://oli.me.uk/
 * @preserve
 */
(function(){"use strict";function t(){}function i(t,n){for(var e=t.length;e--;)if(t[e].listener===n)return e;return-1}function n(e){return function(){return this[e].apply(this,arguments)}}var e=t.prototype,r=this,s=r.EventEmitter;e.getListeners=function(n){var r,e,t=this._getEvents();if(n instanceof RegExp){r={};for(e in t)t.hasOwnProperty(e)&&n.test(e)&&(r[e]=t[e])}else r=t[n]||(t[n]=[]);return r},e.flattenListeners=function(t){var e,n=[];for(e=0;e<t.length;e+=1)n.push(t[e].listener);return n},e.getListenersAsObject=function(n){var e,t=this.getListeners(n);return t instanceof Array&&(e={},e[n]=t),e||t},e.addListener=function(r,e){var t,n=this.getListenersAsObject(r),s="object"==typeof e;for(t in n)n.hasOwnProperty(t)&&-1===i(n[t],e)&&n[t].push(s?e:{listener:e,once:!1});return this},e.on=n("addListener"),e.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},e.once=n("addOnceListener"),e.defineEvent=function(e){return this.getListeners(e),this},e.defineEvents=function(t){for(var e=0;e<t.length;e+=1)this.defineEvent(t[e]);return this},e.removeListener=function(r,s){var n,e,t=this.getListenersAsObject(r);for(e in t)t.hasOwnProperty(e)&&(n=i(t[e],s),-1!==n&&t[e].splice(n,1));return this},e.off=n("removeListener"),e.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},e.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},e.manipulateListeners=function(r,t,i){var e,n,s=r?this.removeListener:this.addListener,o=r?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(e=i.length;e--;)s.call(this,t,i[e]);else for(e in t)t.hasOwnProperty(e)&&(n=t[e])&&("function"==typeof n?s.call(this,e,n):o.call(this,e,n));return this},e.removeEvent=function(e){var t,r=typeof e,n=this._getEvents();if("string"===r)delete n[e];else if(e instanceof RegExp)for(t in n)n.hasOwnProperty(t)&&e.test(t)&&delete n[t];else delete this._events;return this},e.removeAllListeners=n("removeEvent"),e.emitEvent=function(t,u){var n,e,r,i,o,s=this.getListenersAsObject(t);for(i in s)if(s.hasOwnProperty(i))for(n=s[i].slice(0),r=n.length;r--;)e=n[r],e.once===!0&&this.removeListener(t,e.listener),o=e.listener.apply(this,u||[]),o===this._getOnceReturnValue()&&this.removeListener(t,e.listener);return this},e.trigger=n("emitEvent"),e.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},e.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},e._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},e._getEvents=function(){return this._events||(this._events={})},t.noConflict=function(){return r.EventEmitter=s,t},"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:r.EventEmitter=t}).call(this);<|endoftext|>


<commit_before>/**
 * @license Angulartics v0.8.5
 * (c) 2013 Luis Farzati http://luisfarzati.github.io/angulartics
 * License: MIT
 */
(function(angular, analytics) {
'use strict';

var angulartics = window.angulartics || (window.angulartics = {});
angulartics.waitForVendorApi = function (objectName, delay, registerFn) {
  if (!Object.prototype.hasOwnProperty.call(window, objectName)) {
    setTimeout(function () { angulartics.waitForVendorApi(objectName, delay, registerFn); }, delay);
  }
  else {
    registerFn(window[objectName]);
  }
};

/**
 * @ngdoc overview
 * @name angulartics
 */
angular.module('angulartics', [])
.provider('$analytics', function () {
  var settings = {
    pageTracking: {
      autoTrackFirstPage: true,
      autoTrackVirtualPages: true,
      basePath: '',
      bufferFlushDelay: 1000
    },
    eventTracking: {
      bufferFlushDelay: 1000
    }
  };

  var cache = {
    pageviews: [],
    events: []
  };

  var bufferedPageTrack = function (path) {
    cache.pageviews.push(path);
  };
  var bufferedEventTrack = function (event, properties) {
    cache.events.push({name: event, properties: properties});
  };

  var api = {
    settings: settings,

    pageTrackers: [bufferedPageTrack],
    eventTrackers: [bufferedEventTrack],
    pageTrack: function (url) {
      angular.forEach(api.pageTrackers, function (tracker) {
        tracker(url);
      });
    },
    eventTrack: function (eventName, properties) {
      angular.forEach(api.eventTrackers, function (tracker) {
        tracker(eventName, properties);
      });
    }
  };

  var registerPageTrack = function (fn) {
    api.pageTrackers.push(fn);
    angular.forEach(cache.pageviews, function (path, index) {
      setTimeout(function () { api.pageTrack(path); }, index * settings.pageTracking.bufferFlushDelay);
    });
  };
  var registerEventTrack = function (fn) {
    api.eventTrackers.push(fn);
    angular.forEach(cache.events, function (event, index) {
      setTimeout(function () { api.eventTrack(event.name, event.properties); }, index * settings.eventTracking.bufferFlushDelay);
    });
  };

  return {
    $get: function() { return api; },
    settings: settings,
    virtualPageviews: function (value) { this.settings.pageTracking.autoTrackVirtualPages = value; },
    firstPageview: function (value) { this.settings.pageTracking.autoTrackFirstPage = value; },
    withBase: function (value) { this.settings.pageTracking.basePath = (value) ? angular.element('base').attr('href').slice(0, -1) : ''; },
    registerPageTrack: registerPageTrack,
    registerEventTrack: registerEventTrack
  };
})

.run(['$rootScope', '$location', '$analytics', function ($rootScope, $location, $analytics) {
  if ($analytics.settings.pageTracking.autoTrackFirstPage) {
    $analytics.pageTrack($location.path());
  }
  if ($analytics.settings.pageTracking.autoTrackVirtualPages) {
    $rootScope.$on('$locationChangeSuccess', function (event, current) {
      if (current && (current.$$route||current).redirectTo) return;
      var url = $analytics.settings.pageTracking.basePath + $location.url();
      $analytics.pageTrack(url);
    });
  }
}])

.directive('analyticsOn', ['$analytics', function ($analytics) {
  function isCommand(element) {
    return ['a:','button:','button:button','button:submit','input:button','input:submit'].indexOf(
      element.tagName.toLowerCase()+':'+(element.type||'')) >= 0;
  }

  function inferEventType(element) {
    if (isCommand(element)) return 'click';
    return 'click';
  }

  function inferEventName(element) {
    if (isCommand(element)) return element.innerText || element.value;
    return element.id || element.name || element.tagName;
  }

  function isProperty(name) {
    return name.substr(0, 9) === 'analytics' && ['on', 'event'].indexOf(name.substr(10)) === -1;
  }

  return {
    restrict: 'A',
    scope: false,
    link: function ($scope, $element, $attrs) {
      var eventType = $attrs.analyticsOn || inferEventType($element[0]),
          eventName = $attrs.analyticsEvent || inferEventName($element[0]);

      var properties = {};
      angular.forEach($attrs.$attr, function(attr, name) {
        if (isProperty(attr)) {
          properties[name.slice(9).toLowerCase()] = $attrs[name];
        }
      });

      angular.element($element[0]).bind(eventType, function () {
        $analytics.eventTrack(eventName, properties);
      });
    }
  };
}]);
})(angular);
<commit_msg>Prevent double tracking of events.<commit_after>/**
 * @license Angulartics v0.8.5
 * (c) 2013 Luis Farzati http://luisfarzati.github.io/angulartics
 * License: MIT
 */
(function(angular, analytics) {
'use strict';

var angulartics = window.angulartics || (window.angulartics = {});
angulartics.waitForVendorApi = function (objectName, delay, registerFn) {
  if (!Object.prototype.hasOwnProperty.call(window, objectName)) {
    setTimeout(function () { angulartics.waitForVendorApi(objectName, delay, registerFn); }, delay);
  }
  else {
    registerFn(window[objectName]);
  }
};

/**
 * @ngdoc overview
 * @name angulartics
 */
angular.module('angulartics', [])
.provider('$analytics', function () {
  var settings = {
    pageTracking: {
      autoTrackFirstPage: true,
      autoTrackVirtualPages: true,
      basePath: '',
      bufferFlushDelay: 1000
    },
    eventTracking: {
      bufferFlushDelay: 1000
    }
  };

  var cache = {
    pageviews: [],
    events: []
  };

  var bufferedPageTrack = function (path) {
    cache.pageviews.push(path);
  };
  var bufferedEventTrack = function (event, properties) {
    cache.events.push({name: event, properties: properties});
  };

  var api = {
    settings: settings,

    pageTrackers: [],
    eventTrackers: [],
    pageTrack: function (url) {
      if (this.pageTrackers.length) {
        angular.forEach(api.pageTrackers, function (tracker) {
          tracker(url);
        });
      } else {
        bufferedPageTrack(url);
      }
    },
    eventTrack: function (eventName, properties) {
      if (this.eventTrackers.length) {
        angular.forEach(api.eventTrackers, function (tracker) {
          tracker(eventName, properties);
        });
      } else {
        bufferedEventTrack(eventName, properties);
      }
    }
  };

  var registerPageTrack = function (fn) {
    api.pageTrackers.push(fn);
    angular.forEach(cache.pageviews, function (path, index) {
      setTimeout(function () { api.pageTrack(path); }, index * settings.pageTracking.bufferFlushDelay);
    });
  };
  var registerEventTrack = function (fn) {
    api.eventTrackers.push(fn);
    angular.forEach(cache.events, function (event, index) {
      setTimeout(function () { api.eventTrack(event.name, event.properties); }, index * settings.eventTracking.bufferFlushDelay);
    });
  };

  return {
    $get: function() { return api; },
    settings: settings,
    virtualPageviews: function (value) { this.settings.pageTracking.autoTrackVirtualPages = value; },
    firstPageview: function (value) { this.settings.pageTracking.autoTrackFirstPage = value; },
    withBase: function (value) { this.settings.pageTracking.basePath = (value) ? angular.element('base').attr('href').slice(0, -1) : ''; },
    registerPageTrack: registerPageTrack,
    registerEventTrack: registerEventTrack
  };
})

.run(['$rootScope', '$location', '$analytics', function ($rootScope, $location, $analytics) {
  if ($analytics.settings.pageTracking.autoTrackFirstPage) {
    $analytics.pageTrack($location.path());
  }
  if ($analytics.settings.pageTracking.autoTrackVirtualPages) {
    $rootScope.$on('$locationChangeSuccess', function (event, current) {
      if (current && (current.$$route||current).redirectTo) return;
      var url = $analytics.settings.pageTracking.basePath + $location.url();
      $analytics.pageTrack(url);
    });
  }
}])

.directive('analyticsOn', ['$analytics', function ($analytics) {
  function isCommand(element) {
    return ['a:','button:','button:button','button:submit','input:button','input:submit'].indexOf(
      element.tagName.toLowerCase()+':'+(element.type||'')) >= 0;
  }

  function inferEventType(element) {
    if (isCommand(element)) return 'click';
    return 'click';
  }

  function inferEventName(element) {
    if (isCommand(element)) return element.innerText || element.value;
    return element.id || element.name || element.tagName;
  }

  function isProperty(name) {
    return name.substr(0, 9) === 'analytics' && ['on', 'event'].indexOf(name.substr(10)) === -1;
  }

  return {
    restrict: 'A',
    scope: false,
    link: function ($scope, $element, $attrs) {
      var eventType = $attrs.analyticsOn || inferEventType($element[0]),
          eventName = $attrs.analyticsEvent || inferEventName($element[0]);

      var properties = {};
      angular.forEach($attrs.$attr, function(attr, name) {
        if (isProperty(attr)) {
          properties[name.slice(9).toLowerCase()] = $attrs[name];
        }
      });

      angular.element($element[0]).bind(eventType, function () {
        $analytics.eventTrack(eventName, properties);
      });
    }
  };
}]);
})(angular);
<|endoftext|>


<commit_before>/**
 * TagSpaces - universal file and folder organizer
 * Copyright (C) 2017-present TagSpaces UG (haftungsbeschraenkt)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License (version 3) as
 * published by the Free Software Foundation.
 *
 * 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 <https://www.gnu.org/licenses/>.
 *
 * @flow
 */

import { ipcRenderer } from 'electron';
import { walkDirectory, enhanceEntry } from './services/utils-io';
import AppConfig from './config';
import { getThumbnailURLPromise } from './services/thumbsgenerator';

let isGeneratingThumbs = false;

function init() {
  console.log('Init worker');
  ipcRenderer.on('worker', (event, arg) => {
    // console.log('worker received: ' + JSON.stringify(arg));
    switch (arg.action) {
    case 'createDirectoryIndex': {
      console.log('createDirectoryIndex started in worker window');
      console.time('createDirectoryIndex');
      const directoryIndex = [];
      let counter = 0;
      walkDirectory(arg.path, {
        recursive: true,
        skipMetaFolder: true,
        skipDotHiddenFolder: true,
        extractText: arg.extractText
      }, (fileEntry) => {
        counter += 1;
        if (counter > AppConfig.indexerLimit) {
          console.warn('Walk canceled by ' + AppConfig.indexerLimit);
          window.walkCanceled = true;
        }
        directoryIndex.push(enhanceEntry(fileEntry));
      }, (directoryEntry) => {
        if (directoryEntry.name !== AppConfig.metaFolder) {
          counter += 1;
          directoryIndex.push(enhanceEntry(directoryEntry));
        }
      }).then(() => { // entries - can be used for further processing
        window.walkCanceled = false;
        console.log('Directory index created ' + arg.path + ' containing ' + directoryIndex.length);
        console.timeEnd('createDirectoryIndex');
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: directoryIndex,
          error: ''
        });
        return true;
      }).catch((err) => {
        window.walkCanceled = false;
        console.timeEnd('createDirectoryIndex');
        console.warn('Error creating index: ' + err);
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: [], // directoryIndex,
          error: err
        });
      });
      break;
    }
    case 'createThumbnails': {
      console.log('createThumbnails started in worker window');
      if (!arg.tmbGenerationList || arg.tmbGenerationList.length < 1 || isGeneratingThumbs) {
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: [],
          error: 'Empty or not available tmb list or busy worker'
        });
        break;
      }
      isGeneratingThumbs = true;
      const tmbGenerationPromises = [];
      let showSplash = false;
      arg.tmbGenerationList.map(entry => {
        showSplash = entry.endsWith('pdf');
        tmbGenerationPromises.push(getThumbnailURLPromise(entry));
        return true;
      });
      if (showSplash) {
        ipcRenderer.send('setSplashVisibility', {
          visibility: true,
        });
      }
      Promise.all(tmbGenerationPromises).then(tmbResult => {
        console.log('tmb results' + JSON.stringify(tmbResult));
        ipcRenderer.send('setSplashVisibility', {
          visibility: false,
        });
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: tmbResult,
          error: ''
        });
        isGeneratingThumbs = false;
        return true;
      }).catch(error => {
        console.warn('Tmb generation failed: ' + error);
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: [],
          error: 'Error generating thumbnails: ' + error
        });
        ipcRenderer.send('setSplashVisibility', {
          visibility: false,
        });
        isGeneratingThumbs = false;
      });
      break;
    }
    default:
      return false;
    }
  });
}

init();
<commit_msg>speeding up showing the worker window for PDFs<commit_after>/**
 * TagSpaces - universal file and folder organizer
 * Copyright (C) 2017-present TagSpaces UG (haftungsbeschraenkt)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License (version 3) as
 * published by the Free Software Foundation.
 *
 * 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 <https://www.gnu.org/licenses/>.
 *
 * @flow
 */

import { ipcRenderer } from 'electron';
import { walkDirectory, enhanceEntry } from './services/utils-io';
import AppConfig from './config';
import { getThumbnailURLPromise } from './services/thumbsgenerator';

let isGeneratingThumbs = false;

function init() {
  console.log('Init worker');
  ipcRenderer.on('worker', (event, arg) => {
    // console.log('worker received: ' + JSON.stringify(arg));
    switch (arg.action) {
    case 'createDirectoryIndex': {
      console.log('createDirectoryIndex started in worker window');
      console.time('createDirectoryIndex');
      const directoryIndex = [];
      let counter = 0;
      walkDirectory(arg.path, {
        recursive: true,
        skipMetaFolder: true,
        skipDotHiddenFolder: true,
        extractText: arg.extractText
      }, (fileEntry) => {
        counter += 1;
        if (counter > AppConfig.indexerLimit) {
          console.warn('Walk canceled by ' + AppConfig.indexerLimit);
          window.walkCanceled = true;
        }
        directoryIndex.push(enhanceEntry(fileEntry));
      }, (directoryEntry) => {
        if (directoryEntry.name !== AppConfig.metaFolder) {
          counter += 1;
          directoryIndex.push(enhanceEntry(directoryEntry));
        }
      }).then(() => { // entries - can be used for further processing
        window.walkCanceled = false;
        console.log('Directory index created ' + arg.path + ' containing ' + directoryIndex.length);
        console.timeEnd('createDirectoryIndex');
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: directoryIndex,
          error: ''
        });
        return true;
      }).catch((err) => {
        window.walkCanceled = false;
        console.timeEnd('createDirectoryIndex');
        console.warn('Error creating index: ' + err);
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: [], // directoryIndex,
          error: err
        });
      });
      break;
    }
    case 'createThumbnails': {
      console.log('createThumbnails started in worker window');
      if (!arg.tmbGenerationList || arg.tmbGenerationList.length < 1 || isGeneratingThumbs) {
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: [],
          error: 'Empty or not available tmb list or busy worker'
        });
        break;
      }
      isGeneratingThumbs = true;
      const tmbGenerationPromises = [];
      let splashShown = false;
      arg.tmbGenerationList.map(entry => {
        if (!splashShown && entry.endsWith('pdf')) {
          splashShown = true;
          ipcRenderer.send('setSplashVisibility', {
            visibility: true,
          });
        }
        tmbGenerationPromises.push(getThumbnailURLPromise(entry));
        return true;
      });
      Promise.all(tmbGenerationPromises).then(tmbResult => {
        console.log('tmb results' + JSON.stringify(tmbResult));
        ipcRenderer.send('setSplashVisibility', {
          visibility: false,
        });
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: tmbResult,
          error: ''
        });
        isGeneratingThumbs = false;
        return true;
      }).catch(error => {
        console.warn('Tmb generation failed: ' + error);
        ipcRenderer.send('worker', {
          id: arg.id,
          action: arg.action,
          result: [],
          error: 'Error generating thumbnails: ' + error
        });
        ipcRenderer.send('setSplashVisibility', {
          visibility: false,
        });
        isGeneratingThumbs = false;
      });
      break;
    }
    default:
      return false;
    }
  });
}

init();
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import UploaderInput from "./Components/UploaderInput"
import UploaderOutput from "./Components/UploaderOutput"
import ImageUploader from "./Components/ImageUploader"

export default class App extends Component {

	constructor(props) {
		super(props);
		this.imageData = null;
		this.imageWidth = null;
		this.imageHeight = null;

		this.handleInputClick = this.handleInputClick.bind(this);
		this.handleOutputClick = this.handleOutputClick.bind(this);
		this.state = {
			outputSource: "#"
		}
	}

	getSinglePixelImage() {
		return this.getAveragePixel(0, 0, this.imageWidth, this.imageHeight);

	}

	handleInputClick(file) {
		// console.log("input clicked");
		// console.log("file",  file);
		const image = new Image();
		image.onload = () => {
			const canvas = document.createElement('canvas');
			canvas.width = image.width;
			canvas.height = image.height;

			this.imageWidth = canvas.width;
			this.imageHeight = canvas.height;

			const context = canvas.getContext('2d');
			context.drawImage(image, 0, 0);
			this.imageData = context.getImageData(0, 0, canvas.width, canvas.height);

			const newCanvas = document.createElement('canvas');
			const newContext = newCanvas.getContext('2d');
			newContext.putImageData(this.getPixels(3, 3, this.imageData.width, this.imageData.height), 0, 0);
			this.setState({outputSource: newCanvas.toDataURL("image/png")});
		};
		image.src = file;
		document.body.appendChild(image);
	}

	getPixels(numXBlocks, numYBlocks, xsize, ysize) {
		const blockWidth = Math.ceil(xsize / numXBlocks);
		const blockHeight = Math.ceil(ysize / numYBlocks);
		const colorArray = [];
		for (let y = 0; y < numYBlocks; y++) {
			for (let x = 0; x < numXBlocks; x++) {
				const result = this.getAveragePixel(x * blockWidth, y * blockHeight,
				Math.min((x + 1) * blockWidth, xsize), Math.min((y + 1) * blockHeight, ysize));

				colorArray.push(result.red);
				colorArray.push(result.green);
				colorArray.push(result.blue);
				colorArray.push(result.alpha);
			}
		}
		return new ImageData(Uint8ClampedArray.from(colorArray), numXBlocks, numYBlocks);
	}

	getPixelFromImage(x, y, imageData){
		const index = (y * imageData.width + x) * 4;
		const pixel = {
			red: imageData.data[index],
			green: imageData.data[index + 1],
			blue: imageData.data[index + 2],
			alpha: imageData.data[index + 3]
		};

		// console.log(`Pixel at: ${x},${y}: ${JSON.stringify(pixel)}`);
		return pixel
	}

	// Write an individual rgba pixel to an x,y coord in imageData
	writePixelToImageImage(x, y, imageData, r, g, b, a){
		const index = (y * imageData.width + x) * 4;
		imageData.data[index] = r;
		imageData.data[index + 1] = g;
 		imageData.data[index + 2] = b;
 		imageData.data[index + 3] = a;
	}

	// Write an rgba pixel to some span in imageData
	writeValueToImageSpan(start_x, start_y, end_x, end_y, r, g, b, a) {
		for (var m = start_y; m < end_y; m++){
			for (var n = start_x; n < end_x; n++) {
				this.writePixelToImageImage(n, m, this.imageData, r, g, b, a);
			}
		}
	}

	finishedInitialImageLoad() {
		var rgbImage = this.getSinglePixelImage();
		this.convertSingleRGBToImage(rgbImage);
	}

	convertSingleRGBToImage(image) {
		console.log(`Converting Image ${JSON.stringify(image)}`);
		this.writeValueToImageSpan(0, 0, this.imageWidth, this.imageHeight, image.red, image.green, image.blue, image.alpha);

		// Ok, so now this.imageData is all our new pixel. so i need to write that to a canvas, so i can get it in base64.

	}

	getAveragePixel(start_x, start_y, end_x, end_y) {
		let pixelCount = 0;
		let averagePixel = {
			red: 0,
			green: 0,
			blue: 0,
			alpha: 0
		};

		for (var i = start_y; i < end_y; i++){
			for (var j = start_x; j < end_x; j++) {
				pixelCount += 1;
				var pixel = this.getPixelFromImage(j, i, this.imageData);
				averagePixel.red += pixel.red;
				averagePixel.green += pixel.green;
				averagePixel.blue += pixel.blue;
				averagePixel.alpha += pixel.alpha;
			}
		}

		averagePixel.red = averagePixel.red / pixelCount;
		averagePixel.green = averagePixel.green / pixelCount;
		averagePixel.blue = averagePixel.blue / pixelCount;
		averagePixel.alpha = averagePixel.alpha / pixelCount;

		return averagePixel;
	}

	handleOutputClick() {
		// console.log("Output clicked");
	}

  	render() {
	    return (

Excellent Image Compressor

compress photos down to 1 bit

						Quickly and securely compress GIGABYTES of photos down to bytes or less.

						With our revolutionary one-way compression technology, you get state of the art security while using minimal disk space.

						Safely share pictures with your friends, without worying about state sponsored hackers or foreign nationalists.

						Upload your image in the box below, select how much you want to compress your image, and watch the magic happen.
						In one click, either download your newly compressed image, or upload to our site to share with friends.

							<ImageUploader onClick={this.handleInputClick}/>

							<UploaderOutput source={this.state.outputSource} onClick={this.handleOutputClick} />

	    );
	}
}
<commit_msg>OMG IT WORKS<commit_after>import React, { Component } from 'react';
import UploaderInput from "./Components/UploaderInput"
import UploaderOutput from "./Components/UploaderOutput"
import ImageUploader from "./Components/ImageUploader"

export default class App extends Component {

	constructor(props) {
		super(props);
		this.imageData = null;
		this.imageWidth = null;
		this.imageHeight = null;

		this.handleInputClick = this.handleInputClick.bind(this);
		this.handleOutputClick = this.handleOutputClick.bind(this);
		this.state = {
			outputSource: "#"
		}
	}

	getSinglePixelImage() {
		return this.getAveragePixel(0, 0, this.imageWidth, this.imageHeight);

	}

	handleInputClick(file) {
		// console.log("input clicked");
		// console.log("file",  file);
		const image = new Image();
		image.onload = () => {
			const canvas = document.createElement('canvas');
			canvas.width = image.width;
			canvas.height = image.height;

			this.imageWidth = canvas.width;
			this.imageHeight = canvas.height;

			const context = canvas.getContext('2d');
			context.drawImage(image, 0, 0);
			this.imageData = context.getImageData(0, 0, canvas.width, canvas.height);

			const newCanvas = document.createElement('canvas');
			const newContext = newCanvas.getContext('2d');
			// newContext.putImageData(this.getPixels(3, 3, this.imageData.width, this.imageData.height), 0, 0);
			this.finishedInitialImageLoad(); // Once this fires, this.imageData should hold the new imageData
			newContext.putImageData(this.imageData, 0, 0);
			this.setState({outputSource: newCanvas.toDataURL("image/png")});
		};
		image.src = file;
		document.body.appendChild(image);
	}

	getPixels(numXBlocks, numYBlocks, xsize, ysize) {
		const blockWidth = Math.ceil(xsize / numXBlocks);
		const blockHeight = Math.ceil(ysize / numYBlocks);
		const colorArray = [];
		for (let y = 0; y < numYBlocks; y++) {
			for (let x = 0; x < numXBlocks; x++) {
				const result = this.getAveragePixel(x * blockWidth, y * blockHeight,
				Math.min((x + 1) * blockWidth, xsize), Math.min((y + 1) * blockHeight, ysize));

				colorArray.push(result.red);
				colorArray.push(result.green);
				colorArray.push(result.blue);
				colorArray.push(result.alpha);
			}
		}
		return new ImageData(Uint8ClampedArray.from(colorArray), numXBlocks, numYBlocks);
	}

	getPixelFromImage(x, y, imageData){
		const index = (y * imageData.width + x) * 4;
		const pixel = {
			red: imageData.data[index],
			green: imageData.data[index + 1],
			blue: imageData.data[index + 2],
			alpha: imageData.data[index + 3]
		};

		// console.log(`Pixel at: ${x},${y}: ${JSON.stringify(pixel)}`);
		return pixel
	}

	// Write an individual rgba pixel to an x,y coord in imageData
	writePixelToImageImage(x, y, imageData, r, g, b, a){
		const index = (y * imageData.width + x) * 4;
		imageData.data[index] = r;
		imageData.data[index + 1] = g;
 		imageData.data[index + 2] = b;
 		imageData.data[index + 3] = a;
	}

	// Write an rgba pixel to some span in imageData
	writeValueToImageSpan(start_x, start_y, end_x, end_y, r, g, b, a) {
		for (var m = start_y; m < end_y; m++){
			for (var n = start_x; n < end_x; n++) {
				this.writePixelToImageImage(n, m, this.imageData, r, g, b, a);
			}
		}
	}

	finishedInitialImageLoad() {
		var rgbImage = this.getSinglePixelImage();
		this.convertSingleRGBToImage(rgbImage);
	}

	convertSingleRGBToImage(image) {
		console.log(`Converting Image ${JSON.stringify(image)}`);
		this.writeValueToImageSpan(0, 0, this.imageWidth, this.imageHeight, image.red, image.green, image.blue, image.alpha);

		// Ok, so now this.imageData is all our new pixel. so i need to write that to a canvas, so i can get it in base64.

	}

	getAveragePixel(start_x, start_y, end_x, end_y) {
		let pixelCount = 0;
		let averagePixel = {
			red: 0,
			green: 0,
			blue: 0,
			alpha: 0
		};

		for (var i = start_y; i < end_y; i++){
			for (var j = start_x; j < end_x; j++) {
				pixelCount += 1;
				var pixel = this.getPixelFromImage(j, i, this.imageData);
				averagePixel.red += pixel.red;
				averagePixel.green += pixel.green;
				averagePixel.blue += pixel.blue;
				averagePixel.alpha += pixel.alpha;
			}
		}

		averagePixel.red = averagePixel.red / pixelCount;
		averagePixel.green = averagePixel.green / pixelCount;
		averagePixel.blue = averagePixel.blue / pixelCount;
		averagePixel.alpha = averagePixel.alpha / pixelCount;

		return averagePixel;
	}

	handleOutputClick() {
		// console.log("Output clicked");
	}

  	render() {
	    return (

Excellent Image Compressor

compress photos down to 1 bit

						Quickly and securely compress GIGABYTES of photos down to bytes or less.

						With our revolutionary one-way compression technology, you get state of the art security while using minimal disk space.

						Safely share pictures with your friends, without worying about state sponsored hackers or foreign nationalists.

						Upload your image in the box below, select how much you want to compress your image, and watch the magic happen.
						In one click, either download your newly compressed image, or upload to our site to share with friends.

							<ImageUploader onClick={this.handleInputClick}/>

							<UploaderOutput source={this.state.outputSource} onClick={this.handleOutputClick} />

	    );
	}
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import {useEffect} from 'react'
import {form} from 'tocco-app-extensions'
import EntityBrowserApp from 'tocco-entity-browser/src/main'
import {LoadMask} from 'tocco-ui'
import {appContext as appContextPropType} from 'tocco-util'

const WageView = ({
  loadReports,
  reports,
  allowCreate,
  reportIds,
  searchFilters,
  limit,
  intl,
  backendUrl,
  businessUnit,
  appContext
}) => {
  useEffect(() => {
    loadReports(reportIds)
  }, [loadReports, reportIds])

  const modifyFormDefinition = formDefinition => {
    if (!allowCreate) {
      formDefinition = form.removeCreate(formDefinition)
    }

    if (reports.length > 0) {
      formDefinition = form.addReports(formDefinition, reports, intl)
    }

    return formDefinition
  }

  return (
    <LoadMask required={[reports]}>
      <EntityBrowserApp
        entityName="Wage"
        formBase="WageView"
        searchFilters={searchFilters}
        limit={limit}
        modifyFormDefinition={modifyFormDefinition}
        backendUrl={backendUrl}
        businessUnit={businessUnit}
        appContext={appContext}
      />
    </LoadMask>
  )
}

WageView.propTypes = {
  loadReports: PropTypes.func.isRequired,
  reports: PropTypes.arrayOf(PropTypes.object),
  allowCreate: PropTypes.bool,
  reportIds: PropTypes.arrayOf(PropTypes.string).isRequired,
  searchFilters: PropTypes.arrayOf(PropTypes.string),
  limit: PropTypes.number,
  intl: PropTypes.object.isRequired,
  backendUrl: PropTypes.string,
  businessUnit: PropTypes.string,
  appContext: appContextPropType.propTypes.isRequired
}

export default WageView
<commit_msg>fix(wage-view): adjust form base<commit_after>import PropTypes from 'prop-types'
import {useEffect} from 'react'
import {form} from 'tocco-app-extensions'
import EntityBrowserApp from 'tocco-entity-browser/src/main'
import {LoadMask} from 'tocco-ui'
import {appContext as appContextPropType} from 'tocco-util'

const WageView = ({
  loadReports,
  reports,
  allowCreate,
  reportIds,
  searchFilters,
  limit,
  intl,
  backendUrl,
  businessUnit,
  appContext
}) => {
  useEffect(() => {
    loadReports(reportIds)
  }, [loadReports, reportIds])

  const modifyFormDefinition = formDefinition => {
    if (!allowCreate) {
      formDefinition = form.removeCreate(formDefinition)
    }

    if (reports.length > 0) {
      formDefinition = form.addReports(formDefinition, reports, intl)
    }

    return formDefinition
  }

  return (
    <LoadMask required={[reports]}>
      <EntityBrowserApp
        entityName="Wage"
        formBase="Wage_view"
        searchFilters={searchFilters}
        limit={limit}
        modifyFormDefinition={modifyFormDefinition}
        backendUrl={backendUrl}
        businessUnit={businessUnit}
        appContext={appContext}
      />
    </LoadMask>
  )
}

WageView.propTypes = {
  loadReports: PropTypes.func.isRequired,
  reports: PropTypes.arrayOf(PropTypes.object),
  allowCreate: PropTypes.bool,
  reportIds: PropTypes.arrayOf(PropTypes.string).isRequired,
  searchFilters: PropTypes.arrayOf(PropTypes.string),
  limit: PropTypes.number,
  intl: PropTypes.object.isRequired,
  backendUrl: PropTypes.string,
  businessUnit: PropTypes.string,
  appContext: appContextPropType.propTypes.isRequired
}

export default WageView
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.util.linefeed = '\n';

    var options = {
        sourcemap: {
            css: false,
            js: false
        },
        path: {
            tmp: 'tmp',
            pages: 'tmp/pages',
            doc: {
                js: 'docs/js',
                php: 'docs/php'
            },
            src: {
                js: 'js',
                lib: 'lib',
                sass: 'sass',
                node: 'node_modules',
                bower: 'bower_components'
            },
            dest: {
                js: '../view/js',
                fonts: '../view/fonts',
                img: '../view/img',
                css: '../view/css'
            }
        },

        files: {
            boltJs: [
                // Prerequisites
                '<%= path.src.js %>/console.js',
                '<%= path.src.js %>/class-extends.js',
                // Bolt module
                '<%= path.src.js %>/bolt.js',
                '<%= path.src.js %>/modules/actions.js',
                '<%= path.src.js %>/modules/activity.js',
                '<%= path.src.js %>/modules/app.js',
                '<%= path.src.js %>/modules/ckeditor.js',
                '<%= path.src.js %>/modules/conf.js',
                '<%= path.src.js %>/modules/data.js',
                '<%= path.src.js %>/modules/datetime.js',
                '<%= path.src.js %>/modules/editcontent.js',
                '<%= path.src.js %>/modules/files.js',
                '<%= path.src.js %>/modules/liveeditor.js',
                '<%= path.src.js %>/modules/stack.js',
                '<%= path.src.js %>/modules/secmenu.js',
                '<%= path.src.js %>/modules/video.js',
                '<%= path.src.js %>/modules/fields.js',
                '<%= path.src.js %>/modules/fields/geolocation.js',
                '<%= path.src.js %>/modules/fields/slug.js',
                // Old stuff
                '<%= path.src.js %>/fnc-helpers.js',
                '<%= path.src.js %>/activity.js',
                '<%= path.src.js %>/bind-fileupload.js',
                '<%= path.src.js %>/make-uri-slug.js',
                '<%= path.src.js %>/video-embed.js',
                '<%= path.src.js %>/upload-files.js',
                '<%= path.src.js %>/obj-moments.js',
                '<%= path.src.js %>/obj-datetime.js',
                '<%= path.src.js %>/obj-validation.js',
                '<%= path.src.js %>/extend.js',
                '<%= path.src.js %>/init.js'
            ]
        },

        banner: {
            boltJs: [
                '/**',
                ' * These are Bolt’s COMPILED JS files!',
                ' * You can edit *.js files in /app/src/js/ and then run "grunt updateBolt" to generate this file.',
                ' */'
            ].join('\n'),
            boltCss: [
                '/**',
                ' * These are Bolt’s COMPILED CSS files!',
                ' * Do not edit these files, because all changes will be lost.',
                ' * You can edit *.scss files in /app/src/scss/ and then run "grunt updateBolt" to generate this file.',
                ' */'
            ].join('\n')
        }
    };

    // Optionally overwrite options with grunt-local/*.js
    var path = require('path'),
        localOptions = {};

    grunt.file.expand('./grunt-local/*.js').map(function (confPath) {
        grunt.verbose.writeln('Load local options "' + confPath + '"');
        localOptions[path.basename(confPath, '.js')] = require(confPath);
    });
    require('deep-extend')(options, localOptions);

    // Start
    require('load-grunt-config')(grunt, {
        data: options,
        jitGrunt: {
            staticMappings: {
                pages: 'grunt-tasks/pages.js',
                htmllint: 'grunt-html'
            }
        }
    });
};
<commit_msg>Remove path.src.node - not needed anymore as all resources are in path.src.bower<commit_after>module.exports = function(grunt) {
    grunt.util.linefeed = '\n';

    var options = {
        sourcemap: {
            css: false,
            js: false
        },
        path: {
            tmp: 'tmp',
            pages: 'tmp/pages',
            doc: {
                js: 'docs/js',
                php: 'docs/php'
            },
            src: {
                js: 'js',
                lib: 'lib',
                sass: 'sass',
                bower: 'bower_components'
            },
            dest: {
                js: '../view/js',
                fonts: '../view/fonts',
                img: '../view/img',
                css: '../view/css'
            }
        },

        files: {
            boltJs: [
                // Prerequisites
                '<%= path.src.js %>/console.js',
                '<%= path.src.js %>/class-extends.js',
                // Bolt module
                '<%= path.src.js %>/bolt.js',
                '<%= path.src.js %>/modules/actions.js',
                '<%= path.src.js %>/modules/activity.js',
                '<%= path.src.js %>/modules/app.js',
                '<%= path.src.js %>/modules/ckeditor.js',
                '<%= path.src.js %>/modules/conf.js',
                '<%= path.src.js %>/modules/data.js',
                '<%= path.src.js %>/modules/datetime.js',
                '<%= path.src.js %>/modules/editcontent.js',
                '<%= path.src.js %>/modules/files.js',
                '<%= path.src.js %>/modules/liveeditor.js',
                '<%= path.src.js %>/modules/stack.js',
                '<%= path.src.js %>/modules/secmenu.js',
                '<%= path.src.js %>/modules/video.js',
                '<%= path.src.js %>/modules/fields.js',
                '<%= path.src.js %>/modules/fields/geolocation.js',
                '<%= path.src.js %>/modules/fields/slug.js',
                // Old stuff
                '<%= path.src.js %>/fnc-helpers.js',
                '<%= path.src.js %>/activity.js',
                '<%= path.src.js %>/bind-fileupload.js',
                '<%= path.src.js %>/make-uri-slug.js',
                '<%= path.src.js %>/video-embed.js',
                '<%= path.src.js %>/upload-files.js',
                '<%= path.src.js %>/obj-moments.js',
                '<%= path.src.js %>/obj-datetime.js',
                '<%= path.src.js %>/obj-validation.js',
                '<%= path.src.js %>/extend.js',
                '<%= path.src.js %>/init.js'
            ]
        },

        banner: {
            boltJs: [
                '/**',
                ' * These are Bolt’s COMPILED JS files!',
                ' * You can edit *.js files in /app/src/js/ and then run "grunt updateBolt" to generate this file.',
                ' */'
            ].join('\n'),
            boltCss: [
                '/**',
                ' * These are Bolt’s COMPILED CSS files!',
                ' * Do not edit these files, because all changes will be lost.',
                ' * You can edit *.scss files in /app/src/scss/ and then run "grunt updateBolt" to generate this file.',
                ' */'
            ].join('\n')
        }
    };

    // Optionally overwrite options with grunt-local/*.js
    var path = require('path'),
        localOptions = {};

    grunt.file.expand('./grunt-local/*.js').map(function (confPath) {
        grunt.verbose.writeln('Load local options "' + confPath + '"');
        localOptions[path.basename(confPath, '.js')] = require(confPath);
    });
    require('deep-extend')(options, localOptions);

    // Start
    require('load-grunt-config')(grunt, {
        data: options,
        jitGrunt: {
            staticMappings: {
                pages: 'grunt-tasks/pages.js',
                htmllint: 'grunt-html'
            }
        }
    });
};
<|endoftext|>


<commit_before>if (!process.env.token) {
	console.log('Error: Specify token in environment');
    process.exit(1);
}

var Botkit = require('./lib/Botkit.js');
var os = require('os');

var controller = Botkit.slackbot({
	json_file_store: '/home/steef/botkit/storage',
	debug: false,
});

var bot = controller.spawn({
    token: process.env.token
}).startRTM();

controller.hears(['hello','hi','hoi','hallo','dag','hey'],'direct_message,direct_mention,mention',function(bot, message) {
    bot.api.reactions.add({
        timestamp: message.ts,
        channel: message.channel,
        name: 'robot_face',
    },function(err, res) {
        if (err) {
            bot.botkit.log('Failed to add emoji reaction :(',err);
        }
    });
    controller.storage.users.get(message.user,function(err, user) {
        if (user && user.name) {
            bot.reply(message,'Hoi ' + user.name + '!!');
        } else {
            bot.reply(message,'Hoi');
        }
    });
});

controller.hears(['noem me (.*)'],'direct_message,direct_mention,mention',function(bot, message) {
    var matches = message.text.match(/noem me (.*)/i);
    var name = matches[1];
    controller.storage.users.get(message.user,function(err, user) {
        if (!user) {
            user = {
                id: message.user,
            };
        }
        user.name = name;
        controller.storage.users.save(user,function(err, id) {
            bot.reply(message,'Prima, vanaf nu zal ik je ' + user.name + ' noemen.');
        });
    });
});

controller.hears(['what is my name','who am i','wie ben ik','hoe heet ik','wat is mijn naam'],'direct_message,direct_mention,mention',function(bot, message) {
    controller.storage.users.get(message.user,function(err, user) {
        if (user && user.name) {
            bot.reply(message,'Jouw naam is ' + user.name);
        } else {
            bot.reply(message,'Ik ken jou nog niet!');
        }
    });
});

controller.hears(['help'],'direct_message,direct_mention',function(bot, message){
	bot.startConversation(message,helpMe);
});
helpMe = function(response,convo){
	convo.ask('Ik kan helpen met de "takenlijst" en onthouden van "namen"',function(response,convo){
		if(response.text == "Takenlijst" || response.text == "takenlijst"){
			helpWithTakenlijst(response,convo);
		}else if (response.text == "Namen" || response.text == "namen"){
			helpWithNamen(response,convo);
		}else{
			bot.reply(response,"Sorry, daar kan ik je niet mee helpen");
			convo.stop();
		}
	});
}
helpWithTakenlijst = function(response,convo){
	bot.reply(response,'Vraag me om een taak toe te voegen, dan voeg ik het toe aan de takenlijst van het kanaal waar we op dat moment in zitten.\nAls je me om de lijst vraagt, zal ik je deze geven.\nVraag me om een taak af te ronden of af te vinken dan haal ik deze van de lijst af.');
	convo.stop();
}
helpWithNamen = function(response,convo){
	bot.reply(response,"Vertel me hoe ik je moet noemen, dan kan ik die naam in de toekomst gebruiken om te weten wie er bedoeld wordt. (bijv. noem me Elsje.)");
	convo.stop();
}

controller.hears(['shutdown'],'direct_message,direct_mention,mention',function(bot, message) {
    bot.startConversation(message,function(err, convo) {
        convo.ask('Are you sure you want me to shutdown?',[
            {
                pattern: bot.utterances.yes,
                callback: function(response, convo) {
                    convo.say('Bye!');
                    convo.next();
                    setTimeout(function() {
                        process.exit();
                    },3000);
                }
            },
        {
            pattern: bot.utterances.no,
            default: true,
            callback: function(response, convo) {
                convo.say('*Phew!*');
                convo.next();
            }
        }
        ]);
    });
});

controller.hears(['ken ik jou','wie ben jij','hoe lang ben je al wakker','uptime','identify yourself','who are you','what is your name'],'direct_message,direct_mention,mention,ambient',function(bot, message) {
    var hostname = os.hostname();
    var uptime = formatUptime(process.uptime());
    bot.reply(message,':robot_face: Ik ben een bot genaamd <@' + bot.identity.name + '>. Ik draai al  ' + uptime + ' op  ' + hostname + '.');
});

function formatUptime(uptime) {
    var unit = 'seconden';
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'minuten';
    }
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'uren';
    }
    uptime = Math.round(uptime*10)/10 + ' ' + unit;
    return uptime;
}

controller.hears(['takenlijst','lijst'],'mention,direct_mention,direct_message,ambient',function(bot,message){
	if(message.event!="direct_message"){
		showTaskList(message);
	}else{
		bot.reply(message,"Sorry, vraag dit in een kanaal.")
	}
});

controller.hears(['nieuwe taak','voeg toe','taak (.*)voegen'],'direct_mention,mention,direct_message,ambient',function(bot,message){
	bot.startConversation(message,voegTaakToe);
});
voegTaakToe = function(response, convo){
	convo.ask("Wat moet er gedaan worden?",function(response,convo){
		convo.say("Ja, dat moet nodig gebeuren.");
		voorWie(response,convo);
		convo.next();
	});
}
voorWie = function(reponse,convo){
	convo.ask("Wie gaat dit doen?", function(response,convo){
		convo.say("Ha, gesjaakt!");
		wanneerKlaar(response,convo);
		convo.next();
	});
}
wanneerKlaar = function(response,convo){
	convo.ask("Wanneer moet het klaar zijn?",function(response,convo){
		var datetext = response.text;
		datetext = datetext.replace(/-/g,"/");
		var split = datetext.split('/');
		if(typeof split[1] != "undefined" && typeof split[2] != "undefined"){
			datetext = split[1]+'/'+split[0]+'/'+split[2];
		}
		datetext = datetext.replace("maa","mar");
		datetext = datetext.replace("mei","may");
		datetext = datetext.replace("okt","oct");
		console.log(datetext);
		var date = new Date(Date.parse(datetext));
		date.setDate(date.getDate() + 1);
		if(date != "Invalid Date" && date.getTime()>1420070400000){
			response.text = date;
			convo.say("Ik zal het onthouden.");
			if(convo.task.source_message.event=="direct_message"){
				welkKanaal(response,convo);
				convo.next();
			}else{
				opslaanVanTaak(response,convo);
				convo.next();
			}
		}
	});
}
welkKanaal = function(response,convo){
	convo.ask("In welke lijst zal ik dit zetten?",function(response,convo){
		if(true){ //check if input is existing channel
			opslaanVanTaak(response,convo);
			convo.next();
		}
	});
}
opslaanVanTaak = function(response,convo){
	convo.on('end',function(convo){
		if(convo.status=='completed'){
			var res = convo.extractResponses();
			if(res['In welke lijst zal ik dit zetten?']){
					console.log(res['In welke lijst zal ik dit zetten?'].substr(2,9));
					response.channel = res['In welke lijst zal ik dit zetten?'].substr(2,9);
			}
			controller.storage.channels.get(response.channel, function(err, channel_data){
				var list = channel_data;
				list['tasks'].push({
					taskid: list['tasks'].length+1,
					user: response.user,
					task: res['Wat moet er gedaan worden?'],
					responsible: res['Wie gaat dit doen?'],
					deadline: res['Wanneer moet het klaar zijn?'],
					status: "new",
				});
				controller.storage.channels.save({
					id: response.channel,
					tasks: list['tasks'],
				});
			});
			bot.reply(response,"Ok, taak toegevoegd aan de lijst.");
		}else{
			bot.reply(response,"Sorry, ik heb iets niet begrepen, probeer het nog een keer.");
		}
	});
}

showTaskList = function(message){
	controller.storage.channels.get(message.channel,function(err,channel_data){
		var string = "\nTakenlijst van <#"+channel_data.id+">\n```";
		channel_data['tasks'].forEach(function(value,index,array){
			var addtostring ="";
			var deadline = new Date(value.deadline);
			if(value.status != "done"){
				addtostring = 	value.taskid+
						addSpaces(4-value.taskid.toString().length)+
						value.responsible+
						addSpaces(15-value.responsible.length)+
						deadline.toUTCString().substr(5,11)+
						addSpaces(3)+
						value.task+
						"\n";
			}
			return string+=addtostring;
		});
		bot.reply(message,string+"```");
	});

}
addSpaces = function(numberOfSpaces){
	var spaces = "";
	for(i=0; i<numberOfSpaces;i++){
		spaces+=" ";
	}
	return spaces;
}

controller.hears(['taak (.*)afronden','taak (.*)afvinken','ik ben klaar','taak (.*)gedaan'],'direct_mention,mention,direct_message,ambient',function(bot,message){
	console.log(message);
	bot.startConversation(message,completeTask);
});
completeTask = function(response,convo){
	showTaskList(convo.source_message);
	convo.ask("Kan je mij het nummer geven van de taak die van de lijst af mag?",function(response,convo){
		console.log(response.text);
		console.log(parseInt(response.text));
		if(!isNaN(parseInt(response.text))){
			convo.say("BAM, weer wat gedaan. Goed werk <@"+response.user+">.\n");
			TaskDone(response,convo);
			convo.next();
		}
	});
}
TaskDone = function(response,convo){
	convo.on('end',function(convo){
		if(convo.status=='completed'){
			var res = convo.extractResponses();
			var number = parseInt(res['Kan je mij het nummer geven van de taak die van de lijst af mag?']);
	        controller.storage.channels.get(response.channel, function(err, channel_data){
				channel_data['tasks'].forEach(function(value,index,array){
					if(value.taskid == number){
						value.status = "done";
						console.log("changed to done");
					}
				});
				controller.storage.channels.save(channel_data);
			});
	        bot.reply(response,"Ok, verwijderd van de lijst.");
		}else{
			bot.reply(response,"Sorry, ik heb iets niet begrepen, probeer het nog een keer.");
		}
	});
}
<commit_msg>spaces cleanup<commit_after>if (!process.env.token) {
	console.log('Error: Specify token in environment');
    process.exit(1);
}

var Botkit = require('./lib/Botkit.js');
var os = require('os');

var controller = Botkit.slackbot({
	json_file_store: '/home/steef/botkit/storage',
	debug: true,
});

var bot = controller.spawn({
    token: process.env.token
}).startRTM();

controller.on('rtm_close', function(bot,message){
	bot.reply(message,"Ik ga slapen");
	bot.startRTM();
});

controller.hears(['hello','hi','hoi','hallo','dag','hey'],'direct_message,direct_mention,mention',function(bot, message) {
    bot.api.reactions.add({
        timestamp: message.ts,
        channel: message.channel,
        name: 'robot_face',
    },function(err, res) {
        if (err) {
            bot.botkit.log('Failed to add emoji reaction :(',err);
        }
    });
    controller.storage.users.get(message.user,function(err, user) {
        if (user && user.name) {
            bot.reply(message,'Hoi ' + user.name + '!!');
        } else {
            bot.reply(message,'Hoi');
        }
    });
});

controller.hears(['noem me (.*)'],'direct_message,direct_mention,mention',function(bot, message) {
    var matches = message.text.match(/noem me (.*)/i);
    var name = matches[1];
    controller.storage.users.get(message.user,function(err, user) {
        if (!user) {
            user = {
                id: message.user,
            };
        }
        user.name = name;
        controller.storage.users.save(user,function(err, id) {
            bot.reply(message,'Prima, vanaf nu zal ik je ' + user.name + ' noemen.');
        });
    });
});

controller.hears(['what is my name','who am i','wie ben ik','hoe heet ik','wat is mijn naam'],'direct_message,direct_mention,mention',function(bot, message) {
    controller.storage.users.get(message.user,function(err, user) {
        if (user && user.name) {
            bot.reply(message,'Jouw naam is ' + user.name);
        } else {
            bot.reply(message,'Ik ken jou nog niet!');
        }
    });
});

controller.hears(['help'],'direct_message,direct_mention',function(bot, message){
	bot.startConversation(message,helpMe);
});
helpMe = function(response,convo){
	convo.ask('Ik kan helpen met de "takenlijst" en onthouden van "namen"',function(response,convo){
		if(response.text == "Takenlijst" || response.text == "takenlijst"){
			helpWithTakenlijst(response,convo);
		}else if (response.text == "Namen" || response.text == "namen"){
			helpWithNamen(response,convo);
		}else{
			bot.reply(response,"Sorry, daar kan ik je niet mee helpen");
			convo.stop();
		}
	});
}
helpWithTakenlijst = function(response,convo){
	bot.reply(response,'Vraag me om een taak toe te voegen, dan voeg ik het toe aan de takenlijst van het kanaal waar we op dat moment in zitten.\nAls je me om de lijst vraagt, zal ik je deze geven.\nVraag me om een taak af te ronden of af te vinken dan haal ik deze van de lijst af.');
	convo.stop();
}
helpWithNamen = function(response,convo){
	bot.reply(response,"Vertel me hoe ik je moet noemen, dan kan ik die naam in de toekomst gebruiken om te weten wie er bedoeld wordt. (bijv. noem me Elsje.)");
	convo.stop();
}

controller.hears(['shutdown'],'direct_message,direct_mention,mention',function(bot, message) {
	bot.startConversation(message,function(err, convo) {
		convo.ask('Are you sure you want me to shutdown?',[
			{
				pattern: bot.utterances.yes,
				callback: function(response, convo) {
					convo.say('Bye!');
					convo.next();
					setTimeout(function() {
						process.exit();
					},3000);
				}
			},
			{
				pattern: bot.utterances.no,
				default: true,
				callback: function(response, convo) {
					convo.say('*Phew!*');
					convo.next();
				}
			}
		]);
	});
});

controller.hears(['ken ik jou','wie ben jij','hoe lang ben je al wakker','uptime','identify yourself','who are you','what is your name'],'direct_message,direct_mention,mention,ambient',function(bot, message) {
	var hostname = os.hostname();
	var uptime = formatUptime(process.uptime());
	bot.reply(message,':robot_face: Ik ben een bot genaamd <@' + bot.identity.name + '>. Ik draai al  ' + uptime + ' op  ' + hostname + '.');
});

function formatUptime(uptime) {
	var unit = 'seconden';
	if (uptime > 60) {
		uptime = uptime / 60;
		unit = 'minuten';
	}
	if (uptime > 60) {
		uptime = uptime / 60;
		unit = 'uren';
	}
	uptime = Math.round(uptime) + ' ' + unit;
	return uptime;
}

controller.hears(['takenlijst','lijst'],'mention,direct_mention,direct_message,ambient',function(bot,message){
	if(message.event!="direct_message"){
		showTaskList(message);
	}else{
		bot.reply(message,"Sorry, vraag dit in een kanaal.")
	}
});

controller.hears(['nieuwe taak','voeg toe','taak (.*)voegen'],'direct_mention,mention,direct_message,ambient',function(bot,message){
	bot.startConversation(message,voegTaakToe);
});
voegTaakToe = function(response, convo){
	convo.ask("Wat moet er gedaan worden?",function(response,convo){
		convo.say("Ja, dat moet nodig gebeuren.");
		voorWie(response,convo);
		convo.next();
	});
}
voorWie = function(reponse,convo){
	convo.ask("Wie gaat dit doen?", function(response,convo){
		convo.say("Ha, gesjaakt!");
		wanneerKlaar(response,convo);
		convo.next();
	});
}
wanneerKlaar = function(response,convo){
	convo.ask("Wanneer moet het klaar zijn?",function(response,convo){
		var datetext = response.text;
		datetext = datetext.replace(/-/g,"/");
		var split = datetext.split('/');
		if(typeof split[1] != "undefined" && typeof split[2] != "undefined"){
			datetext = split[1]+'/'+split[0]+'/'+split[2];
		}
		datetext = datetext.replace("maa","mar");
		datetext = datetext.replace("mei","may");
		datetext = datetext.replace("okt","oct");
		console.log(datetext);
		var date = new Date(Date.parse(datetext));
		date.setDate(date.getDate() + 1);
		if(date != "Invalid Date" && date.getTime()>1420070400000){
			response.text = date;
			convo.say("Ik zal het onthouden.");
			if(convo.task.source_message.event=="direct_message"){
				welkKanaal(response,convo);
				convo.next();
			}else{
				opslaanVanTaak(response,convo);
				convo.next();
			}
		}
	});
}
welkKanaal = function(response,convo){
	convo.ask("In welke lijst zal ik dit zetten?",function(response,convo){
		if(true){ //check if input is existing channel
			opslaanVanTaak(response,convo);
			convo.next();
		}
	});
}
opslaanVanTaak = function(response,convo){
	convo.on('end',function(convo){
		if(convo.status=='completed'){
			var res = convo.extractResponses();
			if(res['In welke lijst zal ik dit zetten?']){
					console.log(res['In welke lijst zal ik dit zetten?'].substr(2,9));
					response.channel = res['In welke lijst zal ik dit zetten?'].substr(2,9);
			}
			controller.storage.channels.get(response.channel, function(err, channel_data){
				var list = channel_data;
				list['tasks'].push({
					taskid: list['tasks'].length+1,
					user: response.user,
					task: res['Wat moet er gedaan worden?'],
					responsible: res['Wie gaat dit doen?'],
					deadline: res['Wanneer moet het klaar zijn?'],
					status: "new",
				});
				controller.storage.channels.save({
					id: response.channel,
					tasks: list['tasks'],
				});
			});
			bot.reply(response,"Ok, taak toegevoegd aan de lijst.");
		}else{
			bot.reply(response,"Sorry, ik heb iets niet begrepen, probeer het nog een keer.");
		}
	});
}

showTaskList = function(message){
	controller.storage.channels.get(message.channel,function(err,channel_data){
		var string = "\nTakenlijst van <#"+channel_data.id+">\n```";
		channel_data['tasks'].forEach(function(value,index,array){
			var addtostring ="";
			var deadline = new Date(value.deadline);
			if(value.status != "done"){
				addtostring = 	value.taskid+
						addSpaces(4-value.taskid.toString().length)+
						value.responsible+
						addSpaces(15-value.responsible.length)+
						deadline.toUTCString().substr(5,11)+
						addSpaces(3)+
						value.task+
						"\n";
			}
			return string+=addtostring;
		});
		bot.reply(message,string+"```");
	});

}
addSpaces = function(numberOfSpaces){
	var spaces = "";
	for(i=0; i<numberOfSpaces;i++){
		spaces+=" ";
	}
	return spaces;
}

controller.hears(['taak (.*)afronden','taak (.*)afvinken','ik ben klaar','taak (.*)gedaan'],'direct_mention,mention,direct_message,ambient',function(bot,message){
	console.log(message);
	bot.startConversation(message,completeTask);
});
completeTask = function(response,convo){
	showTaskList(convo.source_message);
	convo.ask("Kan je mij het nummer geven van de taak die van de lijst af mag?",function(response,convo){
		console.log(response.text);
		console.log(parseInt(response.text));
		if(!isNaN(parseInt(response.text))){
			convo.say("BAM, weer wat gedaan. Goed werk <@"+response.user+">.\n");
			TaskDone(response,convo);
			convo.next();
		}
	});
}
TaskDone = function(response,convo){
	convo.on('end',function(convo){
		if(convo.status=='completed'){
			var res = convo.extractResponses();
			var number = parseInt(res['Kan je mij het nummer geven van de taak die van de lijst af mag?']);
	        controller.storage.channels.get(response.channel, function(err, channel_data){
				channel_data['tasks'].forEach(function(value,index,array){
					if(value.taskid == number){
						value.status = "done";
						console.log("changed to done");
					}
				});
				controller.storage.channels.save(channel_data);
			});
	        bot.reply(response,"Ok, verwijderd van de lijst.");
		}else{
			bot.reply(response,"Sorry, ik heb iets niet begrepen, probeer het nog een keer.");
		}
	});
}
<|endoftext|>