<commit_before>// Run JSHint and Plato over the specified files

var fs = require('fs');
var path = require('path');
var async = require('async');
var chalk = require('chalk');
var plato = require('plato');
var Getopt = require('node-getopt');
var buildJSHint = require('build-jshint');

var filesets = require('./lib/filesets.js');
var reporter = require('./lib/reporter.js');

// By default reports are output to `./reports` and given the title of `Plato
// Report`.

var outputDir = 'reports';

var options = {};
var jsHintOptions = {};
var platoOptions = {
    title: 'Plato Report',
    recurse: true,
    quiet: true
};

// Check the path provided by the user, prefixing it with `./` if it's not an
// explicitly provided as an absolute or relative path. Valid paths are passed
// to the provided callback.

function checkPath(string, callback, done) {
    var path = string;
    if (!(/^\.|\//).test(string)) {
        path = './' + string;
    }

    fs.stat(path, function(err) {
        if (err) {
            console.log(chalk.red('Error, cannot open: %s'), string);
            process.exit(1);
        } else {
            callback(path, done);
        }
    });
}

// Plato uses the `jshintrc` as is, whereas JSHint-Build needs the options
// inserted into its own options.

function setJSHint(path, done) {
    //var opts = require(path);
    var opts = JSON.parse(fs.readFileSync(path, 'utf8'));

    //platoOptions.jshint = path;
    jsHintOptions.config = opts;
    done();
}

// The default `jshintrc` from the linter package can be overridden with the
// `jshint` option. The provided file is checked to ensure it exists before it's
// used.

function checkJSHint(done) {
    if(!options.jshint) options.jshint = path.join(__dirname, ".jshintrc");

    checkPath(options.jshint, setJSHint, done);
}

// Set the filesets from those defined in the provided configuration file. If
// a given fileset isn't defined then a warning will be output. The `lintOnly`
// fileset is an optional fileset that will be excluded from the Plato fileset.

function setFilesets(path, done) {
    var config = JSON.parse(fs.readFileSync(path, 'utf8'));

    /* jshint sub: true */
    var includeFiles = config['includeFiles'];
    var excludeFiles = config['excludeFiles'];
    var filterFiles = config['lintOnly'];
    /* jshint sub: false */

    if (filterFiles && !Array.isArray(filterFiles)) {
        filterFiles = [];
        console.log(chalk.yellow('invalid `lintOnly` set; ignoring'));
    }

    if (includeFiles && Array.isArray(includeFiles)) {
        filesets.include(includeFiles, filterFiles);
    } else {
        console.log(chalk.yellow('valid `includeFiles` not found in %s'), path);
    }

    if (excludeFiles && Array.isArray(includeFiles)) {
        filesets.exclude(excludeFiles);
    } else {
        console.log(chalk.yellow('valid `excludeFiles` not found in %s'), path);
    }

    done();
}

// The default filesets that are used can be overridden from the command line by
// providing a configuration file with the new filesets defined. The existence
// of the configuration file is checked before the new filesets are defined.

function checkFilesets(done) {
    /* jshint sub: true */
    if (options['filesets']) {
        checkPath(options['filesets'], setFilesets, done);
    } else {
        done();
    }
    /* jshint sub: false */
}

// Run the actual reports. The plato reports are run first, then the JSHint
// report. The output is annotated with headers and details on where the reports
// are stored.

function runReports(err) {
    if (err) { console.log(chalk.red('Error running reports: %s'), err); }

    var excludes = filesets.platoExcludes();

    if (excludes) {
        platoOptions.exclude = excludes;
    }

    jsHintOptions.ignore = filesets.jshintExcludes();
    jsHintOptions.reporter = reporter.reporter;

    console.log(chalk.blue('Building plato reports...'));
    console.log(chalk.gray('(Ignore any output about being unable to parse ' +
        'JSON files)'));

    plato.inspect(filesets.platoIncludes(), outputDir, platoOptions,
        function() {
            console.log(chalk.blue('\nPlato reports have been built to: ') +
                chalk.magenta(outputDir));
            console.log(chalk.blue('\nJSHint Report\n=============\n'));
            buildJSHint(filesets.jshintIncludes(), jsHintOptions,
                reporter.callback);
        }
    );
}

// Provide options to override all the defaults from the command line

getopt = new Getopt([
    ['t', 'title=TITLE', 'The title of the report.'],
    ['o', 'output=PATH', 'The directory to output the reports to'],
    ['l', 'jshint=PATH', 'Path to a jshintrc file for JSHint linting.'],
    ['f', 'filesets=PATH',
     'Path to a file containing the filesets to report on.'],
    ['h', 'help', 'display this help text.']
]);

getopt.setHelp("Usage: node report.js [options]\n[[OPTIONS]]");
getopt.bindHelp();

// Override defaults with any options from the command line, then run the
// reports.

options = getopt.parseSystem().options;

if (options.title) {
    platoOptions.title = options.title;
}

if (options.output) {
    outputDir = options.output;
}

async.parallel([checkJSHint, checkFilesets], runReports);

// ## License
//
// Copyright (c) 2014, RainBird Technologies <follow@rainbird.ai>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.<commit_msg>removed commented code<commit_after>// Run JSHint and Plato over the specified files

var fs = require('fs');
var path = require('path');
var async = require('async');
var chalk = require('chalk');
var plato = require('plato');
var Getopt = require('node-getopt');
var buildJSHint = require('build-jshint');

var filesets = require('./lib/filesets.js');
var reporter = require('./lib/reporter.js');

// By default reports are output to `./reports` and given the title of `Plato
// Report`.

var outputDir = 'reports';

var options = {};
var jsHintOptions = {};
var platoOptions = {
    title: 'Plato Report',
    recurse: true,
    quiet: true
};

// Check the path provided by the user, prefixing it with `./` if it's not an
// explicitly provided as an absolute or relative path. Valid paths are passed
// to the provided callback.

function checkPath(string, callback, done) {
    var path = string;
    if (!(/^\.|\//).test(string)) {
        path = './' + string;
    }

    fs.stat(path, function(err) {
        if (err) {
            console.log(chalk.red('Error, cannot open: %s'), string);
            process.exit(1);
        } else {
            callback(path, done);
        }
    });
}

// Plato uses the `jshintrc` as is, whereas JSHint-Build needs the options
// inserted into its own options.

function setJSHint(path, done) {
    var opts = JSON.parse(fs.readFileSync(path, 'utf8'));

    //platoOptions.jshint = path;
    jsHintOptions.config = opts;
    done();
}

// The default `jshintrc` from the linter package can be overridden with the
// `jshint` option. The provided file is checked to ensure it exists before it's
// used.

function checkJSHint(done) {
    if(!options.jshint) options.jshint = path.join(__dirname, ".jshintrc");

    checkPath(options.jshint, setJSHint, done);
}

// Set the filesets from those defined in the provided configuration file. If
// a given fileset isn't defined then a warning will be output. The `lintOnly`
// fileset is an optional fileset that will be excluded from the Plato fileset.

function setFilesets(path, done) {
    var config = JSON.parse(fs.readFileSync(path, 'utf8'));

    /* jshint sub: true */
    var includeFiles = config['includeFiles'];
    var excludeFiles = config['excludeFiles'];
    var filterFiles = config['lintOnly'];
    /* jshint sub: false */

    if (filterFiles && !Array.isArray(filterFiles)) {
        filterFiles = [];
        console.log(chalk.yellow('invalid `lintOnly` set; ignoring'));
    }

    if (includeFiles && Array.isArray(includeFiles)) {
        filesets.include(includeFiles, filterFiles);
    } else {
        console.log(chalk.yellow('valid `includeFiles` not found in %s'), path);
    }

    if (excludeFiles && Array.isArray(includeFiles)) {
        filesets.exclude(excludeFiles);
    } else {
        console.log(chalk.yellow('valid `excludeFiles` not found in %s'), path);
    }

    done();
}

// The default filesets that are used can be overridden from the command line by
// providing a configuration file with the new filesets defined. The existence
// of the configuration file is checked before the new filesets are defined.

function checkFilesets(done) {
    /* jshint sub: true */
    if (options['filesets']) {
        checkPath(options['filesets'], setFilesets, done);
    } else {
        done();
    }
    /* jshint sub: false */
}

// Run the actual reports. The plato reports are run first, then the JSHint
// report. The output is annotated with headers and details on where the reports
// are stored.

function runReports(err) {
    if (err) { console.log(chalk.red('Error running reports: %s'), err); }

    var excludes = filesets.platoExcludes();

    if (excludes) {
        platoOptions.exclude = excludes;
    }

    jsHintOptions.ignore = filesets.jshintExcludes();
    jsHintOptions.reporter = reporter.reporter;

    console.log(chalk.blue('Building plato reports...'));
    console.log(chalk.gray('(Ignore any output about being unable to parse ' +
        'JSON files)'));

    plato.inspect(filesets.platoIncludes(), outputDir, platoOptions,
        function() {
            console.log(chalk.blue('\nPlato reports have been built to: ') +
                chalk.magenta(outputDir));
            console.log(chalk.blue('\nJSHint Report\n=============\n'));
            buildJSHint(filesets.jshintIncludes(), jsHintOptions,
                reporter.callback);
        }
    );
}

// Provide options to override all the defaults from the command line

getopt = new Getopt([
    ['t', 'title=TITLE', 'The title of the report.'],
    ['o', 'output=PATH', 'The directory to output the reports to'],
    ['l', 'jshint=PATH', 'Path to a jshintrc file for JSHint linting.'],
    ['f', 'filesets=PATH',
     'Path to a file containing the filesets to report on.'],
    ['h', 'help', 'display this help text.']
]);

getopt.setHelp("Usage: node report.js [options]\n[[OPTIONS]]");
getopt.bindHelp();

// Override defaults with any options from the command line, then run the
// reports.

options = getopt.parseSystem().options;

if (options.title) {
    platoOptions.title = options.title;
}

if (options.output) {
    outputDir = options.output;
}

async.parallel([checkJSHint, checkFilesets], runReports);

// ## License
//
// Copyright (c) 2014, RainBird Technologies <follow@rainbird.ai>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.<|endoftext|>


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

  var modules = require('modules');
  var states = require('states');
  var angular = require('angular');
  var _ = require('lodash');

  require('scripts/orchestrators/controllers/orchestrator_location_new');
  require('scripts/orchestrators/controllers/orchestrator_location_config');
  require('scripts/orchestrators/controllers/orchestrator_location_nodes');
  require('scripts/orchestrators/controllers/orchestrator_location_policies');
  require('scripts/orchestrators/controllers/orchestrator_location_secret');
  require('scripts/orchestrators/controllers/orchestrator_location_modifiers');
  require('scripts/orchestrators/controllers/orchestrator_location_metaprops');
  require('scripts/orchestrators/controllers/orchestrator_location_security');
  require('scripts/orchestrators/services/orchestrator_location_service');
  require('scripts/orchestrators/services/location_resources_processor');

  states.state('admin.orchestrators.details.locations', {
    url: '/locations',
    templateUrl: 'views/orchestrators/orchestrator_locations.html',
    controller: 'OrchestratorLocationsCtrl',
    menu: {
      id: 'menu.orchestrators.locations',
      state: 'admin.orchestrators.details.locations',
      key: 'ORCHESTRATORS.NAV.LOCATIONS',
      icon: 'fa fa-cloud',
      priority: 400
    }
  });

  modules.get('a4c-orchestrators', ['ui.router', 'ui.bootstrap', 'a4c-common']).controller('OrchestratorLocationsCtrl',
    ['$scope', '$uibModal', '$http', 'locationService', 'orchestrator', 'menu', 'locationResourcesProcessor', '$translate', '$state', 'breadcrumbsService',
      function($scope, $uibModal, $http, locationService, orchestrator, menu, locationResourcesProcessor, $translate, $state, breadcrumbsService) {

        breadcrumbsService.putConfig({
          state: 'admin.orchestrators.details.locations',
          text: function() {
            return $translate.instant('ORCHESTRATORS.NAV.LOCATIONS');
          }
        });

        $scope.envTypes = ['OTHER', 'DEVELOPMENT', 'INTEGRATION_TESTS', 'USER_ACCEPTANCE_TESTS', 'PRE_PRODUCTION', 'PRODUCTION'];
        $scope.orchestrator = orchestrator;
        $scope.menu = menu;
        var locationSupport;
        $scope.uiModel={};
        // query to get the location support informations for the orchestrator.

        $http.get('rest/latest/orchestrators/' + orchestrator.id + '/locationsupport').then(function(response) {
          if (_.defined(response.data.data)) {
            locationSupport = response.data.data;
            $scope.multipleLocations = locationSupport.multipleLocations;
            $scope.locationTypes = locationSupport.types;
          }
        });

        // get all locations (no need for paginations as we never expect a huge number of locations for an orchestrator)
        function updateLocations(toSelectName) {
          locationService.get({orchestratorId: orchestrator.id}, function(result) {
            $scope.locationsDTOs = result.data;
            if ($scope.locationsDTOs.length > 0) {
              var toSelect = toSelectName ? _.find($scope.locationsDTOs, {'location':{'name':toSelectName}}): undefined;
              $scope.selectLocation(toSelect|| $scope.locationsDTOs[0]);
              $state.go('admin.orchestrators.details.locations.secret');
            }
          });
        }

        if(orchestrator.state === 'CONNECTED') {
          updateLocations();
        }

        $scope.selectLocation = function(location) {
          locationResourcesProcessor.processLocationResources(location.resources);
          $scope.uiModel.locationDTO = location;
          $scope.context.location = location.location;
          $scope.context.locationResources = location.resources;
        };

        $scope.deleteLocation = function(location){
          locationService.delete({orchestratorId: orchestrator.id, locationId: location.location.id}, null, function(result){
            if(result.data === true){
              delete $scope.uiModel.locationDTO;
              updateLocations();
            }
          });
        };

        $scope.updateLocation = function(request) {
          if (request.name !== $scope.uiModel.locationDTO.location.name || request.environmentType !== $scope.uiModel.locationDTO.location.environmentType ) {
            return locationService.update({orchestratorId: orchestrator.id, locationId: $scope.uiModel.locationDTO.location.id}, angular.toJson(request)).$promise.then(
              function() {}, // Success
              function(errorResponse) {
                return $translate.instant('ERRORS.' + errorResponse.data.error.code);
              });
          }
        };

        $scope.openNewModal = function() {
          var modalInstance = $uibModal.open({
            templateUrl: 'views/orchestrators/orchestrator_location_new.html',
            controller: 'NewLocationController',
            resolve: {
              locationTypes: function() {
                return locationSupport.types;
              }
            }
          });

          modalInstance.result.then(function(newLocation) {
            locationService.create({orchestratorId: orchestrator.id}, angular.toJson(newLocation), function() {
              updateLocations(newLocation.name);
            });
          });
        };
      }
    ]); // controller
}); // define
<commit_msg>Remove secret tab location has default tab<commit_after>define(function(require) {
  'use strict';

  var modules = require('modules');
  var states = require('states');
  var angular = require('angular');
  var _ = require('lodash');

  require('scripts/orchestrators/controllers/orchestrator_location_new');
  require('scripts/orchestrators/controllers/orchestrator_location_config');
  require('scripts/orchestrators/controllers/orchestrator_location_nodes');
  require('scripts/orchestrators/controllers/orchestrator_location_policies');
  require('scripts/orchestrators/controllers/orchestrator_location_secret');
  require('scripts/orchestrators/controllers/orchestrator_location_modifiers');
  require('scripts/orchestrators/controllers/orchestrator_location_metaprops');
  require('scripts/orchestrators/controllers/orchestrator_location_security');
  require('scripts/orchestrators/services/orchestrator_location_service');
  require('scripts/orchestrators/services/location_resources_processor');

  states.state('admin.orchestrators.details.locations', {
    url: '/locations',
    templateUrl: 'views/orchestrators/orchestrator_locations.html',
    controller: 'OrchestratorLocationsCtrl',
    menu: {
      id: 'menu.orchestrators.locations',
      state: 'admin.orchestrators.details.locations',
      key: 'ORCHESTRATORS.NAV.LOCATIONS',
      icon: 'fa fa-cloud',
      priority: 400
    }
  });

  modules.get('a4c-orchestrators', ['ui.router', 'ui.bootstrap', 'a4c-common']).controller('OrchestratorLocationsCtrl',
    ['$scope', '$uibModal', '$http', 'locationService', 'orchestrator', 'menu', 'locationResourcesProcessor', '$translate', '$state', 'breadcrumbsService',
      function($scope, $uibModal, $http, locationService, orchestrator, menu, locationResourcesProcessor, $translate, $state, breadcrumbsService) {

        breadcrumbsService.putConfig({
          state: 'admin.orchestrators.details.locations',
          text: function() {
            return $translate.instant('ORCHESTRATORS.NAV.LOCATIONS');
          }
        });

        $scope.envTypes = ['OTHER', 'DEVELOPMENT', 'INTEGRATION_TESTS', 'USER_ACCEPTANCE_TESTS', 'PRE_PRODUCTION', 'PRODUCTION'];
        $scope.orchestrator = orchestrator;
        $scope.menu = menu;
        var locationSupport;
        $scope.uiModel={};
        // query to get the location support informations for the orchestrator.

        $http.get('rest/latest/orchestrators/' + orchestrator.id + '/locationsupport').then(function(response) {
          if (_.defined(response.data.data)) {
            locationSupport = response.data.data;
            $scope.multipleLocations = locationSupport.multipleLocations;
            $scope.locationTypes = locationSupport.types;
          }
        });

        // get all locations (no need for paginations as we never expect a huge number of locations for an orchestrator)
        function updateLocations(toSelectName) {
          locationService.get({orchestratorId: orchestrator.id}, function(result) {
            $scope.locationsDTOs = result.data;
            if ($scope.locationsDTOs.length > 0) {
              var toSelect = toSelectName ? _.find($scope.locationsDTOs, {'location':{'name':toSelectName}}): undefined;
              $scope.selectLocation(toSelect|| $scope.locationsDTOs[0]);
              $state.go('admin.orchestrators.details.locations.config');
            }
          });
        }

        if(orchestrator.state === 'CONNECTED') {
          updateLocations();
        }

        $scope.selectLocation = function(location) {
          locationResourcesProcessor.processLocationResources(location.resources);
          $scope.uiModel.locationDTO = location;
          $scope.context.location = location.location;
          $scope.context.locationResources = location.resources;
        };

        $scope.deleteLocation = function(location){
          locationService.delete({orchestratorId: orchestrator.id, locationId: location.location.id}, null, function(result){
            if(result.data === true){
              delete $scope.uiModel.locationDTO;
              updateLocations();
            }
          });
        };

        $scope.updateLocation = function(request) {
          if (request.name !== $scope.uiModel.locationDTO.location.name || request.environmentType !== $scope.uiModel.locationDTO.location.environmentType ) {
            return locationService.update({orchestratorId: orchestrator.id, locationId: $scope.uiModel.locationDTO.location.id}, angular.toJson(request)).$promise.then(
              function() {}, // Success
              function(errorResponse) {
                return $translate.instant('ERRORS.' + errorResponse.data.error.code);
              });
          }
        };

        $scope.openNewModal = function() {
          var modalInstance = $uibModal.open({
            templateUrl: 'views/orchestrators/orchestrator_location_new.html',
            controller: 'NewLocationController',
            resolve: {
              locationTypes: function() {
                return locationSupport.types;
              }
            }
          });

          modalInstance.result.then(function(newLocation) {
            locationService.create({orchestratorId: orchestrator.id}, angular.toJson(newLocation), function() {
              updateLocations(newLocation.name);
            });
          });
        };
      }
    ]); // controller
}); // define
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { ButtonGroup, Button, classnames } from 'react-components';
import { CURRENCIES, CYCLE } from 'proton-shared/lib/constants';

