<commit_before>/**
 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 * Application
 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute } from 'react-router';

import { doSetAuthSuccess } from 'modules/auth';
import { getAuthCookieStatus } from 'helpers/utils/cookie';

// container
import Layout from 'containers/Layout';

// components
import {
  Counter,
  Home,
  Json,
  Login,
} from 'components';

/**
 * Render application
 *
 * @param {string} mountNodeId - mount node id.
 * @param {object} store       - redux store.
 * @param {object} history     - react router history.
 */
export function renderApp(mountNodeId, store, history) {
  const mountNode = document.getElementById(mountNodeId);

  // don't do anything if mount node not found.
  if (!mountNode) {
    return null;
  }

  // initial app
  if (getAuthCookieStatus()) {
    store.dispatch(doSetAuthSuccess());
  }

  // render application
  ReactDOM.render(
    <Provider store={store}>
      <Router history={history}>
        <Route path="/login" component={Login} onEnter={onLoginEnter}></Route>
        <Route path="/" component={Layout} onEnter={onAppEnter}>
          <IndexRoute component={Home} />
          <Route path="counter" component={Counter}/>
          <Route path="json" component={Json}/>
        </Route>
      </Router>
    </Provider>,
    mountNode
  );

  function onLoginEnter(nextState, replace) {
    const { authenticated } = store.getState().auth;
    if (authenticated) {
      replace('/');
    }
  }

  function onAppEnter(nextState, replace) {
    const { authenticated } = store.getState().auth;
    if (!authenticated) {
      replace('/login');
    }
  }
}
<commit_msg>Add comment<commit_after>/**
 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 * Application
 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute } from 'react-router';

import { doSetAuthSuccess } from 'modules/auth';
import { getAuthCookieStatus } from 'helpers/utils/cookie';

// container
import Layout from 'containers/Layout';

// components
import {
  Counter,
  Home,
  Json,
  Login,
} from 'components';

/**
 * Render application
 *
 * @param {string} mountNodeId - mount node id.
 * @param {object} store       - redux store.
 * @param {object} history     - react router history.
 */
export function renderApp(mountNodeId, store, history) {
  const mountNode = document.getElementById(mountNodeId);

  // don't do anything if mount node not found.
  if (!mountNode) {
    return null;
  }

  // initial app
  if (getAuthCookieStatus()) {
    // found auth status, then set store for `authenticated`
    store.dispatch(doSetAuthSuccess());
  }

  // render application
  ReactDOM.render(
    <Provider store={store}>
      <Router history={history}>
        <Route path="/login" component={Login} onEnter={onLoginEnter}></Route>
        <Route path="/" component={Layout} onEnter={onAppEnter}>
          <IndexRoute component={Home} />
          <Route path="counter" component={Counter}/>
          <Route path="json" component={Json}/>
        </Route>
      </Router>
    </Provider>,
    mountNode
  );

  function onLoginEnter(nextState, replace) {
    const { authenticated } = store.getState().auth;
    if (authenticated) {
      replace('/');
    }
  }

  function onAppEnter(nextState, replace) {
    const { authenticated } = store.getState().auth;
    if (!authenticated) {
      replace('/login');
    }
  }
}
<|endoftext|>


<commit_before>const express = require('@feathersjs/express');
const feathers = require('@feathersjs/feathers');
const configuration = require('@feathersjs/configuration');
const apiMetrics = require('prometheus-api-metrics');
const path = require('path');
const favicon = require('serve-favicon');
const compress = require('compression');
const cors = require('cors');
const rest = require('@feathersjs/express/rest');
const bodyParser = require('body-parser');
const socketio = require('@feathersjs/socketio');
const { ObjectId } = require('mongoose').Types;

const { KEEP_ALIVE, BODYPARSER_JSON_LIMIT, METRICS_PATH, LEAD_TIME } = require('../config/globals');

const middleware = require('./middleware');
const sockets = require('./sockets');
const services = require('./services');

const defaultHeaders = require('./middleware/defaultHeaders');
const handleResponseType = require('./middleware/handleReponseType');
const requestLogger = require('./middleware/requestLogger');
const errorHandler = require('./middleware/errorHandler');
const sentry = require('./middleware/sentry');
const rabbitMq = require('./utils/rabbitmq');

const setupSwagger = require('./swagger');
const { initializeRedisClient } = require('./utils/redis');
const { setupAppHooks } = require('./app.hooks');
const versionService = require('./services/version');

const setupApp = async () => {
	const app = express(feathers());
	app.disable('x-powered-by');

	const config = configuration();
	app.configure(config);

	if (LEAD_TIME) {
		app.use((req, res, next) => {
			req.leadTime = Date.now();
			next();
		});
	}

	const metricsOptions = {};
	if (METRICS_PATH) {
		metricsOptions.metricsPath = METRICS_PATH;
	}
	app.use(apiMetrics(metricsOptions));

	setupSwagger(app);
	initializeRedisClient();
	rabbitMq.setup(app);

	// set custom response header for ha proxy
	if (KEEP_ALIVE) {
		app.use((req, res, next) => {
			res.setHeader('Connection', 'Keep-Alive');
			next();
		});
	}

<<<<<<< HEAD
	app
		.use(compress())
		.options('*', cors())
		.use(cors())
		.use(favicon(path.join(app.get('public'), 'favicon.ico')))
		.use('/', express.static('public'))
		.configure(sentry)
		.use('/helpdesk', bodyParser.json({ limit: BODYPARSER_JSON_LIMIT }))
		.use('/', bodyParser.json({ limit: '10mb' }))
		.use(bodyParser.urlencoded({ extended: true }))
		.use(bodyParser.raw({ type: () => true, limit: '10mb' }));

	await Promise.resolve(); // placeholder for initializing API validation
=======
app
	.use(compress())
	.options('*', cors())
	.use(cors())
	.use(favicon(path.join(app.get('public'), 'favicon.ico')))
	.use('/', express.static('public'))
	.configure(sentry)
	.use('/helpdesk', bodyParser.json({ limit: BODYPARSER_JSON_LIMIT }))
	.use('/', bodyParser.json({ limit: '10mb' }))
	.use(bodyParser.urlencoded({ extended: true }))
	.use(bodyParser.raw({ type: () => true, limit: '10mb' }))
	.use(versionService)
	.use(defaultHeaders)
	.get('/system_info/haproxy', (req, res) => {
		res.send({ timestamp: new Date().getTime() });
	})
	.get('/ping', (req, res) => {
		res.send({ message: 'pong', timestamp: new Date().getTime() });
	})
	.configure(rest(handleResponseType))
	.configure(socketio())
	.configure(requestLogger)
	.use((req, res, next) => {
		// pass header into hooks.params
		// todo: To create a fake requestId on this place is a temporary solution
		// it MUST be removed after the API gateway is established
		const uid = ObjectId();
		req.headers.requestId = uid.toString();
		req.feathers.leadTime = req.leadTime;
		req.feathers.headers = req.headers;
		req.feathers.originalUrl = req.originalUrl;
		next();
	})
	.configure(services)
	.configure(sockets)
	.configure(middleware)
	.configure(setupAppHooks)
	.configure(errorHandler);
>>>>>>> develop

	app
		.use(versionService)
		.use(defaultHeaders)
		.get('/system_info/haproxy', (req, res) => {
			res.send({ timestamp: new Date().getTime() });
		})
		.get('/ping', (req, res) => {
			res.send({ message: 'pong', timestamp: new Date().getTime() });
		})
		.configure(rest(handleResponseType))
		.configure(socketio())
		.configure(requestLogger)
		.use((req, res, next) => {
			// pass header into hooks.params
			// todo: To create a fake requestId on this place is a temporary solution
			// it MUST be removed after the API gateway is established
			const uid = ObjectId();
			req.headers.requestId = uid.toString();

			req.feathers.headers = req.headers;
			next();
		})
		.configure(services)
		.configure(sockets)
		.configure(middleware)
		.configure(setupAppHooks)
		.configure(errorHandler);

	return app;
};

module.exports = setupApp();
<commit_msg>finish unfinished merge<commit_after>const express = require('@feathersjs/express');
const feathers = require('@feathersjs/feathers');
const configuration = require('@feathersjs/configuration');
const apiMetrics = require('prometheus-api-metrics');
const path = require('path');
const favicon = require('serve-favicon');
const compress = require('compression');
const cors = require('cors');
const rest = require('@feathersjs/express/rest');
const bodyParser = require('body-parser');
const socketio = require('@feathersjs/socketio');
const { ObjectId } = require('mongoose').Types;

const { KEEP_ALIVE, BODYPARSER_JSON_LIMIT, METRICS_PATH, LEAD_TIME } = require('../config/globals');

const middleware = require('./middleware');
const sockets = require('./sockets');
const services = require('./services');

const defaultHeaders = require('./middleware/defaultHeaders');
const handleResponseType = require('./middleware/handleReponseType');
const requestLogger = require('./middleware/requestLogger');
const errorHandler = require('./middleware/errorHandler');
const sentry = require('./middleware/sentry');
const rabbitMq = require('./utils/rabbitmq');