const { MONTHLY, YEARLY, TWO_YEARS } = CYCLE;

const PlansGroupButtons = ({ plans, onSelectPlan, model, ...rest }) => {
    return (
        <ButtonGroup {...rest} className="w100">
            {plans.map(({ planName, title }) => {
                return (
                    <Button
                        group
                        key={planName}
                        className={classnames(['flex-item-fluid', planName === model.planName && 'is-active'])}
                        onClick={() => onSelectPlan({ ...model, planName })}
                    >
                        {title}
                    </Button>
                );
            })}
        </ButtonGroup>
    );
};

PlansGroupButtons.propTypes = {
    plans: PropTypes.arrayOf(PropTypes.object).isRequired,
    onSelectPlan: PropTypes.func.isRequired,
    model: PropTypes.shape({
        planName: PropTypes.string.isRequired,
        cycle: PropTypes.oneOf([MONTHLY, TWO_YEARS, YEARLY]).isRequired,
        currency: PropTypes.oneOf(CURRENCIES).isRequired,
    }).isRequired,
};

export default PlansGroupButtons;
<commit_msg>Spread ButtonGroup component<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { ButtonGroup, Button, classnames } from 'react-components';
import { CURRENCIES, CYCLE } from 'proton-shared/lib/constants';

const { MONTHLY, YEARLY, TWO_YEARS } = CYCLE;