const setupSwagger = require('./swagger');
const { initializeRedisClient } = require('./utils/redis');
const { setupAppHooks } = require('./app.hooks');
const versionService = require('./services/version');

const setupApp = async () => {
	const app = express(feathers());
	app.disable('x-powered-by');

	const config = configuration();
	app.configure(config);

	if (LEAD_TIME) {
		app.use((req, res, next) => {
			req.leadTime = Date.now();
			next();
		});
	}

	const metricsOptions = {};
	if (METRICS_PATH) {
		metricsOptions.metricsPath = METRICS_PATH;
	}
	app.use(apiMetrics(metricsOptions));

	setupSwagger(app);
	initializeRedisClient();
	rabbitMq.setup(app);

	// set custom response header for ha proxy
	if (KEEP_ALIVE) {
		app.use((req, res, next) => {
			res.setHeader('Connection', 'Keep-Alive');
			next();
		});
	}

	app
		.use(compress())
		.options('*', cors())
		.use(cors())
		.use(favicon(path.join(app.get('public'), 'favicon.ico')))
		.use('/', express.static('public'))
		.configure(sentry)
		.use('/helpdesk', bodyParser.json({ limit: BODYPARSER_JSON_LIMIT }))
		.use('/', bodyParser.json({ limit: '10mb' }))
		.use(bodyParser.urlencoded({ extended: true }))
		.use(bodyParser.raw({ type: () => true, limit: '10mb' }))

	await Promise.resolve(); // placeholder for initializing API validation

	app
		.use(versionService)
		.use(defaultHeaders)
		.get('/system_info/haproxy', (req, res) => {
			res.send({ timestamp: new Date().getTime() });
		})
		.get('/ping', (req, res) => {
			res.send({ message: 'pong', timestamp: new Date().getTime() });
		})
		.configure(rest(handleResponseType))
		.configure(socketio())
		.configure(requestLogger)
		.use((req, res, next) => {
			// pass header into hooks.params
			// todo: To create a fake requestId on this place is a temporary solution
			// it MUST be removed after the API gateway is established
			const uid = ObjectId();
			req.headers.requestId = uid.toString();
			req.feathers.leadTime = req.leadTime;
			req.feathers.headers = req.headers;
			req.feathers.originalUrl = req.originalUrl;
			next();
		})
		.configure(services)
		.configure(sockets)
		.configure(middleware)
		.configure(setupAppHooks)
		.configure(errorHandler);

	return app;
};

module.exports = setupApp();
<|endoftext|>


<commit_before>'use strict';

const cp = require('child_process');
const fs = require('fs');
const path = require('path');
const EventEmitter = require('events');

const logger = require('../../shared/logger');
const RpcChannel = require('../../shared/rpc-channel');

module.exports = class WorkerClient extends EventEmitter {
  constructor() {
    super();

    this.workerProcess = null;
    this.rpc = RpcChannel.create('#worker', this.send.bind(this), this.on.bind(this));
  }
  reloadWorker() {
    logger.debug('WorkerWrapper: reloading worker');

    if (this.workerProcess !== null) {
      this.workerProcess.kill();
      this.workerProcess = null;
    }

    this.loadWorker();
  }
  loadWorker() {
    logger.debug('WorkerWrapper: loading worker');

    const workerPath = path.join(__dirname, '../../worker/index.js');
    if (!fs.existsSync(workerPath))
      throw new Error('can\'t execute plugin process');

    this.workerProcess = cp.fork(workerPath, [], {
      execArgv: ['--always-compact'],
      silent: true
    });
    this.workerProcess.stdout.on('data', process.stdout.write);
    this.workerProcess.stderr.on('data', process.stdout.write);
    this.workerProcess.on('message', (msg) => this._handleWorkerMessage(msg));
  }
  send(channel, payload) {
    this.workerProcess.send({ channel, payload });
  }
  _handleWorkerMessage(msg) {
    const { channel, payload } = msg;
    this.emit(channel, payload);
  }
};
<commit_msg>Add workaround comment<commit_after>'use strict';

const cp = require('child_process');
const fs = require('fs');
const path = require('path');
const EventEmitter = require('events');

const logger = require('../../shared/logger');
const RpcChannel = require('../../shared/rpc-channel');

module.exports = class WorkerClient extends EventEmitter {
  constructor() {
    super();

    this.workerProcess = null;
    this.rpc = RpcChannel.create('#worker', this.send.bind(this), this.on.bind(this));
  }
  reloadWorker() {
    logger.debug('WorkerWrapper: reloading worker');

    if (this.workerProcess !== null) {
      this.workerProcess.kill();
      this.workerProcess = null;
    }

    this.loadWorker();
  }
  loadWorker() {
    logger.debug('WorkerWrapper: loading worker');

    const workerPath = path.join(__dirname, '../../worker/index.js');
    if (!fs.existsSync(workerPath))
      throw new Error('can\'t execute plugin process');

    this.workerProcess = cp.fork(workerPath, [], {
      execArgv: ['--always-compact'],
      silent: true
    });

    // Workaround for Electron 1.3.4's strange stdio redirection
    this.workerProcess.stdout.on('data', process.stdout.write);
    this.workerProcess.stderr.on('data', process.stdout.write);

    this.workerProcess.on('message', (msg) => this._handleWorkerMessage(msg));
  }
  send(channel, payload) {
    this.workerProcess.send({ channel, payload });
  }
  _handleWorkerMessage(msg) {
    const { channel, payload } = msg;
    this.emit(channel, payload);
  }
};
<|endoftext|>


<commit_before>/**
 * Hellosleep
 */

// Load .env for development environments
(process.env.NODE_ENV !== 'production') && require('dotenv').load();

const keystone = require('keystone');

keystone.init({

  'name': '睡吧',
  'brand': '睡吧',

  'less': 'public',
  'static': 'public',

  'views': 'templates/views',
  'view engine': 'jade',

  'port': process.env.PORT || 3000,

  'session': true,
  'auth': true,
  'user model': 'User',
  'cookie secret': '--- insomnia ---',

  'mongo': process.env.MONGO_URI || 'mongodb://localhost/hellosleep',

  'auto update': true,

//  'session store': 'mongo',

  // editor configuration
  'wysiwyg additional buttons': 'styleselect',

  'basedir': __dirname
});

keystone.import('models');

keystone.set('routes', require('./routes'));

keystone.set('locals', {
  ga: {
    property: process.env.GA_SITE_PROPERTY,
    domain: process.env.GA_SITE_DOMAIN
  },
  env: process.env.NODE_ENV || "development"
});

keystone.start();
<commit_msg>Use mongodb as production session store<commit_after>/**
 * Hellosleep
 */

// Load .env for development environments
(process.env.NODE_ENV !== 'production') && require('dotenv').load();

const keystone = require('keystone');

keystone.init({

  'name': '睡吧',
  'brand': '睡吧',

  'less': 'public',
  'static': 'public',

  'views': 'templates/views',
  'view engine': 'jade',

  'port': process.env.PORT || 3000,

  'session': true,
  'auth': true,
  'user model': 'User',
  'cookie secret': '--- insomnia ---',

  'mongo': process.env.MONGO_URI || 'mongodb://localhost/hellosleep',

  'auto update': true,

  'session store': 'mongo',

  // editor configuration
  'wysiwyg additional buttons': 'styleselect',

  'basedir': __dirname
});

keystone.import('models');

keystone.set('routes', require('./routes'));

keystone.set('locals', {
  ga: {
    property: process.env.GA_SITE_PROPERTY,
    domain: process.env.GA_SITE_DOMAIN
  },
  env: process.env.NODE_ENV || "development"
});

keystone.start();
<|endoftext|>


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

    var DataGridComponent;
    var helpers;
    var $ = require('jquery');
    var _ = require('underscore');
    var tools = require('oroui/js/tools');
    var mediator = require('oroui/js/mediator');
    var BaseComponent = require('oroui/js/app/components/base/component');
    var PageableCollection = require('orodatagrid/js/pageable-collection');
    var Grid = require('orodatagrid/js/datagrid/grid');
    var mapActionModuleName = require('orodatagrid/js/map-action-module-name');
    var mapCellModuleName = require('orodatagrid/js/map-cell-module-name');
    var gridContentManager = require('orodatagrid/js/content-manager');
    var FloatingHeaderPlugin = require('orodatagrid/js/app/plugins/grid/floating-header-plugin');
    var FullscreenPlugin = require('orodatagrid/js/app/plugins/grid/fullscreen-plugin');
    var ColumnManagerPlugin = require('orodatagrid/js/app/plugins/grid/column-manager-plugin');

    helpers = {
        cellType: function(type) {
            return type + 'Cell';
        },
        actionType: function(type) {
            return type + 'Action';
        }
    };

    /**
     * Runs passed builder
     *
     * @param {jQuery.Deferred} built
     * @param {Object} options
     * @param {Object} builder
     */
    function runBuilder(built, options, builder) {
        if (!_.has(builder, 'init') || !$.isFunction(builder.init)) {
            built.resolve();
            throw new TypeError('Builder does not have init method');
        }
        _.defer(_.bind(builder.init, builder), built, options);
    }

    DataGridComponent = BaseComponent.extend({
        initialize: function(options) {
            if (!options.enableFilters) {
                options.builders = _.reject(options.builders, function(module) {
                    return module === 'orofilter/js/datafilter-builder';
                });
            }
            options.builders.push('orodatagrid/js/inline-editing/builder');

            var self = this;
            this._deferredInit();
            this.built = $.Deferred();

            options = options || {};
            this.fixStates(options);
            this.processOptions(options);
            this.initDataGrid(options);

            var promises = [this.built.promise()];

            // run related builders
            _.each(options.builders, function(module) {
                var built = $.Deferred();
                promises.push(built.promise());
                require([module], _.partial(runBuilder, built, options));
            });

            $.when.apply($, promises).always(function() {
                self.subComponents = _.compact(arguments);
                self._resolveDeferredInit();
                self.$el.show();
                self.grid.trigger('shown');
            });
        },

        /**
         * Extends passed options
         *
         * @param options
         */
        processOptions: function(options) {
            if (typeof options.inputName === 'undefined') {
                throw new Error('Option inputName has to be specified');
            }

            options.$el = $(options.el);
            options.gridName = options.gridName || options.metadata.options.gridName;
            options.builders = options.builders || [];
            options.builders.push('orodatagrid/js/grid-views-builder');
            options.gridPromise = this.built.promise();
        },

        /**
         * Collects required modules and runs grid builder
         *
         * @param {Object} options
         */
        initDataGrid: function(options) {
            this.$el = $('<div>');
            $(options.el).append(this.$el);
            this.gridName = options.gridName;
            this.inputName = options.inputName;
            this.data = options.data;
            this.metadata = _.defaults(options.metadata, {
                columns: [],
                options: {},
                state: {},
                initialState: {},
                rowActions: {},
                massActions: {}
            });
            this.modules = {};

            this.collectModules();

            // load all dependencies and build grid
            tools.loadModules(this.modules, this.build, this);
        },

        /**
         * Collects required modules
         */
        collectModules: function() {
            var modules = this.modules;
            var metadata = this.metadata;
            // cells
            _.each(metadata.columns, function(column) {
                var type = column.type;
                modules[helpers.cellType(type)] = mapCellModuleName(type);
            });
            // row actions
            _.each(_.values(metadata.rowActions), function(action) {
                var type = action.frontend_type;
                modules[helpers.actionType(type)] = mapActionModuleName(type);
            });
            // mass actions
            _.each(_.values(metadata.massActions), function(action) {
                var type = action.frontend_type;
                modules[helpers.actionType(type)] = mapActionModuleName(type);
            });
        },

        /**
         * Build grid
         */
        build: function() {
            var collectionModels;
            var collectionOptions;
            var grid;

            var collectionName = this.gridName;
            var collection = gridContentManager.get(collectionName);

            collectionModels = {};
            if (this.data && this.data.data) {
                collectionModels = this.data.data;
            }

            collectionOptions = this.combineCollectionOptions();
            if (this.data && this.data.options) {
                _.extend(collectionOptions, this.data.options);
            }

            if (!collection) {
                // otherwise, create collection from metadata
                collection = new PageableCollection(collectionModels, collectionOptions);
            } else if (this.data) {
                _.extend(collectionOptions, {parse: true});
                collection.reset(collectionModels, collectionOptions);
            }

            // create grid
            var options = this.combineGridOptions();
            mediator.trigger('datagrid_create_before', options, collection);

            this.$el.hide();
            options.el = this.$el[0];
            grid = new Grid(_.extend({collection: collection}, options));
            this.grid = grid;
            grid.render();
            mediator.trigger('datagrid:rendered', grid);

            if (options.routerEnabled !== false) {
                // trace collection changes
                gridContentManager.trace(collection);
            }

            var deferredBuilt = this.built;
            if (grid.deferredRender) {
                grid.deferredRender.then(function() {
                    deferredBuilt.resolve(grid);
                });
            } else {
                deferredBuilt.resolve(grid);
            }
        },

        /**
         * Process metadata and combines options for collection
         *
         * @returns {Object}
         */
        combineCollectionOptions: function() {
            var options = _.extend({
                inputName: this.inputName,
                parse: true,
                url: '\/user\/json',
                state: _.extend({
                    filters: {},
                    sorters: {},
                    columns: {}
                }, this.metadata.state),
                initialState: this.metadata.initialState,
                mode: this.metadata.mode || 'server'
            }, this.metadata.options);
            return options;
        },

        /**
         * Process metadata and combines options for datagrid
         *
         * @returns {Object}
         */
        combineGridOptions: function() {
            var columns;
            var rowActions = {};
            var massActions = {};
            var defaultOptions = {
                sortable: false
            };
            var modules = this.modules;
            var metadata = this.metadata;
            var plugins = this.metadata.plugins || [];

            // columns
            columns = _.map(metadata.columns, function(cell) {
                var cellOptionKeys = ['name', 'label', 'renderable', 'editable', 'sortable', 'align',
                    'order', 'manageable', 'required'];
                var cellOptions = _.extend({}, defaultOptions, _.pick.apply(null, [cell].concat(cellOptionKeys)));
                var extendOptions = _.omit.apply(null, [cell].concat(cellOptionKeys.concat('type')));
                var cellType = modules[helpers.cellType(cell.type)];
                if (!_.isEmpty(extendOptions)) {
                    cellType = cellType.extend(extendOptions);
                }
                cellOptions.cell = cellType;
                return cellOptions;
            });

            // row actions
            _.each(metadata.rowActions, function(options, action) {
                rowActions[action] = modules[helpers.actionType(options.frontend_type)].extend(options);
            });

            // mass actions
            _.each(metadata.massActions, function(options, action) {
                massActions[action] = modules[helpers.actionType(options.frontend_type)].extend(options);
            });

            if (tools.isMobile()) {
                plugins.push(FloatingHeaderPlugin);
            } else {
                if (this.metadata.enableFullScreenLayout) {
                    plugins.push(FullscreenPlugin);
                }
            }

            if (metadata.options.toolbarOptions.addColumnManager) {
                plugins.push(ColumnManagerPlugin);
            }

            return {
                name: this.gridName,
                columns: columns,
                rowActions: rowActions,
                massActions: massActions,
                toolbarOptions: metadata.options.toolbarOptions || {},
                multipleSorting: metadata.options.multipleSorting || false,
                entityHint: metadata.options.entityHint,
                exportOptions: metadata.options.export || {},
                routerEnabled: _.isUndefined(metadata.options.routerEnabled) ? true : metadata.options.routerEnabled,
                multiSelectRowEnabled: metadata.options.multiSelectRowEnabled || !_.isEmpty(massActions),
                metadata: this.metadata,
                plugins: plugins
            };
        },

        fixStates: function(options) {
            if (options.metadata) {
                this.fixState(options.metadata.state);
                this.fixState(options.metadata.initialState);
            }
        },

        fixState: function(state) {
            if (_.isArray(state.filters) && _.isEmpty(state.filters)) {
                state.filters = {};
            }

            if (_.isArray(state.sorters) && _.isEmpty(state.sorters)) {
                state.sorters = {};
            }
        },

        dispose: function() {
            // disposes registered sub-components
            if (this.subComponents) {
                _.each(this.subComponents, function(component) {
                    if (component && typeof component.dispose === 'function') {
                        component.dispose();
                    }
                });
                delete this.subComponents;
            }
            DataGridComponent.__super__.dispose.call(this);
        }
    });

    return DataGridComponent;
});
<commit_msg>BAP-9139: Data grid scope information is not in use<commit_after>define(function(require) {
    'use strict';

    var DataGridComponent;
    var helpers;
    var $ = require('jquery');
    var _ = require('underscore');
    var tools = require('oroui/js/tools');
    var mediator = require('oroui/js/mediator');
    var BaseComponent = require('oroui/js/app/components/base/component');
    var PageableCollection = require('orodatagrid/js/pageable-collection');
    var Grid = require('orodatagrid/js/datagrid/grid');
    var mapActionModuleName = require('orodatagrid/js/map-action-module-name');
    var mapCellModuleName = require('orodatagrid/js/map-cell-module-name');
    var gridContentManager = require('orodatagrid/js/content-manager');
    var FloatingHeaderPlugin = require('orodatagrid/js/app/plugins/grid/floating-header-plugin');
    var FullscreenPlugin = require('orodatagrid/js/app/plugins/grid/fullscreen-plugin');
    var ColumnManagerPlugin = require('orodatagrid/js/app/plugins/grid/column-manager-plugin');

    helpers = {
        cellType: function(type) {
            return type + 'Cell';
        },
        actionType: function(type) {
            return type + 'Action';
        }
    };

    /**
     * Runs passed builder
     *
     * @param {jQuery.Deferred} built
     * @param {Object} options
     * @param {Object} builder
     */
    function runBuilder(built, options, builder) {
        if (!_.has(builder, 'init') || !$.isFunction(builder.init)) {
            built.resolve();
            throw new TypeError('Builder does not have init method');
        }
        _.defer(_.bind(builder.init, builder), built, options);
    }

    DataGridComponent = BaseComponent.extend({
        initialize: function(options) {
            if (!options.enableFilters) {
                options.builders = _.reject(options.builders, function(module) {
                    return module === 'orofilter/js/datafilter-builder';
                });
            }
            options.builders.push('orodatagrid/js/inline-editing/builder');

            var self = this;
            this._deferredInit();
            this.built = $.Deferred();

            options = options || {};
            this.fixStates(options);
            this.processOptions(options);
            this.initDataGrid(options);

            var promises = [this.built.promise()];

            // run related builders
            _.each(options.builders, function(module) {
                var built = $.Deferred();
                promises.push(built.promise());
                require([module], _.partial(runBuilder, built, options));
            });

            $.when.apply($, promises).always(function() {
                self.subComponents = _.compact(arguments);
                self._resolveDeferredInit();
                self.$el.show();
                self.grid.trigger('shown');
            });
        },

        /**
         * Extends passed options
         *
         * @param options
         */
        processOptions: function(options) {
            if (typeof options.inputName === 'undefined') {
                throw new Error('Option inputName has to be specified');
            }

            options.$el = $(options.el);
            options.gridName = options.gridName || options.metadata.options.gridName;
            options.builders = options.builders || [];
            options.builders.push('orodatagrid/js/grid-views-builder');
            options.gridPromise = this.built.promise();
        },

        /**
         * Collects required modules and runs grid builder
         *
         * @param {Object} options
         */
        initDataGrid: function(options) {
            this.$el = $('<div>');
            $(options.el).append(this.$el);
            this.gridName = options.gridName;
            this.inputName = options.inputName;
            this.data = options.data;
            this.metadata = _.defaults(options.metadata, {
                columns: [],
                options: {},
                state: {},
                initialState: {},
                rowActions: {},
                massActions: {}
            });
            this.modules = {};

            this.collectModules();

            // load all dependencies and build grid
            tools.loadModules(this.modules, this.build, this);
        },

        /**
         * Collects required modules
         */
        collectModules: function() {
            var modules = this.modules;
            var metadata = this.metadata;
            // cells
            _.each(metadata.columns, function(column) {
                var type = column.type;
                modules[helpers.cellType(type)] = mapCellModuleName(type);
            });
            // row actions
            _.each(_.values(metadata.rowActions), function(action) {
                var type = action.frontend_type;
                modules[helpers.actionType(type)] = mapActionModuleName(type);
            });
            // mass actions
            _.each(_.values(metadata.massActions), function(action) {
                var type = action.frontend_type;
                modules[helpers.actionType(type)] = mapActionModuleName(type);
            });
        },

        /**
         * Build grid
         */
        build: function() {
            var collectionModels;
            var collectionOptions;
            var grid;

            var collectionName = this.gridName;
            var collection = gridContentManager.get(collectionName);

            collectionModels = {};
            if (this.data && this.data.data) {
                collectionModels = this.data.data;
            }

            collectionOptions = this.combineCollectionOptions();
            if (this.data && this.data.options) {
                _.extend(collectionOptions, this.data.options);
            }

            if (!collection) {
                // otherwise, create collection from metadata
                collection = new PageableCollection(collectionModels, collectionOptions);
            } else if (this.data) {
                _.extend(collectionOptions, {parse: true});
                collection.reset(collectionModels, collectionOptions);
            }

            // create grid
            var options = this.combineGridOptions();
            mediator.trigger('datagrid_create_before', options, collection);

            this.$el.hide();
            options.el = this.$el[0];
            grid = new Grid(_.extend({collection: collection}, options));
            this.grid = grid;
            grid.render();
            mediator.trigger('datagrid:rendered', grid);

            if (options.routerEnabled !== false) {
                // trace collection changes
                gridContentManager.trace(collection);
            }

            var deferredBuilt = this.built;
            if (grid.deferredRender) {
                grid.deferredRender.then(function() {
                    deferredBuilt.resolve(grid);
                });
            } else {
                deferredBuilt.resolve(grid);
            }
        },

        /**
         * Process metadata and combines options for collection
         *
         * @returns {Object}
         */
        combineCollectionOptions: function() {
            var options = _.extend({
                /*
                 * gridName contains extended information "inputName + scopeName"
                 * (allows to differentiate grid instances)
                 */
                inputName: this.gridName,
                parse: true,
                url: '\/user\/json',
                state: _.extend({
                    filters: {},
                    sorters: {},
                    columns: {}
                }, this.metadata.state),
                initialState: this.metadata.initialState,
                mode: this.metadata.mode || 'server'
            }, this.metadata.options);
            return options;
        },

        /**
         * Process metadata and combines options for datagrid
         *
         * @returns {Object}
         */
        combineGridOptions: function() {
            var columns;
            var rowActions = {};
            var massActions = {};
            var defaultOptions = {
                sortable: false
            };
            var modules = this.modules;
            var metadata = this.metadata;
            var plugins = this.metadata.plugins || [];

            // columns
            columns = _.map(metadata.columns, function(cell) {
                var cellOptionKeys = ['name', 'label', 'renderable', 'editable', 'sortable', 'align',
                    'order', 'manageable', 'required'];
                var cellOptions = _.extend({}, defaultOptions, _.pick.apply(null, [cell].concat(cellOptionKeys)));
                var extendOptions = _.omit.apply(null, [cell].concat(cellOptionKeys.concat('type')));
                var cellType = modules[helpers.cellType(cell.type)];
                if (!_.isEmpty(extendOptions)) {
                    cellType = cellType.extend(extendOptions);
                }
                cellOptions.cell = cellType;
                return cellOptions;
            });

            // row actions
            _.each(metadata.rowActions, function(options, action) {
                rowActions[action] = modules[helpers.actionType(options.frontend_type)].extend(options);
            });

            // mass actions
            _.each(metadata.massActions, function(options, action) {
                massActions[action] = modules[helpers.actionType(options.frontend_type)].extend(options);
            });

            if (tools.isMobile()) {
                plugins.push(FloatingHeaderPlugin);
            } else {
                if (this.metadata.enableFullScreenLayout) {
                    plugins.push(FullscreenPlugin);
                }
            }

            if (metadata.options.toolbarOptions.addColumnManager) {
                plugins.push(ColumnManagerPlugin);
            }

            return {
                name: this.gridName,
                columns: columns,
                rowActions: rowActions,
                massActions: massActions,
                toolbarOptions: metadata.options.toolbarOptions || {},
                multipleSorting: metadata.options.multipleSorting || false,
                entityHint: metadata.options.entityHint,
                exportOptions: metadata.options.export || {},
                routerEnabled: _.isUndefined(metadata.options.routerEnabled) ? true : metadata.options.routerEnabled,
                multiSelectRowEnabled: metadata.options.multiSelectRowEnabled || !_.isEmpty(massActions),
                metadata: this.metadata,
                plugins: plugins
            };
        },

        fixStates: function(options) {
            if (options.metadata) {
                this.fixState(options.metadata.state);
                this.fixState(options.metadata.initialState);
            }
        },

        fixState: function(state) {
            if (_.isArray(state.filters) && _.isEmpty(state.filters)) {
                state.filters = {};
            }

            if (_.isArray(state.sorters) && _.isEmpty(state.sorters)) {
                state.sorters = {};
            }
        },

        dispose: function() {
            // disposes registered sub-components
            if (this.subComponents) {
                _.each(this.subComponents, function(component) {
                    if (component && typeof component.dispose === 'function') {
                        component.dispose();
                    }
                });
                delete this.subComponents;
            }
            DataGridComponent.__super__.dispose.call(this);
        }
    });

    return DataGridComponent;
});
<|endoftext|>