const PlansGroupButtons = ({ plans, onSelectPlan, model, ...rest }) => {
    return (
        <ButtonGroup {...rest} className="w100">
            {plans.map(({ planName, title }) => {
                return (
                    <Button
                        key={planName}
                        className={classnames(['flex-item-fluid', planName === model.planName && 'is-selected'])}
                        onClick={() => onSelectPlan({ ...model, planName })}
                    >
                        {title}
                    </Button>
                );
            })}
        </ButtonGroup>
    );
};

PlansGroupButtons.propTypes = {
    plans: PropTypes.arrayOf(PropTypes.object).isRequired,
    onSelectPlan: PropTypes.func.isRequired,
    model: PropTypes.shape({
        planName: PropTypes.string.isRequired,
        cycle: PropTypes.oneOf([MONTHLY, TWO_YEARS, YEARLY]).isRequired,
        currency: PropTypes.oneOf(CURRENCIES).isRequired,
    }).isRequired,
};

export default PlansGroupButtons;
<|endoftext|>


<commit_before>'use strict'

const { getMhub } = require('./.get/get-mhub')
const { getCaddy } = require('./.get/get-caddy')
const { getMongo } = require('./.get/get-mongo')
const { getNpmModule } = require('./.get/get-npm-module')
const { getByHttp } = require('./.get/get-by-http')

// eslint-disable-next-line node/exports-style
module.exports = {
  modules: {
    caddy: {
      internal: true,
      get: getCaddy
    },
    mongo: {
      internal: true,
      get: getMongo
    },
    mhub: {
      internal: true,
      get: getMhub,
      options: {
        package: 'mhub',
        version: '0.9.1'
      }
    },
    'identity-provider': {
      get: getNpmModule,
      options: {
        version: 'FirstLegoLeague/identity-provider#50e95cc'
      }
    },
    display: {
      get: getNpmModule,
      options: {
        package: '@first-lego-league/display',
        version: '2.0.0'
      }
    },
    tournament: {
      get: getNpmModule,
      options: {
        package: '@first-lego-league/tournament',
        version: '0.5.0-alpha-2'
      }
    },
    scoring: {
      get: getNpmModule,
      options: {
        version: 'FirstLegoLeague/scoring#ead6980'
      }
    },
    rankings: {
      get: getNpmModule,
      options: {
        version: 'FirstLegoLeague/rankings#6d500ab'
      }
    },
    clock: {
      get: getNpmModule,
      options: {
        package: '@first-lego-league/clock',
        version: '2.0.4'
      }
    }
  },
  custom: {
    npm: getNpmModule,
    http: getByHttp
  }
}
<commit_msg>Working display and rankings versions<commit_after>'use strict'

const { getMhub } = require('./.get/get-mhub')
const { getCaddy } = require('./.get/get-caddy')
const { getMongo } = require('./.get/get-mongo')
const { getNpmModule } = require('./.get/get-npm-module')
const { getByHttp } = require('./.get/get-by-http')

// eslint-disable-next-line node/exports-style
module.exports = {
  modules: {
    caddy: {
      internal: true,
      get: getCaddy
    },
    mongo: {
      internal: true,
      get: getMongo
    },
    mhub: {
      internal: true,
      get: getMhub,
      options: {
        package: 'mhub',
        version: '0.9.1'
      }
    },
    'identity-provider': {
      get: getNpmModule,
      options: {
        version: 'FirstLegoLeague/identity-provider#50e95cc'
      }
    },
    display: {
      get: getNpmModule,
      options: {
        package: '@first-lego-league/display',
        version: '2.0.3'
      }
    },
    tournament: {
      get: getNpmModule,
      options: {
        package: '@first-lego-league/tournament',
        version: '0.5.0-alpha-2'
      }
    },
    scoring: {
      get: getNpmModule,
      options: {
        version: 'FirstLegoLeague/scoring#ead6980'
      }
    },
    rankings: {
      get: getNpmModule,
      options: {
        version: 'FirstLegoLeague/rankings#851c98'
      }
    },
    clock: {
      get: getNpmModule,
      options: {
        package: '@first-lego-league/clock',
        version: '2.0.4'
      }
    }
  },
  custom: {
    npm: getNpmModule,
    http: getByHttp
  }
}
<|endoftext|>