<commit_before>import koa from 'koa';
import fs from 'fs';
import Q from 'q';
import views from 'co-views';

const render = views(__dirname + '/views', { ext: 'ejs' });

let app = koa();

function myAsync(ala, done) {
    console.log(arguments);
    done(null, []);
}

app.use(function *(next){
    let articlesContent = yield Q.ninvoke(fs, 'readFile', __dirname + '/data/articles.json');
    let articles = JSON.parse(articlesContent);

    this.body = yield render('index', { articles: articles });
});

export function start(port=3000) {
    app.listen(port);
}
<commit_msg>Remove dummy function<commit_after>import koa from 'koa';
import fs from 'fs';
import Q from 'q';
import views from 'co-views';

const render = views(__dirname + '/views', { ext: 'ejs' });

let app = koa();

app.use(function *(next){
    let articlesContent = yield Q.ninvoke(fs, 'readFile', __dirname + '/data/articles.json');
    let articles = JSON.parse(articlesContent);

    this.body = yield render('index', { articles: articles });
});

export function start(port=3000) {
    app.listen(port);
}
<|endoftext|>


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

  angular.module('app', [
    'ui.router',
    'oc.lazyLoad',
    'ngFileUpload',
    'ngDialog',
    'toastr',
    'config'
  ])
  .config(['$stateProvider', '$urlRouterProvider', '$locationProvider', '$ocLazyLoadProvider', '$httpProvider', '$compileProvider', 'statics', 'routes', function($stateProvider, $urlRouterProvider, $locationProvider, $ocLazyLoadProvider, $httpProvider, $compileProvider, statics, routes){
    // $ocLazyLoadProvider.config({
    //   debug: true
    // });
    $urlRouterProvider.otherwise('/main/index');
    $urlRouterProvider.when('/main', '/main/index');
    $urlRouterProvider.when('/main/frame', '/main/frame/start');
    $urlRouterProvider.when('/main/plugin', '/main/plugin/lazyload');
    $locationProvider.hashPrefix('');
    $stateProvider.state('main', {
      url: '/main',
      views: {
        '': {
          templateUrl: statics.path + 'pages/main/main.html'
        },
        '@header': {
          templateUrl: statics.path + 'components/header/header.html'
        },
        '@footer': {
          templateUrl: statics.path + 'components/footer/footer.html'
        }
      },
      resolve: {
        loadMyFile: ['$ocLazyLoad', function($ocLazyLoad){
          return $ocLazyLoad.load({
            files: [
              statics.path + 'components/header/header.js',
              statics.path + 'components/footer/footer.js'
            ]
          });
        }]
      }
    })
    .state('main.index', stateConf('index'))
    .state('main.frame', stateConf('frame'))
    .state('main.frame.start', stateConf('start'))
    .state('main.frame.config', stateConf('config'))
    .state('main.frame.run', stateConf('run'))
    .state('main.frame.component', stateConf('component'))
    .state('main.frame.controller', stateConf('controller'))
    .state('main.frame.form', stateConf('form'))
    .state('main.frame.validate', stateConf('validate'))
    .state('main.frame.event', stateConf('event'))
    .state('main.frame.command', stateConf('command'))
    .state('main.frame.globalapi', stateConf('globalapi'))
    .state('main.plugin', stateConf('plugin'))
    .state('main.plugin.lazyload', stateConf('lazyload'))
    .state('main.plugin.fileupload', stateConf('fileupload'))
    .state('main.plugin.dialog', stateConf('dialog'))
    .state('main.plugin.toastr', stateConf('toastr'))
    ;
    /* state config:start */
    function stateConf(route, htmlfile, jsfiles){
      if (routes[route]){
        if (routes[route] instanceof Array && routes[route].length === 2){
          htmlfile = htmlfile || routes[route][0];
          jsfiles = jsfiles || routes[route][1];
        }else {
          throw new Error('The ' + route + '\'s route template config error! It must be an Array and length === 2.');
        }
      }else {
        throw new Error('The ' + route + ' route not template config!');
      }
      return {
        url: '/' + route,
        templateUrl: statics.path + htmlfile,
        resolve: {
          loadMyFile: ['$ocLazyLoad', function($ocLazyLoad){
            return $ocLazyLoad.load({
              files: (typeof jsfiles === 'string' ? [statics.path + jsfiles] : (jsfiles || []))
            });
          }]
        }
      };
    };
    /* state config:end */
    $httpProvider.interceptors.push(['$rootScope', function($rootScope){
      return {
        request: function(req){
          var md = req.url.match(/[a-zA-Z0-9-]+\.html/)[0].replace('.html', '').match(/[a-zA-Z0-9]+/)[0];
          if (md !== 'frame' && md !== 'plugin' && routes[md]) $rootScope.openTransition = md;
          else $rootScope.openTransition = false;
          $rootScope.footerIsShow = false;
          return req;
        },
        response: function(res){
          $rootScope.footerIsShow = !!$rootScope.openTransition;
          return res;
        }
      }
    }]);
  }])
  .run(['$rootScope', function($rootScope){
    function log(){
      console.log.apply(console, arguments);
    }
    /* print hello world:start */
    // log('  **    **  ********  **        **          ****    *        *    ****    ******    **        ******');
    // log('  **    **  **        **        **        **    **  **      **  **    **  **    **  **        **    **');
    // log('  ********  ********  **        **        **    **  **  **  **  **    **  ********  **        **    **');
    // log('  **    **  **        **        **        **    **  **********  **    **  **  **    **        **    **');
    // log('  **    **  ********  ********  ********    ****     **    **     ****    **    **  ********  ******');
    /* print hello world:end */
    log('%c Angular 1.x and gulp web spa starter.', 'color:red;');
    log('%c 2017 @Hexson', 'color:red;');
  }]);
})();<commit_msg>[dev] update appjs<commit_after>(function(){
  'use strict';
  '__VERSION__';

  angular.module('app', [
    'ui.router',
    'oc.lazyLoad',
    'ngFileUpload',
    'ngDialog',
    'toastr',
    'config'
  ])
  .config(['$stateProvider', '$urlRouterProvider', '$locationProvider', '$ocLazyLoadProvider', '$httpProvider', '$compileProvider', 'statics', 'routes', function($stateProvider, $urlRouterProvider, $locationProvider, $ocLazyLoadProvider, $httpProvider, $compileProvider, statics, routes){
    // $ocLazyLoadProvider.config({
    //   debug: true
    // });
    $urlRouterProvider.otherwise('/main/index');
    $urlRouterProvider.when('/main', '/main/index');
    $urlRouterProvider.when('/main/frame', '/main/frame/start');
    $urlRouterProvider.when('/main/plugin', '/main/plugin/lazyload');
    $locationProvider.hashPrefix('');
    $stateProvider.state('main', {
      url: '/main',
      views: {
        '': {
          templateUrl: statics.path + 'pages/main.html'
        },
        '@header': {
          templateUrl: statics.path + 'components/header.html'
        },
        '@footer': {
          templateUrl: statics.path + 'components/footer.html'
        }
      },
      resolve: {
        loadMyFile: ['$ocLazyLoad', function($ocLazyLoad){
          return $ocLazyLoad.load({
            files: [
              statics.path + 'components/header.js',
              statics.path + 'components/footer.js'
            ]
          });
        }]
      }
    })
    .state('main.index', stateConf('index'))
    .state('main.frame', stateConf('frame'))
    .state('main.frame.start', stateConf('start'))
    .state('main.frame.config', stateConf('config'))
    .state('main.frame.run', stateConf('run'))
    .state('main.frame.component', stateConf('component'))
    .state('main.frame.controller', stateConf('controller'))
    .state('main.frame.form', stateConf('form'))
    .state('main.frame.validate', stateConf('validate'))
    .state('main.frame.event', stateConf('event'))
    .state('main.frame.command', stateConf('command'))
    .state('main.frame.globalapi', stateConf('globalapi'))
    .state('main.plugin', stateConf('plugin'))
    .state('main.plugin.lazyload', stateConf('lazyload'))
    .state('main.plugin.fileupload', stateConf('fileupload'))
    .state('main.plugin.dialog', stateConf('dialog'))
    .state('main.plugin.toastr', stateConf('toastr'))
    .state('main.plugin.storage', stateConf('storage'))
    ;
    /* state config:start */
    function stateConf(route, htmlfile, jsfiles){
      if (routes[route]){
        if (routes[route] instanceof Array && routes[route].length === 2){
          htmlfile = htmlfile || routes[route][0];
          jsfiles = jsfiles || routes[route][1];
        }else {
          throw new Error('The ' + route + '\'s route template config error! It must be an Array and length === 2.');
        }
      }else {
        throw new Error('The ' + route + ' route not template config!');
      }
      return {
        url: '/' + route,
        templateUrl: statics.path + htmlfile,
        resolve: {
          loadMyFile: ['$ocLazyLoad', function($ocLazyLoad){
            return $ocLazyLoad.load({
              files: (typeof jsfiles === 'string' ? [statics.path + jsfiles] : (jsfiles || []))
            });
          }]
        }
      };
    };
    /* state config:end */
    $httpProvider.interceptors.push(['$rootScope', function($rootScope){
      return {
        request: function(req){
          var md = req.url.match(/[a-zA-Z0-9-]+\.html/)[0].replace('.html', '').match(/[a-zA-Z0-9]+/)[0];
          if (md !== 'frame' && md !== 'plugin' && routes[md]) $rootScope.openTransition = md;
          else $rootScope.openTransition = false;
          $rootScope.footerIsShow = false;
          return req;
        },
        response: function(res){
          $rootScope.footerIsShow = !!$rootScope.openTransition;
          return res;
        }
      }
    }]);
  }])
  .run(['$rootScope', function($rootScope){
    function log(){
      console.log.apply(console, arguments);
    }
    /* print hello world:start */
    // log('  **    **  ********  **        **          ****    *        *    ****    ******    **        ******');
    // log('  **    **  **        **        **        **    **  **      **  **    **  **    **  **        **    **');
    // log('  ********  ********  **        **        **    **  **  **  **  **    **  ********  **        **    **');
    // log('  **    **  **        **        **        **    **  **********  **    **  **  **    **        **    **');
    // log('  **    **  ********  ********  ********    ****     **    **     ****    **    **  ********  ******');
    /* print hello world:end */
    log('%c Angular 1.x and gulp web spa starter.', 'color:red;');
    log('%c 2017 @Hexson', 'color:red;');
  }]);
})();<|endoftext|>