<commit_before>var App_post = {};
var $form = null;
function init_post(obj) {
    $form = $('#form-post');

    if (obj.recover_draft == "true") {
        $form.css('opacity', 0).before('
' + I18n("msg.recover") + '
');
    }

    var _draft_inited = false;
    var class_translate = ".translate-item";

    var post_id = obj.post_id;
    var post_draft_id = obj.post_draft_id;
    var post_status = obj.post_status;
    var _drafts_path = obj._drafts_path;
    var _posts_path = obj._posts_path;
    var _ajax_path = obj._ajax_path;
    var _post_tags_path = obj._post_tags_path;

    App_post.save_draft_ajax = function (callback, called_from_interval) {
        _draft_inited = true;
        var data = $form.serializeObject();
        data._method = post_draft_id ? 'patch' : 'post';
        data.post_id = post_id;
        if ($form.data("hash") != get_hash_form() || !called_from_interval) {
            $.ajax({
                type: 'POST',
                url: _drafts_path,
                data: data,
                success: function (res) {
                    if (res.error) {
                        $.fn.alert({type: 'error', title: res.error.join(", "), icon: "times"})
                    } else {
                        if (res._drafts_path) _drafts_path = res._drafts_path
                        post_draft_id = res.draft.id
                        $("#post_draft_id").val(post_draft_id);
                    }
                    if (callback) callback(res);
                },
                dataType: 'json',
                async: false
            });
        }

    };

    App_post.save_draft = function () {
        App_post.save_draft_ajax(function () {
            $form.data("submitted", 1);
            location.href = _posts_path + '?flash[notice]=' + I18n("msg.draft")
        });

    }
    if(window["post_editor_draft_intrval"]) clearInterval(window["post_editor_draft_intrval"]);
    window["post_editor_draft_intrval"] = setInterval(function () { if($form.length == 0){ clearInterval(window["post_editor_draft_intrval"]); } else{ App_post.save_draft_ajax(null, true); } }, 3 * 60 * 1000);
    window.save_draft = App_post.save_draft_ajax;

    if($form.find(".title-post" + class_translate).size() == 0) class_translate = '';
    $form.find(".title-post" + class_translate).each(function () {
        var $this = $(this);
        if (!$this.hasClass('sluged')) {
            if (class_translate) {
                var lng = $this.attr("data-translation_l");
                var $input_slug = $form.find('.slug-post' + class_translate + '[data-translation_l="' + lng + '"]');
                var post_path = obj._post_urls[lng];
            } else {
                var $input_slug = $form.find('.slug-post');
                var post_path = obj._post_urls[Object.keys(obj._post_urls)[0]];
            }

            var $link = $('
' +
                '' + I18n("msg.permalink") + ':     ' +
                '' + I18n("button.edit") + '    ' +
                '' + I18n("msg.preview") + '    ' +
                '' + I18n("msg.view_page") + '' +
                '
').hide();
            $this.addClass('sluged');
            $this.after($link)

            function set_slug(slug) {
                $link.show().find('.sl-link').html(post_path.replace('__-__', '' + slug + ''))
                $link.find('.btn-preview').attr('href', post_path.replace('__-__', slug) + '?draft_id=' + post_draft_id)
                $input_slug.trigger('change_in');
                set_meta_slug();
            }

            var xhr = null;

            function ajax_set_slug(slug) {
                if (xhr) xhr.abort();
                xhr = $.ajax({
                    type: "POST",
                    url: _ajax_path,
                    data: {method: 'exist_slug', slug: slug, post_id: post_id},
                    success: function (res) {
                        if (res.index > 0) {
                            $input_slug.addClass('slugify-locked').val(res.slug);
                            set_slug(res.slug)
                        }

                    }
                });
            }

            function set_meta_slug() {
                $('#meta_slug').val($form.find('.slug-post' + class_translate).map(function () { return this.value; }).get().join(","));
            }

            var slug_tmp = null;
            $input_slug.slugify($this, {
                    change: function (slug) {
                        slug_tmp = slug;
                        set_slug(slug);
                    }
                }
            );

            $this.change(function () {
                if (slug_tmp) ajax_set_slug(slug_tmp);
            });
            if ($input_slug.val()) {
                set_slug($input_slug.val());
                if (post_status == "published") $link.find('.btn-view').show().attr('href', post_path.replace('__-__', $input_slug.val()))
            }
            $link.find('.btn-preview').click(function () { // preview button
                var link = $(this);
                showLoading();
                App_post.save_draft_ajax(function(){
                    hideLoading();
                    var ar = link.attr("href").split("draft_id=");
                    ar[1] = post_draft_id;
                    var clone = link.clone().hide();
                    clone.insertAfter(link).attr('href', ar.join("draft_id="))[0].click();
                    clone.remove();
                });
                return false;
            });
            $link.find('.btn-edit').click(function () {
                var $btn = $(this);
                var $btn_edit = $('' + I18n("button.accept") + '   ' + I18n("button.cancel") + '');
                var $label = $link.find('.sl-url');
                var $input = $("<input type='text' />");
                $label.hide().after($input);
                $btn.hide().after($btn_edit);
                $input.val($label.text());

                function set_delete() {
                    $label.show();
                    $btn.show();
                    $input.remove();
                    $btn_edit.remove();
                }

                $btn_edit.filter('.btn-cancel').click(function () {
                    set_delete();
                    set_meta_slug()
                    return false;
                });
                $btn_edit.filter('.btn-edit').click(function () {
                    var value_new_slug = slugFunc($input.val());
                    if (value_new_slug) {
                        $input_slug.addClass('slugify-locked').val(value_new_slug);
                        ajax_set_slug(value_new_slug)
                        set_slug(value_new_slug)
                        set_delete();
                    }
                    return false;
                });
                return false;
            });
        }
    });

    try{$(".tinymce_textarea:not(.translated-item)", $form).tinymce().destroy();}catch(e){}
    tinymce.init(cama_get_tinymce_settings({
        selector: '.tinymce_textarea:not(.translated-item)',
        height: '480px',
        onPostRender: onEditorPostRender,
        base_path: obj.base_path
    }));

    $form.validate();
    $("#post_status").change(function () {
        $('#post-actions .btn[data-type]').hide();
        $('#post-actions .btn[data-type="' + $(this).val() + '"]').show();
    });

    // here all later actions
    var form_later_actions = function () {
        /*********** scroller (fix buttons position) ***************/
        var panel_scroll = $("#form-post > #post_right_bar");
        var fixed_position = panel_scroll.children(":first");
        var fixed_offset_top = panel_scroll.offset().top;
        $(window).scroll(function () {
            if ($(window).width() < 1024) {
                fixed_position.css({position: "", width: ""});
                panel_scroll.css("padding-top", "");
                return;
            }
            if ($(window).scrollTop() >= fixed_offset_top + 10) {
                fixed_position.css({position: "fixed", width: "279px", top: 0, "z-index": 4});
                panel_scroll.css("padding-top", fixed_position.height() + 20)
            } else {
                fixed_position.css({position: "", width: "auto"});
                panel_scroll.css("padding-top", "")
            }
        }).resize(function () {
            if ($(window).width() >= 1024) {
                panel_scroll.show();
            }
        }).scroll();
        /*********** end scroller buttons ***************/

        /********** post tagEditor ******************/
        var post_tags = $.ajax({
            type: 'GET',
            url: _post_tags_path,
            dataType: "json",
            async: false
        }).responseText;

        $form.find(".tagsinput").tagEditor({
            autocomplete: {delay: 0, position: {collision: 'flip'}, source: $.parseJSON(post_tags)},
            forceLowercase: false,
            placeholder: I18n("button.add_tag") + '...'
        });
        /********** end post tagEditor **************/
            ////// thumbnail
        $form.on("click", ".gallery-item-remove", function () {
            $('#feature-image').hide();
            $('#feature-image input').val('');
            return false;
        });

        // sidebar toggle
        //$("#admin_content #post_right_bar-toggle").on("click", function () {
        //    $("#post_right_bar").is(":visible") ? $("#post_right_bar").hide() : $("#post_right_bar").show();
        //});

        /*********** control save changes before unload form. ***************/
        $form.submit(function () {
            if ($(this).valid()) $form.data("submitted", 1);
        });
        window.onbeforeunload = function () {
            if ($form.data("submitted"))
                return;
            if ($form.data("hash") != get_hash_form()) {
                return "You sure to leave the page without saving changes?";
            }
            if (!$form.data("submitted"))
                return;
            return "You sure to leave the page without saving changes?";
        };

        /*********** link to create categories *************/
        $form.find("#post_add_new_category").ajax_modal({modal_size: 'modal-lg', mode: 'iframe', callback: function(modal){
            modal.find('iframe').on('load', function(){
                $(this).contents().find("#main-header, #sidebar-menu, #main-footer").hide();
                $(this).contents().find('#admin_content').parent().css("margin-left", 0);
            });
        }, on_close: function(modal){
            var panel_cats = $form.find("#post_right_bar .list-categories");
            $.get($form.find("#post_add_new_category").data('reload-url'), {categories: panel_cats.find("input:checkbox:checked").map(function(i, el){ return $(this).val(); }).get()}, function(res){ panel_cats.html(res); });
        }});
        /*********** end *************/
    }
    setTimeout(form_later_actions, 1000);

    // wait for render editors
    var wait_render;

    function onEditorPostRender(editor) {
        if (wait_render) clearTimeout(wait_render);
        wait_render = setTimeout(function () {
            $form.data("hash", get_hash_form());
        }, 1000);
    }

    function get_hash_form() {
        for (editor in tinymce.editors) {
            editor = tinymce.editors[editor];
            var i = $("#" + editor.id).val(tinymce.get(editor.id).getContent()).trigger("change");
        }
        return $form.serialize();
    }

    if (obj.recover_draft == "true") {
        $form.data("validator").cancelSubmit = true;
        $('#post_status').val('published');
        $form.submit();
    }
}

// thumbnail updloader
function upload_feature_image(data) {
    $.fn.upload_filemanager($.extend({
        formats: "image",
        selected: function (image) {
            var image_url = image.url;
            $('#feature-image img').attr('src', image_url);
            $('#feature-image input').val(image_url);
            $('#feature-image .meta strong').html(image.name);
            $('#feature-image').show();
        }
    }, data));
}<commit_msg>modified the time for post editor of changed content verification<commit_after>var App_post = {};
var $form = null;
function init_post(obj) {
    $form = $('#form-post');

    if (obj.recover_draft == "true") {
        $form.css('opacity', 0).before('
' + I18n("msg.recover") + '
');
    }

    var _draft_inited = false;
    var class_translate = ".translate-item";

    var post_id = obj.post_id;
    var post_draft_id = obj.post_draft_id;
    var post_status = obj.post_status;
    var _drafts_path = obj._drafts_path;
    var _posts_path = obj._posts_path;
    var _ajax_path = obj._ajax_path;
    var _post_tags_path = obj._post_tags_path;

    App_post.save_draft_ajax = function (callback, called_from_interval) {
        _draft_inited = true;
        var data = $form.serializeObject();
        data._method = post_draft_id ? 'patch' : 'post';
        data.post_id = post_id;
        if ($form.data("hash") != get_hash_form() || !called_from_interval) {
            $.ajax({
                type: 'POST',
                url: _drafts_path,
                data: data,
                success: function (res) {
                    if (res.error) {
                        $.fn.alert({type: 'error', title: res.error.join(", "), icon: "times"})
                    } else {
                        if (res._drafts_path) _drafts_path = res._drafts_path
                        post_draft_id = res.draft.id
                        $("#post_draft_id").val(post_draft_id);
                    }
                    if (callback) callback(res);
                },
                dataType: 'json',
                async: false
            });
        }

    };

    App_post.save_draft = function () {
        App_post.save_draft_ajax(function () {
            $form.data("submitted", 1);
            location.href = _posts_path + '?flash[notice]=' + I18n("msg.draft")
        });

    }
    if(window["post_editor_draft_intrval"]) clearInterval(window["post_editor_draft_intrval"]);
    window["post_editor_draft_intrval"] = setInterval(function () { if($form.length == 0){ clearInterval(window["post_editor_draft_intrval"]); } else{ App_post.save_draft_ajax(null, true); } }, 3 * 60 * 1000);
    window.save_draft = App_post.save_draft_ajax;

    if($form.find(".title-post" + class_translate).size() == 0) class_translate = '';
    $form.find(".title-post" + class_translate).each(function () {
        var $this = $(this);
        if (!$this.hasClass('sluged')) {
            if (class_translate) {
                var lng = $this.attr("data-translation_l");
                var $input_slug = $form.find('.slug-post' + class_translate + '[data-translation_l="' + lng + '"]');
                var post_path = obj._post_urls[lng];
            } else {
                var $input_slug = $form.find('.slug-post');
                var post_path = obj._post_urls[Object.keys(obj._post_urls)[0]];
            }

            var $link = $('
' +
                '' + I18n("msg.permalink") + ':     ' +
                '' + I18n("button.edit") + '    ' +
                '' + I18n("msg.preview") + '    ' +
                '' + I18n("msg.view_page") + '' +
                '
').hide();
            $this.addClass('sluged');
            $this.after($link)

            function set_slug(slug) {
                $link.show().find('.sl-link').html(post_path.replace('__-__', '' + slug + ''))
                $link.find('.btn-preview').attr('href', post_path.replace('__-__', slug) + '?draft_id=' + post_draft_id)
                $input_slug.trigger('change_in');
                set_meta_slug();
            }

            var xhr = null;

            function ajax_set_slug(slug) {
                if (xhr) xhr.abort();
                xhr = $.ajax({
                    type: "POST",
                    url: _ajax_path,
                    data: {method: 'exist_slug', slug: slug, post_id: post_id},
                    success: function (res) {
                        if (res.index > 0) {
                            $input_slug.addClass('slugify-locked').val(res.slug);
                            set_slug(res.slug)
                        }

                    }
                });
            }

            function set_meta_slug() {
                $('#meta_slug').val($form.find('.slug-post' + class_translate).map(function () { return this.value; }).get().join(","));
            }

            var slug_tmp = null;
            $input_slug.slugify($this, {
                    change: function (slug) {
                        slug_tmp = slug;
                        set_slug(slug);
                    }
                }
            );

            $this.change(function () {
                if (slug_tmp) ajax_set_slug(slug_tmp);
            });
            if ($input_slug.val()) {
                set_slug($input_slug.val());
                if (post_status == "published") $link.find('.btn-view').show().attr('href', post_path.replace('__-__', $input_slug.val()))
            }
            $link.find('.btn-preview').click(function () { // preview button
                var link = $(this);
                showLoading();
                App_post.save_draft_ajax(function(){
                    hideLoading();
                    var ar = link.attr("href").split("draft_id=");
                    ar[1] = post_draft_id;
                    var clone = link.clone().hide();
                    clone.insertAfter(link).attr('href', ar.join("draft_id="))[0].click();
                    clone.remove();
                });
                return false;
            });
            $link.find('.btn-edit').click(function () {
                var $btn = $(this);
                var $btn_edit = $('' + I18n("button.accept") + '   ' + I18n("button.cancel") + '');
                var $label = $link.find('.sl-url');
                var $input = $("<input type='text' />");
                $label.hide().after($input);
                $btn.hide().after($btn_edit);
                $input.val($label.text());

                function set_delete() {
                    $label.show();
                    $btn.show();
                    $input.remove();
                    $btn_edit.remove();
                }

                $btn_edit.filter('.btn-cancel').click(function () {
                    set_delete();
                    set_meta_slug()
                    return false;
                });
                $btn_edit.filter('.btn-edit').click(function () {
                    var value_new_slug = slugFunc($input.val());
                    if (value_new_slug) {
                        $input_slug.addClass('slugify-locked').val(value_new_slug);
                        ajax_set_slug(value_new_slug)
                        set_slug(value_new_slug)
                        set_delete();
                    }
                    return false;
                });
                return false;
            });
        }
    });

    try{$(".tinymce_textarea:not(.translated-item)", $form).tinymce().destroy();}catch(e){}
    tinymce.init(cama_get_tinymce_settings({
        selector: '.tinymce_textarea:not(.translated-item)',
        height: '480px',
        onPostRender: onEditorPostRender,
        base_path: obj.base_path
    }));

    $form.validate();
    $("#post_status").change(function () {
        $('#post-actions .btn[data-type]').hide();
        $('#post-actions .btn[data-type="' + $(this).val() + '"]').show();
    });

    // here all later actions
    var form_later_actions = function () {
        /*********** scroller (fix buttons position) ***************/
        var panel_scroll = $("#form-post > #post_right_bar");
        var fixed_position = panel_scroll.children(":first");
        var fixed_offset_top = panel_scroll.offset().top;
        $(window).scroll(function () {
            if ($(window).width() < 1024) {
                fixed_position.css({position: "", width: ""});
                panel_scroll.css("padding-top", "");
                return;
            }
            if ($(window).scrollTop() >= fixed_offset_top + 10) {
                fixed_position.css({position: "fixed", width: "279px", top: 0, "z-index": 4});
                panel_scroll.css("padding-top", fixed_position.height() + 20)
            } else {
                fixed_position.css({position: "", width: "auto"});
                panel_scroll.css("padding-top", "")
            }
        }).resize(function () {
            if ($(window).width() >= 1024) {
                panel_scroll.show();
            }
        }).scroll();
        /*********** end scroller buttons ***************/

        /********** post tagEditor ******************/
        var post_tags = $.ajax({
            type: 'GET',
            url: _post_tags_path,
            dataType: "json",
            async: false
        }).responseText;

        $form.find(".tagsinput").tagEditor({
            autocomplete: {delay: 0, position: {collision: 'flip'}, source: $.parseJSON(post_tags)},
            forceLowercase: false,
            placeholder: I18n("button.add_tag") + '...'
        });
        /********** end post tagEditor **************/
            ////// thumbnail
        $form.on("click", ".gallery-item-remove", function () {
            $('#feature-image').hide();
            $('#feature-image input').val('');
            return false;
        });

        // sidebar toggle
        //$("#admin_content #post_right_bar-toggle").on("click", function () {
        //    $("#post_right_bar").is(":visible") ? $("#post_right_bar").hide() : $("#post_right_bar").show();
        //});

        /*********** control save changes before unload form. ***************/
        $form.submit(function () {
            if ($(this).valid()) $form.data("submitted", 1);
        });
        window.onbeforeunload = function () {
            if ($form.data("submitted"))
                return;
            if ($form.data("hash") != get_hash_form()) {
                return "You sure to leave the page without saving changes?";
            }
            if (!$form.data("submitted"))
                return;
            return "You sure to leave the page without saving changes?";
        };

        /*********** link to create categories *************/
        $form.find("#post_add_new_category").ajax_modal({modal_size: 'modal-lg', mode: 'iframe', callback: function(modal){
            modal.find('iframe').on('load', function(){
                $(this).contents().find("#main-header, #sidebar-menu, #main-footer").hide();
                $(this).contents().find('#admin_content').parent().css("margin-left", 0);
            });
        }, on_close: function(modal){
            var panel_cats = $form.find("#post_right_bar .list-categories");
            $.get($form.find("#post_add_new_category").data('reload-url'), {categories: panel_cats.find("input:checkbox:checked").map(function(i, el){ return $(this).val(); }).get()}, function(res){ panel_cats.html(res); });
        }});
        /*********** end *************/
    }
    setTimeout(form_later_actions, 1000);
    setTimeout(function(){ $form.data("hash", get_hash_form()); }, 4000);

    function get_hash_form() {
        for (editor in tinymce.editors) {
            editor = tinymce.editors[editor];
            var i = $("#" + editor.id).val(tinymce.get(editor.id).getContent()).trigger("change");
        }
        return $form.serialize();
    }

    if (obj.recover_draft == "true") {
        $form.data("validator").cancelSubmit = true;
        $('#post_status').val('published');
        $form.submit();
    }
}

// thumbnail updloader
function upload_feature_image(data) {
    $.fn.upload_filemanager($.extend({
        formats: "image",
        selected: function (image) {
            var image_url = image.url;
            $('#feature-image img').attr('src', image_url);
            $('#feature-image input').val(image_url);
            $('#feature-image .meta strong').html(image.name);
            $('#feature-image').show();
        }
    }, data));
}<|endoftext|>


<commit_before>import alt from 'alt';
import React from 'react';
import AutoCompleteInput from './AutoCompleteInput';
import {Button, Input, DropdownButton, MenuItem} from 'react-bootstrap';

import SuggestionsFetcher from '../fetchers/SuggestionsFetcher';
import SuggestionActions from '../actions/SuggestionActions';
import SuggestionStore from '../stores/SuggestionStore';
import ElementActions from '../actions/ElementActions';
import UIStore from '../stores/UIStore';
import UIActions from '../actions/UIActions';

export default class Search extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      elementType: 'all'
    }
  }

  handleSelectionChange(selection) {
    selection.elementType = this.state.elementType;
    UIActions.setSearchSelection(selection);

    let uiState = UIStore.getState();
    ElementActions.fetchBasedOnSearchSelectionAndCollection(selection, uiState.currentCollection.id);
  }

  search(query) {
    let promise = SuggestionsFetcher.fetchSuggestions('/api/v1/suggestions/' + this.state.elementType + '/', query);
    return promise;
  }

  handleClearSearchSelection() {
    let uiState = UIStore.getState();

    this.refs.autoComplete.setState({
      value: ''
    })

    UIActions.selectCollection({id: uiState.currentCollection.id});
    UIActions.clearSearchSelection();
  }

  handleElementSelection(event) {
    this.setState({
      elementType: event
    })
  }

  renderMenuItems() {
    let elements = ["all", "samples", "reactions", "wellplates", "screens"];
    return elements.map((element, index) => {
      return (
        <MenuItem key={element} onSelect={() => this.handleElementSelection(element)}>
          {element}
        </MenuItem>
      );
    });
  }

  render() {
    let searchButton = <Button bsStyle="danger" onClick={() => this.handleClearSearchSelection()}></Button>;

    let inputAttributes = {
      placeholder: 'Search for elements...',
      buttonAfter: searchButton,
      style: {
        width: 300
      }
    };

    let suggestionsAttributes = {
      style: {
        marginTop: 15,
        width: 300
      }
    };

    let innerDropdown =
      <DropdownButton title={this.state.elementType}>
        {this.renderMenuItems()}
      </DropdownButton>

    return (

          <AutoCompleteInput inputAttributes={inputAttributes}
                             suggestionsAttributes={suggestionsAttributes}
                             suggestions={input => this.search(input)}
                             ref="autoComplete"
                             onSelectionChange={selection => this.handleSelectionChange(selection)}
                             buttonBefore={innerDropdown}/>

    );
  }
}
<commit_msg>Fix width details<commit_after>import alt from 'alt';
import React from 'react';
import AutoCompleteInput from './AutoCompleteInput';
import {Button, Input, DropdownButton, MenuItem} from 'react-bootstrap';

import SuggestionsFetcher from '../fetchers/SuggestionsFetcher';
import SuggestionActions from '../actions/SuggestionActions';
import SuggestionStore from '../stores/SuggestionStore';
import ElementActions from '../actions/ElementActions';
import UIStore from '../stores/UIStore';
import UIActions from '../actions/UIActions';

export default class Search extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      elementType: 'all'
    }
  }

  handleSelectionChange(selection) {
    selection.elementType = this.state.elementType;
    UIActions.setSearchSelection(selection);

    let uiState = UIStore.getState();
    ElementActions.fetchBasedOnSearchSelectionAndCollection(selection, uiState.currentCollection.id);
  }

  search(query) {
    let promise = SuggestionsFetcher.fetchSuggestions('/api/v1/suggestions/' + this.state.elementType + '/', query);
    return promise;
  }

  handleClearSearchSelection() {
    let uiState = UIStore.getState();

    this.refs.autoComplete.setState({
      value: ''
    })

    UIActions.selectCollection({id: uiState.currentCollection.id});
    UIActions.clearSearchSelection();
  }

  handleElementSelection(event) {
    this.setState({
      elementType: event
    })
  }

  renderMenuItems() {
    let elements = ["all", "samples", "reactions", "wellplates", "screens"];
    return elements.map((element, index) => {
      return (
        <MenuItem key={element} onSelect={() => this.handleElementSelection(element)}>
          {element}
        </MenuItem>
      );
    });
  }

  render() {
    let searchButton = <Button bsStyle="danger" onClick={() => this.handleClearSearchSelection()}></Button>;

    let inputAttributes = {
      placeholder: 'Search for elements...',
      buttonAfter: searchButton,
      style: {
        width: 300
      }
    };

    let suggestionsAttributes = {
      style: {
        marginTop: 15,
        width: 400
      }
    };

    let innerDropdown =
      <DropdownButton title={this.state.elementType} style={{width:'100px'}}>
        {this.renderMenuItems()}
      </DropdownButton>

    return (

          <AutoCompleteInput inputAttributes={inputAttributes}
                             suggestionsAttributes={suggestionsAttributes}
                             suggestions={input => this.search(input)}
                             ref="autoComplete"
                             onSelectionChange={selection => this.handleSelectionChange(selection)}
                             buttonBefore={innerDropdown}/>

    );
  }
}
<|endoftext|>