<commit_before>// Set to true to always pull fresh data - use sparingly!
var CACHE_INVALIDATE = false;
var BUNGIE_API = {
	ADVISORS: 'http://www.bungie.net/Platform/Destiny/Advisors/?definitions=true',
    MANIFEST: {
        ACTIVITY: 'http://www.bungie.net/platform/Destiny/Manifest/Activity/',
		ACTIVITY_TYPE: 'http://www.bungie.net/platform/Destiny/Manifest/ActivityType/'
    }
};

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

var DetailWindow = new ui.Card({
	title: 'Loading...',
	scrollable: true
});

var MenuActivities = {
	nightfall: {
		title: 'Weekly Nightfall',
		subtitle: 'Loading...',
		userdata: {
			key: 'NIGHTFALL'
		}
	},
	weekly: {
		title: 'Weekly Heroic',
		subtitle: 'Loading...',
		userdata: {
			key: 'WEEKLY'
		}
	},
	daily: {
		title: 'Daily Heroic',
		subtitle: 'Loading...',
		userdata: {
			key: 'DAILY'
		}
	},
	crucible: {
		title: 'Daily Crucible',
		subtitle: 'Loading...',
		userdata: {
			key: 'CRUCIBLE'
		}
	}
};

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

	if(item)
	{
		logUI('Updating menu for ' + activity);

		for(key in item)
		{
			MenuActivities[activity][key] = item[key];
		}
	}

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

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

	logUI('New menu sections: ' + JSON.stringify(sections));
	MainMenu.section(0, {title: 'Activity', items: sections});
}