<commit_before>import React from 'react';

const styles = {
  button: {
    marginTop: '10px',
    display: 'inline'
  },
  feed: {
    margin: 'auto 10%'
  },
  footer: {
    margin: '5% 41%'
  },
  header: {
    margin: '2.5% 5%'
  },
  subTitle: {
    fontSize: '18px',
    marginTop: '5px'
  },
  title: {
    fontSize: '28px',
    fontWeight: 'bold',
    color: '#155094'
  },
};

class NotesFeedPage extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    const NotesList = window.shared.NotesList;
    const feed = {
      event_notes: this.props.eventNotes,
      deprecated: {
        interventions: []
      },
      services: {
        active: [],
        discontinued: []
      }
    };

    return (

            My Notes

          {/* TODO: change text to reflect what is actually being displayed */}

 Past {this.props.eventNotes.length} notes.

            <NotesList
              educatorsIndex={this.props.educatorsIndex}
              eventNoteTypesIndex={this.props.eventNoteTypesIndex}
              feed={feed} />

          <button
            className="btn load-more-notes"
            style={styles.button}
            onClick={this.props.onClickLoadMoreNotes}>
            Load 30 More Notes
          </button>

    );
  }
}

NotesFeedPage.propTypes = {
  educatorsIndex: React.PropTypes.object.isRequired,
  eventNotes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
  eventNoteTypesIndex: React.PropTypes.object.isRequired,
  onClickLoadMoreNotes: React.PropTypes.func.isRequired
};

export default NotesFeedPage;
<commit_msg><commit_after>import React from 'react';

const styles = {
  button: {
    marginTop: '10px',
    display: 'inline'
  },
  feed: {
    margin: 'auto 10%'
  },
  footer: {
    margin: '5% 41%'
  },
  header: {
    margin: '2.5% 5%'
  },
  subTitle: {
    fontSize: '18px',
    marginTop: '5px'
  },
  title: {
    fontSize: '28px',
    fontWeight: 'bold',
    color: '#155094'
  },
};

class NotesFeedPage extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    const NotesList = window.shared.NotesList;
    const feed = {
      event_notes: this.props.eventNotes,
      deprecated: {
        interventions: []
      },
      services: {
        active: [],
        discontinued: []
      }
    };

    return (

            My Notes

 Past {this.props.eventNotes.length} notes.

            <NotesList
              educatorsIndex={this.props.educatorsIndex}
              eventNoteTypesIndex={this.props.eventNoteTypesIndex}
              feed={feed} />

          <button
            className="btn load-more-notes"
            style={styles.button}
            onClick={this.props.onClickLoadMoreNotes}>
            Load 30 More Notes
          </button>

    );
  }
}

NotesFeedPage.propTypes = {
  educatorsIndex: React.PropTypes.object.isRequired,
  eventNotes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
  eventNoteTypesIndex: React.PropTypes.object.isRequired,
  onClickLoadMoreNotes: React.PropTypes.func.isRequired
};

export default NotesFeedPage;
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Language Technology Group and Interactive Graphics Systems Group, Technische Universität Darmstadt, Germany
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