var MainMenu = new ui.Menu({
	sections: []
});

MainMenu.on('select', function(event){
	var sections = event.item.userdata.getDetails();

	logUI('Showing details for ' + event.item.userdata.key);

	for(var key in sections)
	{
		if(sections.hasOwnProperty(key) && DetailWindow[key])
		{
			DetailWindow[key](sections[key]);
		}
	}

	DetailWindow.show();
	MainMenu.hide();
});

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

var today = new Date();
var activityData;

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

	if(activityData)
	{
        var nfreset;
        var dailyreset;

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

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

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

	ajax({
		url: BUNGIE_API.ADVISORS,
		type: 'json'
	}, function(data){
		activityData = data;
		localStorage.setItem('activityData', JSON.stringify(data));
		ClearWait();

		logRemote('Got remote activity data: ' + JSON.stringify(data));

		updateActivities();
	}, function(error){
		ClearWait();

		logError('Could not get response from ' +  BUNGIE_API.ADVISORS + ': ' + error);
	});
}
else
{
	logLocal('Got locally stored activity data: ' + JSON.stringify(activityData.Response.data.nightfallActivityHash));
	updateActivities();
}

MainMenu.show();

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

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

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

	getLocalData(nightfallHash, function(data){
		var item = {
			subtitle: data.Response.data.activity.activityDescription,
			userdata: {
				key: nightfallHash,
				getDetails: function() {
					return {
						title: 'Weekly Nightfall',
						subtitle: 'Strike',
						body: data.Response.data.activity.activityDescription
					};
				}
			}
		};

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

	getLocalData(weeklyHash, function(data){
		var item = {
			subtitle: data.Response.data.activity.activityDescription,
			userdata: {
				key: weeklyHash,
				getDetails: function() {
					return {
						title: 'Weekly Heroic',
						subtitle: 'Strike',
						body: data.Response.data.activity.activityDescription
					};
				}
			}
		};

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

    getLocalData(dailyHash, function(data){
        var item = {
            title: data.Response.data.activity.activityName,
            subtitle: data.Response.data.activity.activityDescription,
			userdata: {
				key: dailyHash,
				getDetails: function() {
					return {
						title: 'Daily Heroic',
						subtitle: data.Response.data.activity.activityName,
						body: data.Response.data.activity.activityDescription
					};
				}
			}
        };

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

    getLocalData(crucibleHash, function(data){
		var activityHash = data.Response.data.activity.activityTypeHash;
		var activityType = data.Response.definitions.activityTypes[activityHash].activityTypeName;

        var item = {
			title: activityType + ': ' + data.Response.data.activity.activityName,
            subtitle: data.Response.data.activity.activityDescription,
			userdata: {
				key: crucibleHash,
				getDetails: function() {
					return {
						title: activityType,
						subtitle: data.Response.data.activity.activityName,
						body: data.Response.data.activity.activityDescription
					};
				}
			}
        };

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

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

	logInfo('Getting local data for hash: ' + hash);

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

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

		if(!data || !data.Response.definitions)
			throw 'No activity data for ' + hash + ', fetching fresh data';

        if(CACHE_INVALIDATE)
            throw 'Manually flushing cache!';
	}
	catch(e) {
		var activityUrl = BUNGIE_API.MANIFEST.ACTIVITY + hash.split('-')[hash.split('-').length-1];
		logError('Tried (unsuccessfully) to grab local data for ' + hash + ': ' + e);
		logInfo('Pulling data for ' + hash + ' from: ' + activityUrl);

		AjaxWait();

		ajax({
			url: activityUrl + '?definitions=true',
			type: 'json'
		}, function(data){
			localStorage.setItem(hash, JSON.stringify(data));
			ClearWait();

			logRemote('Got remote activity data: ' + JSON.stringify(data));

			callback(data);
		}, function(error){
			ClearWait();

			logError('Could not get response from ' +  activityUrl + ': ' + error);
		});
	}

	if(data)
	{
		logLocal('Found local data for hash ' + hash + ', executing callback');
		callback(data);
	}
}

function log(prefix, message)
{
	return console.log('[' + prefix + '] ' + message);
}

function logUI(message)
{
	return log('UI', message);
}

function logError(message)
{
	return log('EE', message);
}

function logInfo(message)
{
	return log('II', message);
}

function logRemote(message)
{
	return log('<<', message);
}

function logLocal(message)
{
	return log('>>', message);
}

<commit_msg>Back button fix<commit_after>// Set to true to always pull fresh data - use sparingly!
var CACHE_INVALIDATE = false;
var BUNGIE_API = {
	ADVISORS: 'http://www.bungie.net/Platform/Destiny/Advisors/?definitions=true',
    MANIFEST: {
        ACTIVITY: 'http://www.bungie.net/platform/Destiny/Manifest/Activity/',
		ACTIVITY_TYPE: 'http://www.bungie.net/platform/Destiny/Manifest/ActivityType/'
    }
};

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

var DetailWindow = new ui.Card({
	title: 'Loading...',
	scrollable: true
});

var MenuActivities = {
	nightfall: {
		title: 'Weekly Nightfall',
		subtitle: 'Loading...',
		userdata: {
			key: 'NIGHTFALL'
		}
	},
	weekly: {
		title: 'Weekly Heroic',
		subtitle: 'Loading...',
		userdata: {
			key: 'WEEKLY'
		}
	},
	daily: {
		title: 'Daily Heroic',
		subtitle: 'Loading...',
		userdata: {
			key: 'DAILY'
		}
	},
	crucible: {
		title: 'Daily Crucible',
		subtitle: 'Loading...',
		userdata: {
			key: 'CRUCIBLE'
		}
	}
};

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

	if(item)
	{
		logUI('Updating menu for ' + activity);

		for(key in item)
		{
			MenuActivities[activity][key] = item[key];
		}
	}

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

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

	logUI('New menu sections: ' + JSON.stringify(sections));
	MainMenu.section(0, {title: 'Activity', items: sections});
}

var MainMenu = new ui.Menu({
	sections: []
});

MainMenu.on('select', function(event){
	var sections = event.item.userdata.getDetails();

	logUI('Showing details for ' + event.item.userdata.key);

	for(var key in sections)
	{
		if(sections.hasOwnProperty(key) && DetailWindow[key])
		{
			DetailWindow[key](sections[key]);
		}
	}

	DetailWindow.show();
});

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

var today = new Date();
var activityData;

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

	if(activityData)
	{
        var nfreset;
        var dailyreset;

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

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

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

	ajax({
		url: BUNGIE_API.ADVISORS,
		type: 'json'
	}, function(data){
		activityData = data;
		localStorage.setItem('activityData', JSON.stringify(data));
		ClearWait();

		logRemote('Got remote activity data: ' + JSON.stringify(data));

		updateActivities();
	}, function(error){
		ClearWait();

		logError('Could not get response from ' +  BUNGIE_API.ADVISORS + ': ' + error);
	});
}
else
{
	logLocal('Got locally stored activity data: ' + JSON.stringify(activityData.Response.data.nightfallActivityHash));
	updateActivities();
}

MainMenu.show();

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

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

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

	getLocalData(nightfallHash, function(data){
		var item = {
			subtitle: data.Response.data.activity.activityDescription,
			userdata: {
				key: nightfallHash,
				getDetails: function() {
					return {
						title: 'Weekly Nightfall',
						subtitle: 'Strike',
						body: data.Response.data.activity.activityDescription
					};
				}
			}
		};

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

	getLocalData(weeklyHash, function(data){
		var item = {
			subtitle: data.Response.data.activity.activityDescription,
			userdata: {
				key: weeklyHash,
				getDetails: function() {
					return {
						title: 'Weekly Heroic',
						subtitle: 'Strike',
						body: data.Response.data.activity.activityDescription
					};
				}
			}
		};

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

    getLocalData(dailyHash, function(data){
        var item = {
            title: data.Response.data.activity.activityName,
            subtitle: data.Response.data.activity.activityDescription,
			userdata: {
				key: dailyHash,
				getDetails: function() {
					return {
						title: 'Daily Heroic',
						subtitle: data.Response.data.activity.activityName,
						body: data.Response.data.activity.activityDescription
					};
				}
			}
        };

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

    getLocalData(crucibleHash, function(data){
		var activityHash = data.Response.data.activity.activityTypeHash;
		var activityType = data.Response.definitions.activityTypes[activityHash].activityTypeName;

        var item = {
			title: activityType + ': ' + data.Response.data.activity.activityName,
            subtitle: data.Response.data.activity.activityDescription,
			userdata: {
				key: crucibleHash,
				getDetails: function() {
					return {
						title: activityType,
						subtitle: data.Response.data.activity.activityName,
						body: data.Response.data.activity.activityDescription
					};
				}
			}
        };

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

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

	logInfo('Getting local data for hash: ' + hash);

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

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

		if(!data || !data.Response.definitions)
			throw 'No activity data for ' + hash + ', fetching fresh data';

        if(CACHE_INVALIDATE)
            throw 'Manually flushing cache!';
	}
	catch(e) {
		var activityUrl = BUNGIE_API.MANIFEST.ACTIVITY + hash.split('-')[hash.split('-').length-1];
		logError('Tried (unsuccessfully) to grab local data for ' + hash + ': ' + e);
		logInfo('Pulling data for ' + hash + ' from: ' + activityUrl);

		AjaxWait();

		ajax({
			url: activityUrl + '?definitions=true',
			type: 'json'
		}, function(data){
			localStorage.setItem(hash, JSON.stringify(data));
			ClearWait();

			logRemote('Got remote activity data: ' + JSON.stringify(data));

			callback(data);
		}, function(error){
			ClearWait();

			logError('Could not get response from ' +  activityUrl + ': ' + error);
		});
	}

	if(data)
	{
		logLocal('Found local data for hash ' + hash + ', executing callback');
		callback(data);
	}
}

function log(prefix, message)
{
	return console.log('[' + prefix + '] ' + message);
}

function logUI(message)
{
	return log('UI', message);
}

function logError(message)
{
	return log('EE', message);
}

function logInfo(message)
{
	return log('II', message);
}

function logRemote(message)
{
	return log('<<', message);
}

function logLocal(message)
{
	return log('>>', message);
}

<|endoftext|>


<commit_before>var init = function() {

	chrome.storage.local.get(['words', 'foundWords'], function( result ){

		var words = [];
		var foundWords = [];

		if( ! result.words ) {

			words = ['innovaatio','synenergia','multimedia','kissa','sosiaalinen media', 'talvivaara', 'ammattiliitto', 'pääministeri', 'huippu'];
			words = _.shuffle( words );

			chrome.storage.local.set( { 'words' : words } )

			console.log("Uusi järjestys arvottu!")

		} else {
			words = result.words;
			foundWords = result.foundWords;
		}

		console.log('??????????');
		console.log( foundWords );
		display( words, foundWords );
	});
}

init();

var display = function(words, foundWords) {

	var text = $('body').text();
	text = text.toLowerCase();

	var container = $('<div>', { id: 'bs-container', style : 'display: none;'} );
	var found = 0;

	for(var i=0;i<9;i++){
		var d = $('<div>', { class: 'bs-box', html : words[i] } ) ;

		if( text.indexOf(words[i]) >0 || foundWords.indexOf(words[i])!= -1 ){
			d.addClass('bs-found');

			// haz found previously?
			if( foundWords.indexOf(words[i]) == -1 ) {
                found++;
				foundWords.push(words[i]);
			}
		}
	    container.append( d );
    }

    console.log( foundWords );

    chrome.storage.local.set( { 'foundWords' : foundWords } );

    $('body').prepend( container );

    var button = $('<div>', { id: 'bs-button', html: 'BS Bingo™ (' + found + ')'} );
	$('body').prepend( button );

	var new_game = $('<div>', { id: 'bs-button', html: 'new game'} );
	$('body').prepend( new_game );

    button.on('click', function() {
    	container.slideToggle();
    });

}
<commit_msg>jotai<commit_after>var init = function() {

	chrome.storage.local.get(['words', 'foundWords'], function( result ){

		var words = [];
		var foundWords = [];

		if( ! result.words ) {

			words = ['innovaatio','synenergia','multimedia','kissa','sosiaalinen media', 'talvivaara', 'ammattiliitto', 'pääministeri', 'huippu'];
			words = _.shuffle( words );

			chrome.storage.local.set( { 'words' : words } )

			console.log("Uusi järjestys arvottu!")

		} else {
			words = result.words;
			foundWords = result.foundWords;
		}

		console.log( foundWords );
		display( words, foundWords );
	});
}

init();

var display = function(words, foundWords) {

	var text = $('body').text();
	text = text.toLowerCase();

	var container = $('<div>', { id: 'bs-container', style : 'display: none;'} );
	var found = 0;

	for(var i=0;i<9;i++){
		var d = $('<div>', { class: 'bs-box', html : words[i] } ) ;

		if( text.indexOf(words[i]) >0 || foundWords.indexOf(words[i])!= -1 ){
			d.addClass('bs-found');

			// haz found previously?
			if( foundWords.indexOf(words[i]) == -1 ) {
                found++;
				foundWords.push(words[i]);
			}
		}
	    container.append( d );
    }

    console.log( foundWords );

    chrome.storage.local.set( { 'foundWords' : foundWords } );

    $('body').prepend( container );

    var button = $('<div>', { id: 'bs-button', html: 'BS Bingo™ (' + found + ')'} );
	$('body').prepend( button );

	var new_game = $('<div>', { id: 'bs-button', html: 'new game'} );
	$('body').prepend( new_game );

    button.on('click', function() {
    	container.slideToggle();
    });

}
<|endoftext|>


<commit_before>const path = require('path');
const express = require('@feathersjs/express');
const favicon = require('serve-favicon');
const compress = require('compression');
const cors = require('cors');
const feathers = require('@feathersjs/feathers');
const configuration = require('@feathersjs/configuration');
const commons = require('@schul-cloud/commons');
const rest = require('@feathersjs/express/rest');
const bodyParser = require('body-parser');
const socketio = require('@feathersjs/socketio');
const { ObjectId } = require('mongoose').Types;

const middleware = require('./middleware');
const sockets = require('./sockets');
const services = require('./services/');

const defaultHeaders = require('./middleware/defaultHeaders');
const handleResponseType = require('./middleware/handleReponseType');
const requestLogger = require('./middleware/requestLogger');
const errorHandler = require('./middleware/errorHandler');
const sentry = require('./middleware/sentry');

const setupSwagger = require('./swagger');
const allHooks = require('./app.hooks');
const versionService = require('./services/version');

const app = express(feathers());
const config = configuration();
const Configuration = new commons.Configuration({
	schemaFileName: 'default.schema.json',
});

app.configure(config);
Configuration.init(app);
setupSwagger(app);

// set custom response header for ha proxy
if (process.env.KEEP_ALIVE) {
	app.use((req, res, next) => {
		res.setHeader('Connection', 'Keep-Alive');
		next();
	});
}

app.use(compress())
	.options('*', cors())
	.use(cors())
	.use(favicon(path.join(app.get('public'), 'favicon.ico')))
	.use('/', express.static('public'))
	.configure(sentry)
	.use(bodyParser.json())
	.use(bodyParser.urlencoded({ extended: true }))
	.use(bodyParser.raw({ type: () => true, limit: '10mb' }))
	.use(versionService)
	.use(defaultHeaders)
	.get('/system_info/haproxy', (req, res) => { res.send({ timestamp: new Date().getTime() }); })
	.get('/ping', (req, res) => { res.send({ message: 'pong', timestamp: new Date().getTime() }); })
	.configure(rest(handleResponseType))
	.configure(socketio())
	.configure(requestLogger)
	.use((req, res, next) => {
		// pass header into hooks.params
		// todo: To create a fake requestId on this place is a temporary solution
		// it MUST be removed after the API gateway is established
		const uid = ObjectId();
		req.headers.requestId = uid.toString();

		req.feathers.headers = req.headers;
		next();
	})
	.configure(services)
	.configure(sockets)
	.configure(middleware)
	.configure(allHooks)
	.configure(errorHandler);

module.exports = app;
<commit_msg>no more require custom schema filename<commit_after>const path = require('path');
const express = require('@feathersjs/express');
const favicon = require('serve-favicon');
const compress = require('compression');
const cors = require('cors');
const feathers = require('@feathersjs/feathers');
const configuration = require('@feathersjs/configuration');
const commons = require('@schul-cloud/commons');
const rest = require('@feathersjs/express/rest');
const bodyParser = require('body-parser');
const socketio = require('@feathersjs/socketio');
const { ObjectId } = require('mongoose').Types;

const middleware = require('./middleware');
const sockets = require('./sockets');
const services = require('./services/');

const defaultHeaders = require('./middleware/defaultHeaders');
const handleResponseType = require('./middleware/handleReponseType');
const requestLogger = require('./middleware/requestLogger');
const errorHandler = require('./middleware/errorHandler');
const sentry = require('./middleware/sentry');

const setupSwagger = require('./swagger');
const allHooks = require('./app.hooks');
const versionService = require('./services/version');

const app = express(feathers());
const config = configuration();
const Configuration = new commons.Configuration();

app.configure(config);
Configuration.init(app);
setupSwagger(app);

// set custom response header for ha proxy
if (process.env.KEEP_ALIVE) {
	app.use((req, res, next) => {
		res.setHeader('Connection', 'Keep-Alive');
		next();
	});
}

app.use(compress())
	.options('*', cors())
	.use(cors())
	.use(favicon(path.join(app.get('public'), 'favicon.ico')))
	.use('/', express.static('public'))
	.configure(sentry)
	.use(bodyParser.json())
	.use(bodyParser.urlencoded({ extended: true }))
	.use(bodyParser.raw({ type: () => true, limit: '10mb' }))
	.use(versionService)
	.use(defaultHeaders)
	.get('/system_info/haproxy', (req, res) => { res.send({ timestamp: new Date().getTime() }); })
	.get('/ping', (req, res) => { res.send({ message: 'pong', timestamp: new Date().getTime() }); })
	.configure(rest(handleResponseType))
	.configure(socketio())
	.configure(requestLogger)
	.use((req, res, next) => {
		// pass header into hooks.params
		// todo: To create a fake requestId on this place is a temporary solution
		// it MUST be removed after the API gateway is established
		const uid = ObjectId();
		req.headers.requestId = uid.toString();

		req.feathers.headers = req.headers;
		next();
	})
	.configure(services)
	.configure(sockets)
	.configure(middleware)
	.configure(allHooks)
	.configure(errorHandler);

module.exports = app;
<|endoftext|>


<commit_before>const _ = require('lodash')
const async = require('async')
const entities = require('html-entities').AllHtmlEntities
const fs = require('fs')
const ical = require('ical')
const op = require('object-path')
const parseString = require('xml2js').parseString
const path = require('path')
const request = require('request')

const interval = 1000 * 60 * 15

var getNews = (news_url, callback) => {
    request.get({url: news_url, strictSSL: true, timeout: 10000}, (err, response, body) => {
        if(err) { return callback(err) }

        parseString(body, { trim: true, normalizeTags: true, ignoreAttrs: true }, (err, result) => {
            if(err) { return callback(err) }

            const rss = op.get(result, 'rss.channel.0.item')

            let news = []
            for (let i = 0; i < rss.length; i++) {
                news.push({
                    title: op.get(rss, [i, 'title', 0]),
                    date: new Date(op.get(rss, [i, 'pubdate', 0])),
                    text: op.get(rss, [i, 'description', 0]).replace('[…]', '...'),
                    url: op.get(rss, [i, 'link', 0])
                })
            }

            callback(null, news)
        })
    })
}

var getRooms = (rooms_url, callback) => {
    request.get({url: rooms_url, strictSSL: true, json: true, timeout: 10000}, (err, response, body) => {
        if(err) { return callback(err) }

        let rooms = []
        for (let i = 0; i < body.length; i++) {
            if(!op.has(body, [i, 'properties', 'calendar', 'values', 0, 'value'])) { continue }

            rooms.push({
                title: op.get(body, [i, 'displayname']),
                info: op.get(body, [i, 'displayinfo']),
                ical: op.get(body, [i, 'properties', 'calendar', 'values', 0, 'value']),
            })
        }

        callback(null, rooms)
    })
}

var doHarvest = () => {
    console.log('')

    getNews('http://www.artun.ee/?feed=newsticker', (err, news) => {
        if (err) { return console.error(err) }

        sortedNews = _.sortBy(news, ['date'])

        fs.writeFile(path.resolve(__dirname, 'json', 'news.json'), JSON.stringify(sortedNews), 'utf8', () => {
            console.log((new Date()).toISOString(), `News: ${sortedNews.length}`);
        })
    })

    getRooms('https://eka.entu.ee/api/get_entity_list?only_public=true&full_info=true&entity_definition_keyname=room', (err, rooms) => {
        if (err) { return console.error(err) }

        console.log((new Date()).toISOString(), `Rooms: ${rooms.length}`)

        var events = []
        async.each(rooms, (room, callback) => {
            ical.fromURL(room.ical, {}, function(err, data) {
                if(err) { return callback(err) }

                for (let k in data) {
                    if (!data.hasOwnProperty(k)) { continue }
                    if (op.get(data, [k, 'type']) !== 'VEVENT') { continue }

                    events.push({
                        title: room.title,
                        info: room.info,
                        start: op.get(data, [k, 'start']),
                        end: op.get(data, [k, 'end']),
                        summary: entities.decode(op.get(data, [k, 'summary'])),
                        description: entities.decode(op.get(data, [k, 'description']))
                    })
                }

                callback(null)
            })
        }, err => {
            if (err) { return console.error(err) }

            sortedEvents = _.sortBy(events, ['start', 'end', 'title'])

            fs.writeFile(path.resolve(__dirname, 'json', 'events.json'), JSON.stringify(sortedEvents), 'utf8', () => {
                console.log((new Date()).toISOString(), `Events: ${sortedEvents.length}`)
            })
        })
    })
}

setInterval(doHarvest, interval)

doHarvest()
<commit_msg>Ignore ical errors<commit_after>const _ = require('lodash')
const async = require('async')
const entities = require('html-entities').AllHtmlEntities
const fs = require('fs')
const ical = require('ical')
const op = require('object-path')
const parseString = require('xml2js').parseString
const path = require('path')
const request = require('request')

const interval = 1000 * 60 * 15

var getNews = (news_url, callback) => {
    request.get({url: news_url, strictSSL: true, timeout: 10000}, (err, response, body) => {
        if(err) { return callback(err) }

        parseString(body, { trim: true, normalizeTags: true, ignoreAttrs: true }, (err, result) => {
            if(err) { return callback(err) }

            const rss = op.get(result, 'rss.channel.0.item')

            let news = []
            for (let i = 0; i < rss.length; i++) {
                news.push({
                    title: op.get(rss, [i, 'title', 0]),
                    date: new Date(op.get(rss, [i, 'pubdate', 0])),
                    text: op.get(rss, [i, 'description', 0]).replace('[…]', '...'),
                    url: op.get(rss, [i, 'link', 0])
                })
            }

            callback(null, news)
        })
    })
}

var getRooms = (rooms_url, callback) => {
    request.get({url: rooms_url, strictSSL: true, json: true, timeout: 10000}, (err, response, body) => {
        if(err) { return callback(err) }

        let rooms = []
        for (let i = 0; i < body.length; i++) {
            if(!op.has(body, [i, 'properties', 'calendar', 'values', 0, 'value'])) { continue }

            rooms.push({
                title: op.get(body, [i, 'displayname']),
                info: op.get(body, [i, 'displayinfo']),
                ical: op.get(body, [i, 'properties', 'calendar', 'values', 0, 'value']),
            })
        }

        callback(null, rooms)
    })
}

var doHarvest = () => {
    console.log('')

    getNews('http://www.artun.ee/?feed=newsticker', (err, news) => {
        if (err) { return console.error(err) }

        sortedNews = _.sortBy(news, ['date'])

        fs.writeFile(path.resolve(__dirname, 'json', 'news.json'), JSON.stringify(sortedNews), 'utf8', () => {
            console.log((new Date()).toISOString(), `News: ${sortedNews.length}`);
        })
    })

    getRooms('https://eka.entu.ee/api/get_entity_list?only_public=true&full_info=true&entity_definition_keyname=room', (err, rooms) => {
        if (err) { return console.error(err) }

        console.log((new Date()).toISOString(), `Rooms: ${rooms.length}`)

        var events = []
        async.each(rooms, (room, callback) => {
            ical.fromURL(room.ical, {}, function(err, data) {
                if (err) {
                    console.error(room.ical)
                    console.error(err)
                    return callback(null)
                }

                for (let k in data) {
                    if (!data.hasOwnProperty(k)) { continue }
                    if (op.get(data, [k, 'type']) !== 'VEVENT') { continue }

                    events.push({
                        title: room.title,
                        info: room.info,
                        start: op.get(data, [k, 'start']),
                        end: op.get(data, [k, 'end']),
                        summary: entities.decode(op.get(data, [k, 'summary'])),
                        description: entities.decode(op.get(data, [k, 'description']))
                    })
                }

                callback(null)
            })
        }, err => {
            if (err) { return console.error(err) }

            sortedEvents = _.sortBy(events, ['start', 'end', 'title'])

            fs.writeFile(path.resolve(__dirname, 'json', 'events.json'), JSON.stringify(sortedEvents), 'utf8', () => {
                console.log((new Date()).toISOString(), `Events: ${sortedEvents.length}`)
            })
        })
    })
}

setInterval(doHarvest, interval)

doHarvest()
<|endoftext|>