define([
    'angular',
    'jquery-json'
], function (angular) {
    'use strict';

    angular.module("myApp.observer", ['play.routing'])
        .factory('ObserverService', ['playRoutes', '$q', function(playRoutes, $q) {
            // Stores callback instances consisting of a callback method and a priority number
            var observerCallbacks = [];
            //holds subscriber functions
            var subscriber = [];
            //all items in order
            var history = [];
            //all item structured by type
            var items = {};
            //types of tracked items
            // TODO: expandNode, egoNetwork not used. Remove them. Make sure index of types still fits! Better don't access via index ...
            var types = ["entity", "metadata", "time", "expandNode", "egoNetwork", "merge", "hide", "edit", "annotate", "fulltext", "reset", "delete", "openDoc", "timeX"];
            var notfiyTypes = ["entity", "metadata", "time", "timeX", "fulltext", "reset"];
            var metadataTypes = [];
            var entityTypes = [];
            var histogramLoD = [];
            types.forEach(function(type) {
                if(type != types[1])
                    items[type] = [];
                else
                    items[type] = {};
            });
            //items[types[1]] = metadataTypes;

            //fetch metadata Types dynamically
            function updateMetadataTypes() {
                var deferred = $q.defer();
                metadataTypes = [];
                playRoutes.controllers.MetadataController.getMetadataTypes().get().then(function (response) {
                    //TODO: hack for ES issue
                    metadataTypes = [];
                    angular.forEach(response.data, function(type){
                        //metadataTypes.push(type.replace(".","_").toLowerCase());
                        metadataTypes.push(type.replace("sender","Sender"));
                    });

                    angular.forEach(metadataTypes, function (type) {
                        items['metadata'][type] = [];
                    });
                    deferred.resolve(metadataTypes);
                    //TODO: how to add metadata filter
                    //items['metadata']['Tags'].push('PREF');
                });
                return deferred.promise;
            }
            // fetch entity types dynamically
            function updateEntityTypes() {
                var deferred = $q.defer();
                entityTypes = [];
                playRoutes.controllers.EntityController.getEntityTypes().get().then(function (response) {
                    entityTypes = angular.copy(response.data);
                    deferred.resolve(entityTypes);
                });
                return deferred.promise;
            }
            // fetch levels of detail for histogram
            function updateLoD() {
                var deferred = $q.defer();
                playRoutes.controllers.HistogramController.getTimelineLOD().get().then(function (response) {
                    histogramLoD = angular.copy(response.data);
                    deferred.resolve(histogramLoD);
                });
                return deferred.promise;
            }

            var lastAdded = -1;
            var lastRemoved = -1;

            //promises.then() waits for factory ready to use
            var promiseMetadata = updateMetadataTypes();
            var promiseEntities = updateEntityTypes();
            var promiseLoD = updateLoD();
            //var promise = $q.all([updateMetadataTypes(), updateEntityTypes()]);

            return {
                /**
                 * Register an observer with callback function and priority for updating the views. The
                 * callbackInstance has the following format: { priority: 1, callback: foo }
                 * IMPORTANT: the callback function has to return a promise a
                 */
                registerObserverCallback: function(callbackInstance){
                    observerCallbacks.push(callbackInstance);
                },
                /**
                 * call all observer callback functions
                 */
                notifyObservers: function(){
                    var callBackPromises = [];
                    var prioritized = observerCallbacks.sort(function(a, b) { return a.priority - b.priority; });

                    angular.forEach(prioritized, function(callbackInstance){
                        callBackPromises.push(callbackInstance.callback());
                    });
                    var promise = $q.all(callBackPromises);
                    return promise;
                },

                addItem: function (item, notify = true) {

                    //looking for already existing items
                    var  isDup =false;
                    var action = "added";
                    switch(item.type) {
                        //entity
                        case types[0]:
                            items[item.type].forEach(function(x) {
                                if (item.data.id == x.data.id) isDup = true;
                            });
                            break;
                        //metadata
                        case types[1]:
                            //history.forEach(function(x) {
                            //    if (item.data.id == x.data.id) isDup = true;
                            //});
                            break;
                        //time filter
                        case types[2]:
                            if(items[item.type].length > 0) action = "replaced";
                            break;
                        //time filter
                        case types[13]:
                            if(items[item.type].length > 0) action = "replaced";
                            break;
                        case types[5]:
                            action = "other";
                            break;
                        case types[6]:
                            action = "other";
                            break;
                        case types[7]:
                            action = "other";
                            break;
                        case types[11]:
                            action = "other";
                            break;
                        case types[12]:
                            action = "other";
                            break;
                    }

                    if(isDup) return  -1;

                    lastAdded++;
                    item["action"] = action;
                    item["id"] = angular.copy(lastAdded);
                    item["active"] = true;

                    history.push(item);
                    //if(items.indexOf(item.type) == -1) items[item.type] = [];
                    //adding item structured
                    switch(item.type) {
                        //entity
                        case types[0]:
                            items[item.type].push(item);
                            break;
                        //metadata
                        case types[1]:
                            items[item.type][item.data.type].push(item);
                            break;
                        //time filter
                        case types[2]:
                            items[item.type].push(item);
                            break;
                        //time filter
                        case types[13]:
                            items[item.type].push(item);
                            break;
                        //reset
                        case types[10]:
                            item.active = false;
                            items[item.type].push(item);
                            break;
                        case types[12]:
                            item.active = false;
                            items[item.type].push(item);
                            break;
                        default:
                            items[item.type].push(item);
                            break;
                    }

                    if(notfiyTypes.indexOf(item.type) >= 0 && notify)
                        this.notifyObservers();
                    console.log("added to history: " + item.data.item);
                    return (lastAdded);
                },

                removeItem: function (id, type, notify = true) {
                    var toBeRemoved = history[history.findIndex(function (item) {
                        return id == item.id;
                    })];
                    toBeRemoved.active = false;
                    var item = angular.copy(toBeRemoved);
                    lastAdded++;
                    item["id"] = angular.copy(lastAdded);
                    item["action"] = "removed";
                    history.push(item);
                    switch(item.type) {

                        //metadata
                        case types[1]:
                            items[type][item.data.type].splice(items[type][item.data.type].findIndex(function (item) {
                                return id == item.id;
                            }), 1);
                            break;

                        default:
                            items[type].splice(items[type].findIndex(function (item) {
                                return id == item.id;
                            }), 1);
                    }
                    lastRemoved = id;
                    if(notify)
                        this.notifyObservers();
                    console.log("removed from history: " + lastRemoved);
                },

                //TODO: replace type by array to more then one type can be subscribed in a merged item array
                subscribeItems: function (_subscriber, type) {
                    subscriber.push({
                        func: _subscriber,
                        type: type
                    });
                    _subscriber(items[type]);
                },

                subscribeAllItems: function(_subscriber) {
                    subscriber.push({
                        func: _subscriber,
                        type: 'all'
                    });
                    _subscriber(items);
                },

                subscribeHistory: function (_subscriber) {
                    subscriber.push({
                        func: _subscriber,
                        type: 'history'
                    });
                    _subscriber(history);
                },

                /**
                 * IMPORTANT: the callback function has to return an promise
                 * @param _subscriber
                 */
                subscribeReset: function(_subscriber) {
                    subscriber.push({
                        func: _subscriber,
                        type: 'reset'
                    });
                },

                refreshSubscribers: function(reset = true) {
                    var proms = [];
                  angular.forEach(subscriber, function(_subscriber) {
                      switch(_subscriber.type) {
                          case 'reset':
                              if(reset) proms.push(_subscriber.func());
                              break;
                          case 'all':
                              _subscriber.func(items);
                              break;
                          case 'history':
                              _subscriber.func(history);
                              break;
                          default:
                              _subscriber.func(items[_subscriber.type]);
                      }
                  });
                    return $q.all(proms);
                },

                getTypes: function() {
                    return types;
                },

                /**
                 * after async type load, you get the types (promise.then(function(types) [}))
                 * @returns promise types are fetched
                 */
                getMetadataTypes: function() {
                    return promiseMetadata;
                },
                /**
                 * after async type load, you get the types (promise.then(function(types) [}))
                 * @returns promise types are fetched
                 */
                getEntityTypes: function() {
                    return promiseEntities;
                },

                getTimeRange: function() {
                    if(items["time"].length == 0) return ""; else return items["time"][items["time"].length-1].data.item;
                },

                getXTimeRange: function() {
                    if(items["timeX"].length == 0) return ""; else return items["timeX"][items["timeX"].length-1].data.item;
                },

                getFacets: function() {
                    var facets = [];
                    if(items.metadata) {
                            metadataTypes.forEach(function(metaType) {
                            if(items.metadata[metaType].length > 0) {
                                var keys = [];
                                angular.forEach(items.metadata[metaType], function(x) {
                                    keys.push(x.data.item);
                                });
                                facets.push({key: metaType.replace(".","_"), data: keys});
                            }
                        });
                        if(facets == 0) facets = [{'key':'dummy','data': []}];

                    } else {
                        facets = [{'key':'dummy','data': []}];
                    }
                    return facets;
                },

                drillUpTimeFilter: function() {
                    this.removeItem(items["time"][items["time"].length-1].id,'time');
                    while(items["time"][items["time"].length-1] && items["time"][items["time"].length-1].data.lod == "month")
                        this.removeItem(items["time"][items["time"].length-1].id,'time',false);
                },

                drillUpXTimeFilter: function() {
                    this.removeItem(items["timeX"][items["timeX"].length-1].id,'timeX');
                    while(items["timeX"][items["timeX"].length-1] && items["timeX"][items["timeX"].length-1].data.lod == "month")
                        this.removeItem(items["timeX"][items["timeX"].length-1].id,'timeX',false);
                },
                /**
                 * after async type load, you get the types (promise.then(function(lod) [}))
                 * @returns promise lod are fetched
                 */
                getHistogramLod: function() {
                    return promiseLoD;
                },

                initTypes: function() {
                    promiseMetadata = updateMetadataTypes();
                    promiseEntities = updateEntityTypes();
                    promiseLoD = updateLoD();
                },

                reset: function() {
                    var rootThis = this;
                    history.forEach(function(item) {
                        if(item.active)
                            rootThis.removeItem(item.id, item.type, false);
                    });
                    items = {};
                    types.forEach(function(type) {
                        items[type] = [];
                    });
                    this.initTypes();
                    $q.all([
                        promiseEntities, promiseLoD, promiseMetadata
                    ]).then(function(values) {
                        rootThis.refreshSubscribers().then(function(val) {
                            rootThis.notifyObservers();
                        });

                        rootThis.addItem({
                            type: 'reset',
                            active: false,
                            data: {
                                item: "",
                                description: "Filter has been reset"
                            }
                        }, false);
                    });

                },

                loadState: function(input) {
                    console.log(input);
                    var rootThis = this;
                    history.splice(0);
                    items =  {};
                    types.forEach(function(type) {
                        if(type != types[1])
                            items[type] = [];
                        else
                            items[type] = {};
                    });
                    this.initTypes();

                    //history = angular.copy(input.history);
                    console.log(history);
                    $q.all([
                        promiseEntities, promiseLoD, promiseMetadata
                    ]).then(function() {
                        angular.forEach(input.history, function (item) {
                            history.push(angular.copy(item));
                        });
                            types.forEach(function (type) {
                                $.each(input.items[type], function (index, item) {
                                    if (type != types[1])
                                        items[type].push(item);
                                    else {
                                        if(item[0])
                                            items[type][item[0].data.type] = angular.copy(item);

                                    }
                                });
                            });
                        console.log(items);

                        lastAdded = history[history.length-1].id;
                        lastRemoved = -1;
                        rootThis.refreshSubscribers(false).then(function(val) {
                            rootThis.notifyObservers();
                        });
                        }
                    );
                }
            }
        }]);

});
<commit_msg>vertical scroll fix<commit_after>/*
 * Copyright (C) 2016 Language Technology Group and Interactive Graphics Systems Group, Technische Universität Darmstadt, Germany
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

define([
    'angular',
    'jquery-json'
], function (angular) {
    'use strict';

    angular.module("myApp.observer", ['play.routing'])
        .factory('ObserverService', ['playRoutes', '$q', function(playRoutes, $q) {
            // Stores callback instances consisting of a callback method and a priority number
            var observerCallbacks = [];
            //holds subscriber functions
            var subscriber = [];
            //all items in order
            var history = [];
            //all item structured by type
            var items = {};
            //types of tracked items
            // TODO: expandNode, egoNetwork not used. Remove them. Make sure index of types still fits! Better don't access via index ...
            var types = ["entity", "metadata", "time", "expandNode", "egoNetwork", "merge", "hide", "edit", "annotate", "fulltext", "reset", "delete", "openDoc", "timeX"];
            var notfiyTypes = ["entity", "metadata", "time", "timeX", "fulltext", "reset"];
            var metadataTypes = [];
            var entityTypes = [];
            var histogramLoD = [];
            types.forEach(function(type) {
                if(type != types[1])
                    items[type] = [];
                else
                    items[type] = {};
            });
            //items[types[1]] = metadataTypes;

            //fetch metadata Types dynamically
            function updateMetadataTypes() {
                var deferred = $q.defer();
                metadataTypes = [];
                playRoutes.controllers.MetadataController.getMetadataTypes().get().then(function (response) {
                    //TODO: hack for ES issue
                    metadataTypes = [];
                    angular.forEach(response.data, function(type){
                        //metadataTypes.push(type.replace(".","_").toLowerCase());
                        metadataTypes.push(type.replace("sender","Sender"));
                    });

                    angular.forEach(metadataTypes, function (type) {
                        items['metadata'][type] = [];
                    });
                    deferred.resolve(metadataTypes);
                    //TODO: how to add metadata filter
                    //items['metadata']['Tags'].push('PREF');
                });
                return deferred.promise;
            }
            // fetch entity types dynamically
            function updateEntityTypes() {
                var deferred = $q.defer();
                entityTypes = [];
                playRoutes.controllers.EntityController.getEntityTypes().get().then(function (response) {
                    entityTypes = angular.copy(response.data);
                    deferred.resolve(entityTypes);
                });
                return deferred.promise;
            }
            // fetch levels of detail for histogram
            function updateLoD() {
                var deferred = $q.defer();
                playRoutes.controllers.HistogramController.getTimelineLOD().get().then(function (response) {
                    histogramLoD = angular.copy(response.data);
                    deferred.resolve(histogramLoD);
                });
                return deferred.promise;
            }

            var lastAdded = -1;
            var lastRemoved = -1;

            //promises.then() waits for factory ready to use
            var promiseMetadata = updateMetadataTypes();
            var promiseEntities = updateEntityTypes();
            var promiseLoD = updateLoD();
            //var promise = $q.all([updateMetadataTypes(), updateEntityTypes()]);

            return {
                /**
                 * Register an observer with callback function and priority for updating the views. The
                 * callbackInstance has the following format: { priority: 1, callback: foo }
                 * IMPORTANT: the callback function has to return a promise a
                 */
                registerObserverCallback: function(callbackInstance){
                    observerCallbacks.push(callbackInstance);
                },
                /**
                 * call all observer callback functions
                 */
                notifyObservers: function(){
                    var callBackPromises = [];
                    var prioritized = observerCallbacks.sort(function(a, b) { return a.priority - b.priority; });

                    angular.forEach(prioritized, function(callbackInstance){
                        callBackPromises.push(callbackInstance.callback());
                    });
                    var promise = $q.all(callBackPromises);
                    return promise;
                },

                addItem: function (item, notify = true) {

                    //looking for already existing items
                    var  isDup =false;
                    var action = "added";
                    switch(item.type) {
                        //entity
                        case types[0]:
                            items[item.type].forEach(function(x) {
                                if (item.data.id == x.data.id) isDup = true;
                            });
                            break;
                        //metadata
                        case types[1]:
                            //history.forEach(function(x) {
                            //    if (item.data.id == x.data.id) isDup = true;
                            //});
                            break;
                        //time filter
                        case types[2]:
                            if(items[item.type].length > 0) action = "replaced";
                            break;
                        //time filter
                        case types[13]:
                            if(items[item.type].length > 0) action = "replaced";
                            break;
                        case types[5]:
                            action = "other";
                            break;
                        case types[6]:
                            action = "other";
                            break;
                        case types[7]:
                            action = "other";
                            break;
                        case types[11]:
                            action = "other";
                            break;
                        case types[12]:
                            action = "other";
                            break;
                    }

                    if(isDup) return  -1;

                    lastAdded++;
                    item["action"] = action;
                    item["id"] = angular.copy(lastAdded);
                    item["active"] = true;

                    history.push(item);
                    //if(items.indexOf(item.type) == -1) items[item.type] = [];
                    //adding item structured
                    switch(item.type) {
                        //entity
                        case types[0]:
                            items[item.type].push(item);
                            break;
                        //metadata
                        case types[1]:
                            items[item.type][item.data.type].push(item);
                            break;
                        //time filter
                        case types[2]:
                            items[item.type].push(item);
                            break;
                        //time filter
                        case types[13]:
                            items[item.type].push(item);
                            break;
                        //reset
                        case types[10]:
                            item.active = false;
                            items[item.type].push(item);
                            break;
                        case types[12]:
                            item.active = false;
                            items[item.type].push(item);
                            break;
                        default:
                            items[item.type].push(item);
                            break;
                    }

                    if(notfiyTypes.indexOf(item.type) >= 0 && notify)
                        this.notifyObservers();
                    console.log("added to history: " + item.data.item);
                    return (lastAdded);
                },

                removeItem: function (id, type, notify = true) {
                    var toBeRemoved = history[history.findIndex(function (item) {
                        return id == item.id;
                    })];
                    toBeRemoved.active = false;
                    var item = angular.copy(toBeRemoved);
                    lastAdded++;
                    item["id"] = angular.copy(lastAdded);
                    item["action"] = "removed";
                    history.push(item);
                    switch(item.type) {

                        //metadata
                        case types[1]:
                            items[type][item.data.type].splice(items[type][item.data.type].findIndex(function (item) {
                                return id == item.id;
                            }), 1);
                            break;

                        default:
                            items[type].splice(items[type].findIndex(function (item) {
                                return id == item.id;
                            }), 1);
                    }
                    lastRemoved = id;
                    if(notify)
                        this.notifyObservers();
                    console.log("removed from history: " + lastRemoved);
                },

                //TODO: replace type by array to more then one type can be subscribed in a merged item array
                subscribeItems: function (_subscriber, type) {
                    subscriber.push({
                        func: _subscriber,
                        type: type
                    });
                    _subscriber(items[type]);
                },

                subscribeAllItems: function(_subscriber) {
                    subscriber.push({
                        func: _subscriber,
                        type: 'all'
                    });
                    _subscriber(items);
                },

                subscribeHistory: function (_subscriber) {
                    subscriber.push({
                        func: _subscriber,
                        type: 'history'
                    });
                    _subscriber(history);
                },

                /**
                 * IMPORTANT: the callback function has to return an promise
                 * @param _subscriber
                 */
                subscribeReset: function(_subscriber) {
                    subscriber.push({
                        func: _subscriber,
                        type: 'reset'
                    });
                },

                refreshSubscribers: function(reset = true) {
                    var proms = [];
                  angular.forEach(subscriber, function(_subscriber) {
                      switch(_subscriber.type) {
                          case 'reset':
                              if(reset) proms.push(_subscriber.func());
                              break;
                          case 'all':
                              _subscriber.func(items);
                              break;
                          case 'history':
                              _subscriber.func(history);
                              break;
                          default:
                              _subscriber.func(items[_subscriber.type]);
                      }
                  });
                    return $q.all(proms);
                },

                getTypes: function() {
                    return types;
                },

                /**
                 * after async type load, you get the types (promise.then(function(types) [}))
                 * @returns promise types are fetched
                 */
                getMetadataTypes: function() {
                    return promiseMetadata;
                },
                /**
                 * after async type load, you get the types (promise.then(function(types) [}))
                 * @returns promise types are fetched
                 */
                getEntityTypes: function() {
                    return promiseEntities;
                },

                getTimeRange: function() {
                    if(items["time"].length == 0) return ""; else return items["time"][items["time"].length-1].data.item;
                },

                getXTimeRange: function() {
                    if(items["timeX"].length == 0) return ""; else return items["timeX"][items["timeX"].length-1].data.item;
                },

                getFacets: function() {
                    var facets = [];
                    if(items.metadata) {
                            metadataTypes.forEach(function(metaType) {
                            if(items.metadata[metaType].length > 0) {
                                var keys = [];
                                angular.forEach(items.metadata[metaType], function(x) {
                                    keys.push(x.data.item);
                                });
                                facets.push({key: metaType.replace(".","_"), data: keys});
                            }
                        });
                        if(facets == 0) facets = [{'key':'dummy','data': []}];

                    } else {
                        facets = [{'key':'dummy','data': []}];
                    }
                    return facets;
                },

                drillUpTimeFilter: function() {
                    this.removeItem(items["time"][items["time"].length-1].id,'time');
                    while(items["time"][items["time"].length-1] && items["time"][items["time"].length-1].data.lod == "month")
                        this.removeItem(items["time"][items["time"].length-1].id,'time',false);
                },

                drillUpXTimeFilter: function() {
                    this.removeItem(items["timeX"][items["timeX"].length-1].id,'timeX');
                    while(items["timeX"][items["timeX"].length-1] && items["timeX"][items["timeX"].length-1].data.lod == "month")
                        this.removeItem(items["timeX"][items["timeX"].length-1].id,'timeX',false);
                },
                /**
                 * after async type load, you get the types (promise.then(function(lod) [}))
                 * @returns promise lod are fetched
                 */
                getHistogramLod: function() {
                    return promiseLoD;
                },

                initTypes: function() {
                    promiseMetadata = updateMetadataTypes();
                    promiseEntities = updateEntityTypes();
                    promiseLoD = updateLoD();
                },

                reset: function() {
                    var rootThis = this;
                    history.forEach(function(item) {
                        if(item.active)
                            rootThis.removeItem(item.id, item.type, false);
                    });
                    items = {};
                    types.forEach(function(type) {
                        items[type] = [];
                    });
                    this.initTypes();
                    $q.all([
                        promiseEntities, promiseLoD, promiseMetadata
                    ]).then(function(values) {
                        rootThis.refreshSubscribers().then(function(val) {
                            rootThis.notifyObservers();
                        });

                        rootThis.addItem({
                            type: 'reset',
                            active: false,
                            data: {
                                item: "",
                                description: "Filter has been reset"
                            }
                        }, false);
                    });

                },

                loadState: function(input) {
                    console.log(input);
                    var rootThis = this;
                    history.splice(0);
                    history.length = 0;
                    items =  {};
                    types.forEach(function(type) {
                        if(type != types[1])
                            items[type] = [];
                        else
                            items[type] = {};
                    });
                    this.initTypes();

                    //history = angular.copy(input.history);
                    console.log(history);
                    $q.all([
                        promiseEntities, promiseLoD, promiseMetadata
                    ]).then(function() {
                        angular.forEach(input.history, function (item) {
                            history.push(angular.copy(item));
                        });
                            types.forEach(function (type) {
                                $.each(input.items[type], function (index, item) {
                                    if (type != types[1])
                                        items[type].push(item);
                                    else {
                                        if(item[0])
                                            items[type][item[0].data.type] = angular.copy(item);

                                    }
                                });
                            });
                        console.log(items);

                        lastAdded = history[history.length-1].id;
                        lastRemoved = -1;
                        rootThis.refreshSubscribers(false).then(function(val) {
                            rootThis.notifyObservers();
                        });
                        }
                    );
                }
            }
        }]);

});
<|endoftext|>