<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow
 */

'use strict';

const invariant = require('invariant');
const warnOnce = require('warnOnce');

// Export React, plus some native additions.
module.exports = {
  // Components
  get AccessibilityInfo() {
    return require('AccessibilityInfo');
  },
  get ActivityIndicator() {
    return require('ActivityIndicator');
  },
  get ART() {
    return require('ReactNativeART');
  },
  get Button() {
    return require('Button');
  },
  get CheckBox() {
    warnOnce(
      'checkBox-moved',
      'CheckBox has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/checkbox' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-checkbox',
    );
    return require('CheckBox');
  },
  get DatePickerIOS() {
    return require('DatePickerIOS');
  },
  get DrawerLayoutAndroid() {
    return require('DrawerLayoutAndroid');
  },
  get FlatList() {
    return require('FlatList');
  },
  get Image() {
    return require('Image');
  },
  get ImageBackground() {
    return require('ImageBackground');
  },
  get ImageEditor() {
    warnOnce(
      'image-editor-moved',
      'Image Editor has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/image-editor' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-image-editor',
    );
    return require('ImageEditor');
  },
  get ImageStore() {
    warnOnce(
      'imagestore-deprecation',
      'ImageStore is deprecated and will be removed in a future release. ' +
        'To get a base64-encoded string from a local image use either of the following third-party libraries:' +
        "* expo-file-system: `readAsStringAsync(filepath, 'base64')`" +
        "* react-native-fs: `readFile(filepath, 'base64')`",
    );
    return require('ImageStore');
  },
  get InputAccessoryView() {
    return require('InputAccessoryView');
  },
  get KeyboardAvoidingView() {
    return require('KeyboardAvoidingView');
  },
  get MaskedViewIOS() {
    warnOnce(
      'maskedviewios-moved',
      'MaskedViewIOS has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/masked-view' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-masked-view',
    );
    return require('MaskedViewIOS');
  },
  get Modal() {
    return require('Modal');
  },
  get Picker() {
    return require('Picker');
  },
  get PickerIOS() {
    return require('PickerIOS');
  },
  get ProgressBarAndroid() {
    return require('ProgressBarAndroid');
  },
  get ProgressViewIOS() {
    return require('ProgressViewIOS');
  },
  get SafeAreaView() {
    return require('SafeAreaView');
  },
  get ScrollView() {
    return require('ScrollView');
  },
  get SectionList() {
    return require('SectionList');
  },
  get SegmentedControlIOS() {
    return require('SegmentedControlIOS');
  },
  get Slider() {
    warnOnce(
      'slider-moved',
      'Slider has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/slider' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-slider',
    );
    return require('Slider');
  },
  get Switch() {
    return require('Switch');
  },
  get RefreshControl() {
    return require('RefreshControl');
  },
  get StatusBar() {
    return require('StatusBar');
  },
  get Text() {
    return require('Text');
  },
  get TextInput() {
    return require('TextInput');
  },
  get Touchable() {
    return require('Touchable');
  },
  get TouchableHighlight() {
    return require('TouchableHighlight');
  },
  get TouchableNativeFeedback() {
    return require('TouchableNativeFeedback');
  },
  get TouchableOpacity() {
    return require('TouchableOpacity');
  },
  get TouchableWithoutFeedback() {
    return require('TouchableWithoutFeedback');
  },
  get View() {
    return require('View');
  },
  get ViewPagerAndroid() {
    warnOnce(
      'viewpager-moved',
      'ViewPagerAndroid has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/viewpager' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-viewpager',
    );
    return require('ViewPagerAndroid');
  },
  get VirtualizedList() {
    return require('VirtualizedList');
  },
  get VirtualizedSectionList() {
    return require('VirtualizedSectionList');
  },

  // APIs
  get ActionSheetIOS() {
    return require('ActionSheetIOS');
  },
  get Alert() {
    return require('Alert');
  },
  get Animated() {
    return require('Animated');
  },
  get AppRegistry() {
    return require('AppRegistry');
  },
  get AppState() {
    return require('AppState');
  },
  get AsyncStorage() {
    warnOnce(
      'async-storage-moved',
      'Async Storage has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/async-storage' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-async-storage',
    );
    return require('AsyncStorage');
  },
  get BackHandler() {
    return require('BackHandler');
  },
  get Clipboard() {
    return require('Clipboard');
  },
  get DatePickerAndroid() {
    return require('DatePickerAndroid');
  },
  get DeviceInfo() {
    return require('DeviceInfo');
  },
  get Dimensions() {
    return require('Dimensions');
  },
  get Easing() {
    return require('Easing');
  },
  get findNodeHandle() {
    return require('ReactNative').findNodeHandle;
  },
  get I18nManager() {
    return require('I18nManager');
  },
  get ImagePickerIOS() {
    return require('ImagePickerIOS');
  },
  get InteractionManager() {
    return require('InteractionManager');
  },
  get Keyboard() {
    return require('Keyboard');
  },
  get LayoutAnimation() {
    return require('LayoutAnimation');
  },
  get Linking() {
    return require('Linking');
  },
  get NativeDialogManagerAndroid() {
    return require('NativeDialogManagerAndroid').default;
  },
  get NativeEventEmitter() {
    return require('NativeEventEmitter');
  },
  get PanResponder() {
    return require('PanResponder');
  },
  get PermissionsAndroid() {
    return require('PermissionsAndroid');
  },
  get PixelRatio() {
    return require('PixelRatio');
  },
  get PushNotificationIOS() {
    warnOnce(
      'pushNotificationIOS-moved',
      'PushNotificationIOS has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/push-notification-ios' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-push-notification-ios',
    );
    return require('PushNotificationIOS');
  },
  get Settings() {
    return require('Settings');
  },
  get Share() {
    return require('Share');
  },
  get StatusBarIOS() {
    return require('StatusBarIOS');
  },
  get StyleSheet() {
    return require('StyleSheet');
  },
  get Systrace() {
    return require('Systrace');
  },
  get TimePickerAndroid() {
    return require('TimePickerAndroid');
  },
  get ToastAndroid() {
    return require('ToastAndroid');
  },
  get TurboModuleRegistry() {
    return require('TurboModuleRegistry');
  },
  get TVEventHandler() {
    return require('TVEventHandler');
  },
  get UIManager() {
    return require('UIManager');
  },
  get unstable_batchedUpdates() {
    return require('ReactNative').unstable_batchedUpdates;
  },
  get UTFSequence() {
    return require('UTFSequence');
  },
  get Vibration() {
    return require('Vibration');
  },
  get YellowBox() {
    return require('YellowBox');
  },

  // Plugins
  get DeviceEventEmitter() {
    return require('RCTDeviceEventEmitter');
  },
  get NativeAppEventEmitter() {
    return require('RCTNativeAppEventEmitter');
  },
  get NativeModules() {
    return require('NativeModules');
  },
  get Platform() {
    return require('Platform');
  },
  get processColor() {
    return require('processColor');
  },
  get requireNativeComponent() {
    return require('requireNativeComponent');
  },

  // Prop Types
  get ColorPropType() {
    return require('DeprecatedColorPropType');
  },
  get EdgeInsetsPropType() {
    return require('DeprecatedEdgeInsetsPropType');
  },
  get PointPropType() {
    return require('DeprecatedPointPropType');
  },
  get ViewPropTypes() {
    return require('DeprecatedViewPropTypes');
  },
};

if (__DEV__) {
  // $FlowFixMe This is intentional: Flow will error when attempting to access ListView.
  Object.defineProperty(module.exports, 'ListView', {
    configurable: true,
    get() {
      invariant(
        false,
        'ListView has been removed from React Native. ' +
          'See https://fb.me/nolistview for more information or use ' +
          '`deprecated-react-native-listview`.',
      );
    },
  });

  // $FlowFixMe This is intentional: Flow will error when attempting to access SwipeableListView.
  Object.defineProperty(module.exports, 'SwipeableListView', {
    configurable: true,
    get() {
      invariant(
        false,
        'SwipeableListView has been removed from React Native. ' +
          'See https://fb.me/nolistview for more information or use ' +
          '`deprecated-react-native-swipeable-listview`.',
      );
    },
  });

  // $FlowFixMe This is intentional: Flow will error when attempting to access WebView.
  Object.defineProperty(module.exports, 'WebView', {
    configurable: true,
    get() {
      invariant(
        false,
        'WebView has been removed from React Native. ' +
          "It can now be installed and imported from 'react-native-webview' instead of 'react-native'. " +
          'See https://github.com/react-native-community/react-native-webview',
      );
    },
  });
}
<commit_msg>Temporarily bring back the "ToolbarAndroid" export for RN<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow
 */

'use strict';

const invariant = require('invariant');
const warnOnce = require('warnOnce');

// Export React, plus some native additions.
module.exports = {
  // Components
  get AccessibilityInfo() {
    return require('AccessibilityInfo');
  },
  get ActivityIndicator() {
    return require('ActivityIndicator');
  },
  get ART() {
    return require('ReactNativeART');
  },
  get Button() {
    return require('Button');
  },
  get CheckBox() {
    warnOnce(
      'checkBox-moved',
      'CheckBox has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/checkbox' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-checkbox',
    );
    return require('CheckBox');
  },
  get DatePickerIOS() {
    return require('DatePickerIOS');
  },
  get DrawerLayoutAndroid() {
    return require('DrawerLayoutAndroid');
  },
  get FlatList() {
    return require('FlatList');
  },
  get Image() {
    return require('Image');
  },
  get ImageBackground() {
    return require('ImageBackground');
  },
  get ImageEditor() {
    warnOnce(
      'image-editor-moved',
      'Image Editor has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/image-editor' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-image-editor',
    );
    return require('ImageEditor');
  },
  get ImageStore() {
    warnOnce(
      'imagestore-deprecation',
      'ImageStore is deprecated and will be removed in a future release. ' +
        'To get a base64-encoded string from a local image use either of the following third-party libraries:' +
        "* expo-file-system: `readAsStringAsync(filepath, 'base64')`" +
        "* react-native-fs: `readFile(filepath, 'base64')`",
    );
    return require('ImageStore');
  },
  get InputAccessoryView() {
    return require('InputAccessoryView');
  },
  get KeyboardAvoidingView() {
    return require('KeyboardAvoidingView');
  },
  get MaskedViewIOS() {
    warnOnce(
      'maskedviewios-moved',
      'MaskedViewIOS has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/masked-view' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-masked-view',
    );
    return require('MaskedViewIOS');
  },
  get Modal() {
    return require('Modal');
  },
  get Picker() {
    return require('Picker');
  },
  get PickerIOS() {
    return require('PickerIOS');
  },
  get ProgressBarAndroid() {
    return require('ProgressBarAndroid');
  },
  get ProgressViewIOS() {
    return require('ProgressViewIOS');
  },
  get SafeAreaView() {
    return require('SafeAreaView');
  },
  get ScrollView() {
    return require('ScrollView');
  },
  get SectionList() {
    return require('SectionList');
  },
  get SegmentedControlIOS() {
    return require('SegmentedControlIOS');
  },
  get Slider() {
    warnOnce(
      'slider-moved',
      'Slider has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/slider' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-slider',
    );
    return require('Slider');
  },
  get Switch() {
    return require('Switch');
  },
  get RefreshControl() {
    return require('RefreshControl');
  },
  get StatusBar() {
    return require('StatusBar');
  },
  get Text() {
    return require('Text');
  },
  get TextInput() {
    return require('TextInput');
  },
  get Touchable() {
    return require('Touchable');
  },
  get TouchableHighlight() {
    return require('TouchableHighlight');
  },
  get TouchableNativeFeedback() {
    return require('TouchableNativeFeedback');
  },
  get TouchableOpacity() {
    return require('TouchableOpacity');
  },
  get TouchableWithoutFeedback() {
    return require('TouchableWithoutFeedback');
  },
  get View() {
    return require('View');
  },
  get ViewPagerAndroid() {
    warnOnce(
      'viewpager-moved',
      'ViewPagerAndroid has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/viewpager' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-viewpager',
    );
    return require('ViewPagerAndroid');
  },
  get VirtualizedList() {
    return require('VirtualizedList');
  },
  get VirtualizedSectionList() {
    return require('VirtualizedSectionList');
  },

  // APIs
  get ActionSheetIOS() {
    return require('ActionSheetIOS');
  },
  get Alert() {
    return require('Alert');
  },
  get Animated() {
    return require('Animated');
  },
  get AppRegistry() {
    return require('AppRegistry');
  },
  get AppState() {
    return require('AppState');
  },
  get AsyncStorage() {
    warnOnce(
      'async-storage-moved',
      'Async Storage has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/async-storage' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-async-storage',
    );
    return require('AsyncStorage');
  },
  get BackHandler() {
    return require('BackHandler');
  },
  get Clipboard() {
    return require('Clipboard');
  },
  get DatePickerAndroid() {
    return require('DatePickerAndroid');
  },
  get DeviceInfo() {
    return require('DeviceInfo');
  },
  get Dimensions() {
    return require('Dimensions');
  },
  get Easing() {
    return require('Easing');
  },
  get findNodeHandle() {
    return require('ReactNative').findNodeHandle;
  },
  get I18nManager() {
    return require('I18nManager');
  },
  get ImagePickerIOS() {
    return require('ImagePickerIOS');
  },
  get InteractionManager() {
    return require('InteractionManager');
  },
  get Keyboard() {
    return require('Keyboard');
  },
  get LayoutAnimation() {
    return require('LayoutAnimation');
  },
  get Linking() {
    return require('Linking');
  },
  get NativeDialogManagerAndroid() {
    return require('NativeDialogManagerAndroid').default;
  },
  get NativeEventEmitter() {
    return require('NativeEventEmitter');
  },
  get PanResponder() {
    return require('PanResponder');
  },
  get PermissionsAndroid() {
    return require('PermissionsAndroid');
  },
  get PixelRatio() {
    return require('PixelRatio');
  },
  get PushNotificationIOS() {
    warnOnce(
      'pushNotificationIOS-moved',
      'PushNotificationIOS has been extracted from react-native core and will be removed in a future release. ' +
        "It can now be installed and imported from '@react-native-community/push-notification-ios' instead of 'react-native'. " +
        'See https://github.com/react-native-community/react-native-push-notification-ios',
    );
    return require('PushNotificationIOS');
  },
  get Settings() {
    return require('Settings');
  },
  get Share() {
    return require('Share');
  },
  get StatusBarIOS() {
    return require('StatusBarIOS');
  },
  get StyleSheet() {
    return require('StyleSheet');
  },
  get Systrace() {
    return require('Systrace');
  },
  get TimePickerAndroid() {
    return require('TimePickerAndroid');
  },
  get ToastAndroid() {
    return require('ToastAndroid');
  },
  get TurboModuleRegistry() {
    return require('TurboModuleRegistry');
  },
  get TVEventHandler() {
    return require('TVEventHandler');
  },
  get UIManager() {
    return require('UIManager');
  },
  get unstable_batchedUpdates() {
    return require('ReactNative').unstable_batchedUpdates;
  },
  get UTFSequence() {
    return require('UTFSequence');
  },
  get Vibration() {
    return require('Vibration');
  },
  get YellowBox() {
    return require('YellowBox');
  },

  // Plugins
  get DeviceEventEmitter() {
    return require('RCTDeviceEventEmitter');
  },
  get NativeAppEventEmitter() {
    return require('RCTNativeAppEventEmitter');
  },
  get NativeModules() {
    return require('NativeModules');
  },
  get Platform() {
    return require('Platform');
  },
  get processColor() {
    return require('processColor');
  },
  get requireNativeComponent() {
    return require('requireNativeComponent');
  },

  // Prop Types
  get ColorPropType() {
    return require('DeprecatedColorPropType');
  },
  get EdgeInsetsPropType() {
    return require('DeprecatedEdgeInsetsPropType');
  },
  get PointPropType() {
    return require('DeprecatedPointPropType');
  },
  get ViewPropTypes() {
    return require('DeprecatedViewPropTypes');
  },
  // TODO(cpojer): Temporary fix for missing Toolbar
  get ToolbarAndroid() {
    return require('UnimplementedView');
  },
};

if (__DEV__) {
  // $FlowFixMe This is intentional: Flow will error when attempting to access ListView.
  Object.defineProperty(module.exports, 'ListView', {
    configurable: true,
    get() {
      invariant(
        false,
        'ListView has been removed from React Native. ' +
          'See https://fb.me/nolistview for more information or use ' +
          '`deprecated-react-native-listview`.',
      );
    },
  });

  // $FlowFixMe This is intentional: Flow will error when attempting to access SwipeableListView.
  Object.defineProperty(module.exports, 'SwipeableListView', {
    configurable: true,
    get() {
      invariant(
        false,
        'SwipeableListView has been removed from React Native. ' +
          'See https://fb.me/nolistview for more information or use ' +
          '`deprecated-react-native-swipeable-listview`.',
      );
    },
  });

  // $FlowFixMe This is intentional: Flow will error when attempting to access WebView.
  Object.defineProperty(module.exports, 'WebView', {
    configurable: true,
    get() {
      invariant(
        false,
        'WebView has been removed from React Native. ' +
          "It can now be installed and imported from 'react-native-webview' instead of 'react-native'. " +
          'See https://github.com/react-native-community/react-native-webview',
      );
    },
  });
}
<|endoftext|>


<commit_before>vitaApp.factory('awsService', ['$rootScope',
function($rootScope) {
  var awsService = {};

  awsService.rootScope = $rootScope;

  //TODO load
  awsService.AwsKey = "";
  awsService.SecretKey = "";
  awsService.Bucket = "";

  awsService.SavePost = function(post) {

  };

  awsService.SaveFriend = function(friend) {

  };

  awsService.DeleteFriend = function(friend) {

  };

  awsService.DeletePost = function(post) {

  };

  $rootScope.$on('FriendSaved', function(event, friend){
    //Save friend to aws
  });

  $rootScope.$on('FriendDeleted', function(event, friend){
    //Save friend to aws
  });

  $rootScope.$on('PostSaved', function(event, post){
    //Save Post to aws
  });

  $rootScope.$on('FriendDeleted', function(event, post){
    //Save Post to aws
  });

  // factory function body that constructs shinyNewServiceInstance
  return awsService;
}]);<commit_msg>tweaking broadcast events<commit_after>vitaApp.factory('awsService', ['$rootScope',
function($rootScope) {
  var awsService = {};

  awsService.rootScope = $rootScope;

  //TODO load
  awsService.UseAws = true;
  awsService.AwsKey = "";
  awsService.SecretKey = "";
  awsService.Bucket = "";

  awsService.SavePost = function(post) {

  };

  awsService.SaveFriend = function(friend) {

  };

  awsService.DeleteFriend = function(friend) {

  };

  awsService.DeletePost = function(post) {

  };

  $rootScope.$on('FriendSaved', function(event, friend){
    if (awsService.UseAws) {
      awsService.SaveFriend(friend);
    }
  });

  $rootScope.$on('FriendDeleted', function(event, friend){
    if (awsService.UseAws) {
      awsService.DeleteFriend(friend);
    }
  });

  $rootScope.$on('PostSaved', function(event, post){
    if (awsService.UseAws) {
      awsService.SavePost(post);
    }
  });

  $rootScope.$on('PostDeleted', function(event, post){
    if (awsService.UseAws) {
      awsService.DeletePost(post);
    }
  });

  // factory function body that constructs shinyNewServiceInstance
  return awsService;
}]);<|endoftext|>


<commit_before>const r = require('../r');
const db = require('./db');

const experiments = require('./experiments');
const experimentDelete = require('./experiment-delete');
const projects = require('./projects');
const files = require('./files');

function* deleteProject(projectId, options) {

    let dryRun = !!(options && options.dryRun);

    let errorAddIn =
        " WARNING. The project may have been partially deleted - project state unknown.";

    let hasPublishedDatasets = yield testForPublishedDatasets(projectId);
    if (hasPublishedDatasets) {
        return {error: "Can not delete a project that has any experiment with a published datasets"}
    }

    let hasDOIAssigned = yield testForDOIAssigned(projectId);
    if (hasDOIAssigned) {
        return {error: "Can not delete a project that has any experiment with a DOI assigned"}
    }

    let results = yield projects.getProject(projectId);

    let project = null;
    let datasets = [];
    let samples = [];

    if (results.val) {
        project = results.val;
        datasets = project.datasets;
        samples = project.samples;
    } else {
        let error = results.error;
        error += errorAddIn;
        return {
            error: error
        }
    }

    let processIdList = yield r.table("project2process")
        .getAll(projectId,{index: "project_id"}).getField('process_id');

    let fileIdList = yield r.table("project2datafile")
        .getAll(projectId,{index: "project_id"}).getField('datafile_id');

    results = yield experiments.getAllForProject(projectId);
    let experimentList = results.val;

    let deletedExperiments = [];
    for (let i = 0; i < experimentList.length; i++) {
        let experiment = experimentList[i];
        let results = yield experimentDelete
            .deleteExperiment(projectId, experiment.id, {deleteProcesses: true, dryRun: dryRun});
        if (results.val) {
            let tally = results.val;
            deletedExperiments.push(
                {
                    experiment: experiment,
                    deleted: tally
                }
            );
        } else {
            let error = results.error;
            error += errorAddIn;
            return {
                error: error
            }
        }
    }

    let ret = {
        val: {
            project: project,
            experiments: deletedExperiments,
            datasets: datasets,
            files: fileIdList,
            processes: processIdList,
            samples: samples
        }
    };

    if (!dryRun) {
        yield deleteSamples(samples);
        yield deleteProcesses(processIdList);
        yield deleteFiles(fileIdList);
        yield deleteLinks(projectId);
        yield deteleProjectRecord(projectId);
    }

    return ret;
}

module.exports = {
    deleteProject
};

function* testForPublishedDatasets(projectId){

    let results = yield experiments.getAllForProject(projectId);
    let experimentList = results.val;

    for (let i = 0; i < experimentList.length; i++) {
        let datasetList = experimentList[i].datasets;
        for (let j = 0; j < datasetList.length; j++) {
            let dataset = datasetList[j];
            if (datasetList[j].published) {
                return true;
            }
        }
    }
    return false;
}

function* testForDOIAssigned(projectId){

    let results = yield experiments.getAllForProject(projectId);
    let experimentList = results.val;

    for (let i = 0; i < experimentList.length; i++) {
        let datasetList = experimentList[i].datasets;
        for (let j = 0; j < datasetList.length; j++) {
            let dataset = datasetList[j];
            if (datasetList[j].doi) {
                return true;
            }
        }
    }
    return false;
}

function* deleteSamples(samples) {
    let sampleIdList = [];
    samples.forEach((sample) => {
        sampleIdList.push(sample.id);
    });
    yield r.table("samples").getAll(r.args(sampleIdList)).delete();
}

function* deleteProcesses(processIdList) {
    yield r.table("processes").getAll(r.args(processIdList)).delete();
}

function* deleteFiles(fileIdList) {
    for (let i = 0; i < fileIdList.length; i++) {
        yield files.deleteFile(fileIdList[i]);
    }
}

function* deleteLinks(projectId) {
    let tables = [
        'project2datadir' ,
        'project2datafile' ,
        'project2experiment' ,
        'project2process' ,
        'project2sample',
        'access'
    ];

    for (let i = 0; i < tables.length; i++) {
        yield r.table(tables[i]).getAll(projectId, {index: 'project_id'}).delete();
    }
}

function* deteleProjectRecord(projectId) {
    yield r.table("projects").get(projectId).delete();
}<commit_msg>Fix spelling error<commit_after>const r = require('../r');

const experiments = require('./experiments');
const experimentDelete = require('./experiment-delete');
const projects = require('./projects');
const files = require('./files');

function* deleteProject(projectId, options) {

    let dryRun = !!(options && options.dryRun);

    let errorAddIn =
        " WARNING. The project may have been partially deleted - project state unknown.";

    let hasPublishedDatasets = yield testForPublishedDatasets(projectId);
    if (hasPublishedDatasets) {
        return {error: "Can not delete a project that has any experiment with a published datasets"}
    }

    let hasDOIAssigned = yield testForDOIAssigned(projectId);
    if (hasDOIAssigned) {
        return {error: "Can not delete a project that has any experiment with a DOI assigned"}
    }

    let results = yield projects.getProject(projectId);

    let project = null;
    let datasets = [];
    let samples = [];

    if (results.val) {
        project = results.val;
        datasets = project.datasets;
        samples = project.samples;
    } else {
        let error = results.error;
        error += errorAddIn;
        return {
            error: error
        }
    }

    let processIdList = yield r.table("project2process")
        .getAll(projectId, {index: "project_id"}).getField('process_id');

    let fileIdList = yield r.table("project2datafile")
        .getAll(projectId, {index: "project_id"}).getField('datafile_id');

    results = yield experiments.getAllForProject(projectId);
    let experimentList = results.val;

    let deletedExperiments = [];
    for (let i = 0; i < experimentList.length; i++) {
        let experiment = experimentList[i];
        let results = yield experimentDelete
            .deleteExperiment(projectId, experiment.id, {deleteProcesses: true, dryRun: dryRun});
        if (results.val) {
            let tally = results.val;
            deletedExperiments.push(
                {
                    experiment: experiment,
                    deleted: tally
                }
            );
        } else {
            let error = results.error;
            error += errorAddIn;
            return {
                error: error
            }
        }
    }

    let ret = {
        val: {
            project: project,
            experiments: deletedExperiments,
            datasets: datasets,
            files: fileIdList,
            processes: processIdList,
            samples: samples
        }
    };

    if (!dryRun) {
        yield deleteSamples(samples);
        yield deleteProcesses(processIdList);
        yield deleteFiles(fileIdList);
        yield deleteLinks(projectId);
        yield deleteProjectRecord(projectId);
    }

    return ret;
}

module.exports = {
    deleteProject
};

function* testForPublishedDatasets(projectId) {

    let results = yield experiments.getAllForProject(projectId);
    let experimentList = results.val;

    for (let i = 0; i < experimentList.length; i++) {
        let datasetList = experimentList[i].datasets;
        for (let j = 0; j < datasetList.length; j++) {
            if (datasetList[j].published) {
                return true;
            }
        }
    }
    return false;
}

function* testForDOIAssigned(projectId) {

    let results = yield experiments.getAllForProject(projectId);
    let experimentList = results.val;

    for (let i = 0; i < experimentList.length; i++) {
        let datasetList = experimentList[i].datasets;
        for (let j = 0; j < datasetList.length; j++) {
            if (datasetList[j].doi) {
                return true;
            }
        }
    }
    return false;
}

function* deleteSamples(samples) {
    let sampleIdList = [];
    samples.forEach((sample) => {
        sampleIdList.push(sample.id);
    });
    yield r.table("samples").getAll(r.args(sampleIdList)).delete();
}

function* deleteProcesses(processIdList) {
    yield r.table("processes").getAll(r.args(processIdList)).delete();
}

function* deleteFiles(fileIdList) {
    for (let i = 0; i < fileIdList.length; i++) {
        yield files.deleteFile(fileIdList[i]);
    }
}

function* deleteLinks(projectId) {
    let tables = [
        'project2datadir',
        'project2datafile',
        'project2experiment',
        'project2process',
        'project2sample',
        'access'
    ];

    for (let i = 0; i < tables.length; i++) {
        yield r.table(tables[i]).getAll(projectId, {index: 'project_id'}).delete();
    }
}

function* deleteProjectRecord(projectId) {
    yield r.table("projects").get(projectId).delete();
}<|endoftext|>


<commit_before>var calendar = {
    init : function(domCal){
    	console.log(" calendar2 init ", domCal);
      $("#showHideCalendar").click(function(){
        if($(this).data("hidden")){
          $(this).html(" "+trad.showcalendar+"");
          $(this).data("hidden",0);
          $(domCal).show(700);
        }else{
          $(this).html(" "+trad.showcalendar+"");
          $(this).data("hidden",1);
          $(domCal).hide(700);
        }

      });

        /*lazyLoad('/plugins/fullcalendar/fullcalendar/fullcalendar.min.js',
              '/plugins/fullcalendar/fullcalendar/fullcalendar.css',
            null,false);
        lazyLoad( baseUrl+'/plugins/fullcalendar/fullcalendar/locale/'+mainLanguage+'.js',null,null,false);*/
    },
    bindEventCalendar : function(){
    	console.log(" calendar2 bindEventCalendar ");
      //var popoverElement;

      $('.popover').mouseenter(function(){
       // alert();
        $(this).hide();
     //   calendar.showPopup=false;
      });
      $('body').off().on('click', function (e) {
      // close the popover if: click outside of the popover || click on the close button of the popover
        //alert(e.target);
        if (typeof popoverElement != "undefined" && popoverElement
          && ((!popoverElement.is(e.target) && popoverElement.has(e.target).length === 0 && $('.popover').has(e.target).length === 0)
            || (popoverElement.has(e.target) && e.target.id === 'closepopover'))) {

            // $('.popover').popover('hide'); --> works
           // if(calendar.showPopup)
           //alert("ici");
              calendar.closePopovers();
        }
      });
    },
    closePopovers : function() {
    	console.log(" calendar2 closePopovers ");
      calendar.showPopup=false;
      $('.popover').not(this).popover('hide');
    },
    templateRef : {
      "competition":"#ed553b",
      "concert" :"#b45f04",
      "contest":"#ed553b",
      "exhibition":"#b45f04",
      "festival":"#b45f04",
      "getTogether":"#eb4124",
      "market":"#df01a5",
      "meeting":"#eb4124",
      "course":"#df01a5",
      "workshop":"#eb4124",
      "conference":"#0073b0",
      "debate":"#0073b0",
      "film":"#2e2e2e",
      "crowdfunding":"#93be3d",
      "others":"#93be3d",
    },
    events : [],
    //dateToShow, calendar, $eventDetail, eventClass, eventCategory,
    widgetNotes : $('#notes .e-slider'),
    sliderNotes : $('#readNote .e-slider'),
    //oTable,
    //contributors,
    //subViewElement, subViewContent, subViewIndex,
    tabOrganiser : [],
    showPopup : false,
    //creates fullCalendar
    buildCalObj: function(eventObj) {
    	console.log(" calendar2 buildCalObj ", eventObj);
        //entries for the calendar
        //console.log(" calendar2 eventcaleanr",eventObj);
        var taskCal = null;
        if(eventObj.startDate && eventObj.startDate != "") {
            if(typeof eventObj.startDateCal != "undefined")
              var startDate = moment(eventObj.startDateCal).local();
            else if(typeof eventObj.startDateDB != "undefined")
              var startDate = moment(eventObj.startDateDB).local();
            else
              var startDate = moment(eventObj.startDate).local();
            var endDate = null;
            if(eventObj.endDate && eventObj.endDate != "" ){
                if(typeof eventObj.endDateCal != "undefined")
                  endDate = moment(eventObj.endDateCal).local();
                if(typeof eventObj.endDateDB != "undefined")
                    endDate = moment(eventObj.endDateDB).local();
                else
                    endDate = moment(eventObj.endDate).local();

            }
            mylog.log("Start Date = "+startDate+" // End Date = "+endDate);

            var organiser = "";
            if("undefined" != typeof eventObj["links"] && "undefined" != typeof eventObj.links["organizer"]){
                $.each(eventObj.links["organizer"], function(k, v){
                  	if($.inArray(k, calendar.tabOrganiser)==-1)
                        calendar.tabOrganiser.push(k);
                    organiser = k;
                })
            }
            var organizerName = eventObj.name;
            if(eventObj.organizer != "")
                organizerName = eventObj.organizer +" : "+ eventObj.name;
            console.log(" calendar2 eventObj", eventObj);
            taskCal = {
                "title" : eventObj.name + " : " + tradCategory[eventObj.typeEvent],
                "content" : (eventObj.description && eventObj.description != "" ) ? eventObj.description : "",
                "start" : startDate.format(),
                "end" : ( endDate ) ? endDate.format() : startDate.format(),
                "startDate" : eventObj.startDate,
                "endDate" : eventObj.endDate,
                "startDateDB" : eventObj.startDateDB,
                "endDateDB" : eventObj.endDateDB,
                 "allDay" : eventObj.allDay,
                "className": organiser,
                "category": organiser,
                "type": eventObj.typeEvent,
                "description":eventObj.description,
                "shortDescription": eventObj.shortDescription,
                "profilMediumImageUrl": eventObj.profilMediumImageUrl,
                "adresse": eventObj.cityName,
                //"adresse": eventObj.cityName,
                //"backgroundColor":calendar.templateColor[eventObj.typeEvent],
                "links":eventObj.links,
            }
            if(typeof eventObj.imgProfil != "undefined")
              taskCal.imgProfil=eventObj.imgProfil;
            if(typeof eventObj.id != "undefined")
              taskCal.id = eventObj.id;
            else
              taskCal.id = eventObj._id.$id;
            if(eventObj.allDay )
                taskCal.allDay = eventObj.allDay;
            //mylog.log(taskCal);
        }
        return taskCal;
    },
    showCalendar : function (domElement, events, initMode, initDate) {
    	console.log(" calendar2 showCalendar ", domElement, events, initMode, initDate);
        calendarObject = [];
        if(events){
            $.each(events,function(eventId,eventObj){
                eventCal = calendar.buildCalObj(eventObj);
                if(eventCal)
                    calendarObject.push( eventCal );
            });
        }

        if(typeof initDate != "undefined" && notNull(initDate) ){
          splitInit=initDate.split("-");
          dateToShow = new Date(splitInit[0], splitInit[1]-1, splitInit[2]);
        }
        else{
          initDate=null;
          dateToShow = new Date();
        }
        $(domElement).fullCalendar({
            header : {
            		left : 'prev,next',
            		center : 'title',
            		right : 'today, month, agendaWeek, agendaDay'
            },
            lang : mainLanguage,
            year : dateToShow.getFullYear(),
            month : dateToShow.getMonth(),
            date : dateToShow.getDate(),
            //gotoDate:moment(initDate),
            editable : false,
            eventBackgroundColor: '#FFA200',
            textColor: '#fff',
            defaultView: initMode,
            events : calendarObject,
            eventLimit: true,
            timezone : 'local',
            /*select: function (start, end, jsEvent) {
                closePopovers();
                popoverElement = $(jsEvent.target);
                $(jsEvent.target).popover({
                    title: 'the title',
                    content: function () {
                        return $("#popoverContent").html();
                    },
                    template: popTemplate,
                    placement: 'left',
                    html: 'true',
                    trigger: 'click',
                    animation: 'true',
                    container: 'body'
                }).popover('show');
            },*/
            eventClick: function (calEvent, jsEvent, view) {
            	console.log(" calendar2 eventClick ", calEvent, jsEvent, view);
              //closePopovers();
             // calendar.showPopup=true;
             popoverElement = $(jsEvent.currentTarget);

            },
            eventRender:function(event, element, view) {
                console.log(" calendar2 eventRender event",event,"element",element, "element", view);
                if(networkJson == "undefined"){
                    popupHtml=calendar.popupHtml(event);
                    element.popover({
                        html:true,
                        animation: true,
                        container:'body',
                        title: event.name,
                        template:calendar.popupTemplate(),
                        placement: 'top',
                        trigger: 'focus',
                        content: popupHtml,
                    });
                    element.attr('tabindex', -1);
                }

             // $("#popup"+event.id).mouseout(function(){
               // $(this).remove();
              //});
              //element.find(".fc-content").css("background-color", calendar.templateColor[event.type]);
            },
            /*eventClick : function(calEvent, jsEvent, view) {
                //show event in subview
                dateToShow = calEvent.start;
                urlCtrl.loadByHash("#page.type.events.id."+calEvent._id);
            }*/
        });
        calendar.setCategoryColor(calendar.tabOrganiser);
        calendar.bindEventCalendar();
        dateToShow = new Date();
    },
    setCategoryColor : function(tab){
      console.log(" calendar2 setCategoryColor ", tab);
  		  $(".fc-content").css("color", "white");
  	  	for(var i =0; i<tab.length; i++){
  	  	  	$("."+tab[i]+" .fc-content").css("color", "white");
            //$("."+tab[i]+" .fc-content").css("background-color", calendar.templateColor[i]);
  	  	}
  	},
  	getRandomColor : function() {
		console.log(" calendar2 getRandomColor ");
  	    var letters = '0123456789ABCDEF'.split('');
  	    var color = '#';
  	    for (var i = 0; i < 6; i++ ) {
  	        color += letters[Math.floor(Math.random() * 16)];
  	    }
  	    return color;
  	},
    popupTemplate : function(){
		console.log(" calendar2 popupTemplate ");
		template='
'+
					'

'+
					'
'+
					'<button id="closepopover" type="button" class="close margin-right-5" aria-hidden="true">×</button>'+
					'

'+
					'
'+
					'

'+
					'
';
		return template;
    },
    popupHtml : function(data){
		console.log(" calendar2 popupHtml ", data);
      var popupContent = "
";

      var color = "orange";
      var ico = 'calendar';
      var imgProfilPath =  assetPath + "/images/thumb/default_events.png";
      if(typeof data.profilMediumImageUrl !== "undefined" && data.profilMediumImageUrl != "")
        imgProfilPath =  baseUrl + data.profilMediumImageUrl;
      var icons = '!!!';

      var typeElement = "events";
      var icon = 'fa-calendar';

      var onclick = "";
      var url = '#page.type.'+typeElement+'.id.'+data.id;
      onclick = 'calendar.closePopovers();urlCtrl.loadByHash("'+url+'");';

      popupContent += "
";
      popupContent += "
"
                    +   "
"
                    +      "

"
                    +   "
"
                    +   "
";

      if("undefined" != typeof data.title)
        popupContent  +=  "
" + data.title + "
";

      if(data.start != null){
        popupContent +="
";
        startLbl=" ";
        startDate=moment(data.start).format("DD MMMM YYYY");
        endDate="";
        hoursStr="
";
        if(data.allDay)
          hoursStr+=tradDynForm.allday;
        else
          hoursStr+=" "+moment(data.start).format("H:mm");
        if(data.end != null){
          if(startDate != moment(data.end).format("DD MMMM YYYY")){
            startLbl+=trad.fromdate+" ";
            endDate=" "+trad.todatemin+" "+moment(data.end).format("DD MMMM YYYY");
          }
          if(!data.allDay)
            hoursStr+= " - "+moment(data.end).format("H:mm");
        }
        popupContent += startLbl+startDate+endDate+hoursStr;
        popupContent +="
";
      }
      popupContent += "
";
      //Short description
      if ("undefined" != typeof data['shortDescription'] && data['shortDescription'] != "" && data['shortDescription'] != null) {
        popupContent += "
"
                + "
" + data['shortDescription'] + "
"
              + "
";
      }
      //Contacts information
  //    popupContent += this.getPopupContactsInformation(data);
      //address
//      popupContent += this.getPopupAddressInformation(data);
     // popupContent += directory.getDateFormated(data,true);

      popupContent += '
';

                popupContent += "";
      popupContent += '
 en savoir +
';
      popupContent += '';

      return popupContent;
    }
}<commit_msg>fix #1131<commit_after>var calendar = {
    init : function(domCal){
    	console.log(" calendar2 init ", domCal);
      $("#showHideCalendar").click(function(){
        if($(this).data("hidden")){
          $(this).html(" "+trad.showcalendar+"");
          $(this).data("hidden",0);
          $(domCal).show(700);
        }else{
          $(this).html(" "+trad.showcalendar+"");
          $(this).data("hidden",1);
          $(domCal).hide(700);
        }

      });

        /*lazyLoad('/plugins/fullcalendar/fullcalendar/fullcalendar.min.js',
              '/plugins/fullcalendar/fullcalendar/fullcalendar.css',
            null,false);
        lazyLoad( baseUrl+'/plugins/fullcalendar/fullcalendar/locale/'+mainLanguage+'.js',null,null,false);*/
    },
    bindEventCalendar : function(){
    	console.log(" calendar2 bindEventCalendar ");
      //var popoverElement;

      $('.popover').mouseenter(function(){
       // alert();
        $(this).hide();
     //   calendar.showPopup=false;
      });
      $('body').off().on('click', function (e) {
      // close the popover if: click outside of the popover || click on the close button of the popover
        //alert(e.target);
        if (typeof popoverElement != "undefined" && popoverElement
          && ((!popoverElement.is(e.target) && popoverElement.has(e.target).length === 0 && $('.popover').has(e.target).length === 0)
            || (popoverElement.has(e.target) && e.target.id === 'closepopover'))) {

            // $('.popover').popover('hide'); --> works
           // if(calendar.showPopup)
           //alert("ici");
              calendar.closePopovers();
        }
      });
    },
    closePopovers : function() {
    	console.log(" calendar2 closePopovers ");
      calendar.showPopup=false;
      $('.popover').not(this).popover('hide');
    },
    templateRef : {
      "competition":"#ed553b",
      "concert" :"#b45f04",
      "contest":"#ed553b",
      "exhibition":"#b45f04",
      "festival":"#b45f04",
      "getTogether":"#eb4124",
      "market":"#df01a5",
      "meeting":"#eb4124",
      "course":"#df01a5",
      "workshop":"#eb4124",
      "conference":"#0073b0",
      "debate":"#0073b0",
      "film":"#2e2e2e",
      "crowdfunding":"#93be3d",
      "others":"#93be3d",
    },
    events : [],
    //dateToShow, calendar, $eventDetail, eventClass, eventCategory,
    widgetNotes : $('#notes .e-slider'),
    sliderNotes : $('#readNote .e-slider'),
    //oTable,
    //contributors,
    //subViewElement, subViewContent, subViewIndex,
    tabOrganiser : [],
    showPopup : false,
    //creates fullCalendar
    buildCalObj: function(eventObj) {
    	console.log(" calendar2 buildCalObj ", eventObj);
        //entries for the calendar
        //console.log(" calendar2 eventcaleanr",eventObj);
        var taskCal = null;
        if(eventObj.startDate && eventObj.startDate != "") {
            if(typeof eventObj.startDateCal != "undefined")
              var startDate = moment(eventObj.startDateCal).local();
            else if(typeof eventObj.startDateDB != "undefined")
              var startDate = moment(eventObj.startDateDB).local();
            else
              var startDate = moment(eventObj.startDate).local();
            var endDate = null;
            if(eventObj.endDate && eventObj.endDate != "" ){
                if(typeof eventObj.endDateCal != "undefined")
                  endDate = moment(eventObj.endDateCal).local();
                if(typeof eventObj.endDateDB != "undefined")
                    endDate = moment(eventObj.endDateDB).local();
                else
                    endDate = moment(eventObj.endDate).local();

            }
            mylog.log("Start Date = "+startDate+" // End Date = "+endDate);

            var organiser = "";
            if("undefined" != typeof eventObj["links"] && "undefined" != typeof eventObj.links["organizer"]){
                $.each(eventObj.links["organizer"], function(k, v){
                  	if($.inArray(k, calendar.tabOrganiser)==-1)
                        calendar.tabOrganiser.push(k);
                    organiser = k;
                })
            }
            var organizerName = eventObj.name;
            if(eventObj.organizer != "")
                organizerName = eventObj.organizer +" : "+ eventObj.name;
            console.log(" calendar2 eventObj", eventObj);
            taskCal = {
                "title" : eventObj.name + " : " + tradCategory[eventObj.typeEvent],
                "content" : (eventObj.description && eventObj.description != "" ) ? eventObj.description : "",
                "start" : startDate.format(),
                "end" : ( endDate ) ? endDate.format() : startDate.format(),
                "startDate" : eventObj.startDate,
                "endDate" : eventObj.endDate,
                "startDateDB" : eventObj.startDateDB,
                "endDateDB" : eventObj.endDateDB,
                 "allDay" : eventObj.allDay,
                "className": organiser,
                "category": organiser,
                "type": eventObj.typeEvent,
                "description":eventObj.description,
                "shortDescription": eventObj.shortDescription,
                "profilMediumImageUrl": eventObj.profilMediumImageUrl,
                "adresse": eventObj.cityName,
                //"adresse": eventObj.cityName,
                //"backgroundColor":calendar.templateColor[eventObj.typeEvent],
                "links":eventObj.links,
            }
            if(typeof eventObj.imgProfil != "undefined")
              taskCal.imgProfil=eventObj.imgProfil;
            if(typeof eventObj.id != "undefined")
              taskCal.id = eventObj.id;
            else
              taskCal.id = eventObj._id.$id;
            if(eventObj.allDay )
                taskCal.allDay = eventObj.allDay;
            //mylog.log(taskCal);
        }
        return taskCal;
    },
    showCalendar : function (domElement, events, initMode, initDate) {
    	console.log(" calendar2 showCalendar ", domElement, events, initMode, initDate);
        calendarObject = [];
        if(events){
            $.each(events,function(eventId,eventObj){
                eventCal = calendar.buildCalObj(eventObj);
                if(eventCal)
                    calendarObject.push( eventCal );
            });
        }

        if(typeof initDate != "undefined" && notNull(initDate) ){
          splitInit=initDate.split("-");
          dateToShow = new Date(splitInit[0], splitInit[1]-1, splitInit[2]);
        }
        else{
          initDate=null;
          dateToShow = new Date();
        }
        $(domElement).fullCalendar({
            header : {
            		left : 'prev,next',
            		center : 'title',
            		right : 'today, month, agendaWeek, agendaDay'
            },
            lang : mainLanguage,
            year : dateToShow.getFullYear(),
            month : dateToShow.getMonth(),
            date : dateToShow.getDate(),
            //gotoDate:moment(initDate),
            editable : false,
            eventBackgroundColor: '#FFA200',
            textColor: '#fff',
            defaultView: initMode,
            events : calendarObject,
            eventLimit: true,
            timezone : 'local',
            /*select: function (start, end, jsEvent) {
                closePopovers();
                popoverElement = $(jsEvent.target);
                $(jsEvent.target).popover({
                    title: 'the title',
                    content: function () {
                        return $("#popoverContent").html();
                    },
                    template: popTemplate,
                    placement: 'left',
                    html: 'true',
                    trigger: 'click',
                    animation: 'true',
                    container: 'body'
                }).popover('show');
            },*/
            eventClick: function (calEvent, jsEvent, view) {
            	console.log(" calendar2 eventClick ", calEvent, jsEvent, view);
              //closePopovers();
             // calendar.showPopup=true;
             popoverElement = $(jsEvent.currentTarget);

            },
            eventRender:function(event, element, view) {
                console.log(" calendar2 eventRender event",event,"element",element, "element", view);
                if(typeof networkJson == "undefined"){
                    popupHtml=calendar.popupHtml(event);
                    element.popover({
                        html:true,
                        animation: true,
                        container:'body',
                        title: event.name,
                        template:calendar.popupTemplate(),
                        placement: 'top',
                        trigger: 'focus',
                        content: popupHtml,
                    });
                    element.attr('tabindex', -1);
                }

             // $("#popup"+event.id).mouseout(function(){
               // $(this).remove();
              //});
              //element.find(".fc-content").css("background-color", calendar.templateColor[event.type]);
            },
            /*eventClick : function(calEvent, jsEvent, view) {
                //show event in subview
                dateToShow = calEvent.start;
                urlCtrl.loadByHash("#page.type.events.id."+calEvent._id);
            }*/
        });
        calendar.setCategoryColor(calendar.tabOrganiser);
        calendar.bindEventCalendar();
        dateToShow = new Date();
    },
    setCategoryColor : function(tab){
      console.log(" calendar2 setCategoryColor ", tab);
  		  $(".fc-content").css("color", "white");
  	  	for(var i =0; i<tab.length; i++){
  	  	  	$("."+tab[i]+" .fc-content").css("color", "white");
            //$("."+tab[i]+" .fc-content").css("background-color", calendar.templateColor[i]);
  	  	}
  	},
  	getRandomColor : function() {
		console.log(" calendar2 getRandomColor ");
  	    var letters = '0123456789ABCDEF'.split('');
  	    var color = '#';
  	    for (var i = 0; i < 6; i++ ) {
  	        color += letters[Math.floor(Math.random() * 16)];
  	    }
  	    return color;
  	},
    popupTemplate : function(){
		console.log(" calendar2 popupTemplate ");
		template='
'+
					'

'+
					'
'+
					'<button id="closepopover" type="button" class="close margin-right-5" aria-hidden="true">×</button>'+
					'

'+
					'
'+
					'

'+
					'
';
		return template;
    },
    popupHtml : function(data){
		console.log(" calendar2 popupHtml ", data);
      var popupContent = "
";

      var color = "orange";
      var ico = 'calendar';
      var imgProfilPath =  assetPath + "/images/thumb/default_events.png";
      if(typeof data.profilMediumImageUrl !== "undefined" && data.profilMediumImageUrl != "")
        imgProfilPath =  baseUrl + data.profilMediumImageUrl;
      var icons = '!!!';

      var typeElement = "events";
      var icon = 'fa-calendar';

      var onclick = "";
      var url = '#page.type.'+typeElement+'.id.'+data.id;
      onclick = 'calendar.closePopovers();urlCtrl.loadByHash("'+url+'");';

      popupContent += "
";
      popupContent += "
"
                    +   "
"
                    +      "

"
                    +   "
"
                    +   "
";

      if("undefined" != typeof data.title)
        popupContent  +=  "
" + data.title + "
";

      if(data.start != null){
        popupContent +="
";
        startLbl=" ";
        startDate=moment(data.start).format("DD MMMM YYYY");
        endDate="";
        hoursStr="
";
        if(data.allDay)
          hoursStr+=tradDynForm.allday;
        else
          hoursStr+=" "+moment(data.start).format("H:mm");
        if(data.end != null){
          if(startDate != moment(data.end).format("DD MMMM YYYY")){
            startLbl+=trad.fromdate+" ";
            endDate=" "+trad.todatemin+" "+moment(data.end).format("DD MMMM YYYY");
          }
          if(!data.allDay)
            hoursStr+= " - "+moment(data.end).format("H:mm");
        }
        popupContent += startLbl+startDate+endDate+hoursStr;
        popupContent +="
";
      }
      popupContent += "
";
      //Short description
      if ("undefined" != typeof data['shortDescription'] && data['shortDescription'] != "" && data['shortDescription'] != null) {
        popupContent += "
"
                + "
" + data['shortDescription'] + "
"
              + "
";
      }
      //Contacts information
  //    popupContent += this.getPopupContactsInformation(data);
      //address
//      popupContent += this.getPopupAddressInformation(data);
     // popupContent += directory.getDateFormated(data,true);

      popupContent += '
';

                popupContent += "";
      popupContent += '
 en savoir +
';
      popupContent += '';

      return popupContent;
    }
}<|endoftext|>


<commit_before>//gisportal common JS stuff

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

function showError(msg) {
    bootbox.alert({
        title: "Error",
        message: msg+"!",
        size: 'small'
    });
}

function onUploadFormSubmit() {

    var form = $('#uploadForm')[0];
    var client = $('#client_id')[0].value;

    if(client=='') {
        showError(GP.clientRequired);
        return false;
    }

    var editingProject = $('#project_name')[0].value;

    if ($('#userfile')[0].files.length==0) {
        showError(GP.noFile);
        return false;
    }

    var file = $('#userfile')[0].files[0].name;
    var newProject = file.split('.')[0];
    var ext = file.split('.')[1];

    form.action = form.action+client;

    //client side validation
    if (ext.toLowerCase() !== 'qgs') {
        showError(GP.onlyQgs);
        form.reset();
        return false;
    }
    if (editingProject && editingProject !== newProject) {
        showError(GP.differentProjects+" "+editingProject+ ": "+newProject);
        form.reset();
        return false;
    }
}

function confirmLink(msg,name,url) {
    bootbox.confirm(msg.replaceAll('{name}',name), function(doIt){
        if(doIt) {
            window.location = url;
        }
    });
}

function addRole(group, back) {
    //get user and role from ui
    var user = $('input.typeahead').typeahead("getActive");
    var role_id = $('#user_role').val();
    if(!user) {
        showError(GP.userRequired);
        return false;
    }

    window.location = GP.settings.siteUrl + "/users/add_role/"+group+"/"+user.id+"/"+role_id+"/"+back;
}

function addRoleMulti(user) {

    var groups = $('#project_group_id').val();
    var role_id = $('#user_role').val();

    if(!groups || groups.length == 0) {
        showError('Select groups');
        return false
    }

    var arr = encodeURIComponent(groups.map(Number));

    window.location = GP.settings.siteUrl + "/users/add_role_multi/"+arr+"/"+user+"/"+role_id;
}

function addLayerMulti(layer) {

    var groups = $('#project_group_id').val();
    var destination = $('#destination').val();

    if(!groups || groups.length == 0) {
        showError('Select groups');
        return false
    }

    var arr = encodeURIComponent(groups.map(Number));

    window.location = GP.settings.siteUrl + "/project_groups/add_layer/"+arr+"/"+layer+"/"+destination;
}

function addGroup(back) {

    var client_id = $('#client_id').val();

    bootbox.prompt({
        title: GP.addGroupTitle,
        message: GP.addGroupMsg,
        callback: function (name) {
            if(name) {
                window.location = GP.settings.siteUrl + "/project_groups/add_group/"+client_id+"/"+encodeURIComponent(name)+"?back="+back;
            }
        }
    });
}

function chooseGroup(client, target) {

    //disable button
    $('#copyBtn').css("pointer-events", "none");

    var groups = [];

    var url = GP.settings.siteUrl + '/project_groups/get_list/' + client + '/true';

    $.getJSON(url, function (data) {
        $.each(data, function (key, entry) {
            if(entry.id == target) {
                return;
            }
            groups.push({"value": entry.id, "text": entry.name});
        });

        if(groups.length == 0) {
            showError("No available groups!");
            return false;
        }

        bootbox.prompt({
            title: GP.copyTitle,
            message: GP.copyMsg,
            inputType: 'radio',
            inputOptions: groups,
            callback: function (source) {
                //result = group_id or null
                if(source) {
                    window.location = GP.settings.siteUrl + "/users/copy_roles/"+source+"/"+target;
                }
            }
        });

        //enable button back
        $('#copyBtn').css("pointer-events", "auto");
    });
}

function switchRole(group, user, role, back) {
    //assuming we only have roles 20 and 21 to switch between.
    var newRole = 0;

    if (role == 20) {
        newRole = 21;
    } else if (role == 21) {
        newRole = 20;
    }

    if(newRole>0) {
        window.location = GP.settings.siteUrl + "/users/set_role/"+group+"/"+user+"/"+newRole+"/"+back;
    }
}

function onProjectGroupEditClick() {
    var group = $('#project_group_id').val();
    if(group) {
        var url = GP.settings.siteUrl + '/project_groups/edit/' + group;
        window.location = url;
    }
}

function onGroupChange(id,sel) {
    var btn = $('#projectGroupEditBtn');
    var val = sel.value;
    if(id==val) {
        btn.removeClass('disabled');
    } else {
        btn.addClass('disabled');
    }
}

function getParentGroups(sel, group)
{
    var val = sel.value;
    var list = $('#parent_id');

    var url = GP.settings.siteUrl+'/project_groups/get_parents/'+val+'/'+group;

    if (val > 0) {

        //get new parent groups
        list.empty();
        list.append('<option></option>');
        list.prop('selectedIndex', 0);

        $.getJSON(url, function (data) {
            $.each(data, function (key, entry) {
                list.append($('<option></option>').attr('value', entry.id).text(entry.name));
            })
        });
    }
}

function onClientChange(sel,action)
{
    var val = sel.value;
    var div = $('#templateDiv');
    var group = $('#project_group_id');
    var groupDiv = $('#groupDiv');
    var url = GP.settings.siteUrl+'/project_groups/get_list/'+val;

    if(action == 2) {
        div = $('#uploadDiv');
    }

    if (val > 0) {
        div.show();

        //get new client groups
        group.empty();
        if(action != 3) {
            group.append('<option disabled>' + GP.selectGroup + '</option>');
        }
        group.prop('selectedIndex', 0);

        $.getJSON(url, function (data) {
            $.each(data, function (key, entry) {
                group.append($('<option></option>').attr('value', entry.id).text(entry.name));
            })
        });

        groupDiv.show();

    } else {
        div.hide();
        groupDiv.hide();
    }
}

function checkValues() {
    var baseList = $('#lstBase2').getValues();
    var baseIds = document.getElementById('base_ids');
    baseIds.value = ('{'+baseList.join()+'}');

    var extraList = $('#lstExtra2').getValues();
    var extraIds = document.getElementById('extra_ids');
    extraIds.value = ('{'+extraList.join()+'}');
}

function moveItem(list1, list2) {
    $('select').moveToListAndDelete(list1, list2);
    //e.preventDefault();
}

function moveAllItems(list1, list2) {
    $('select').moveAllToListAndDelete(list1, list2);
    //e.preventDefault();
}

function moveUp(list) {
    $('select').moveUpDown(list, true, false);
}

function moveDown(list) {
    $('select').moveUpDown(list, false, true);
}

//    //example calling over id
//
//    $('#btnAllLeft').click(function (e) {
//        $('select').moveAllToListAndDelete('#lstBox2', '#lstBox1');
//        e.preventDefault();
//    });

function openSubGroups(index, row) {
    return row.gp_type == 1;

}

function makeGroupAction(value, row) {

    var type = row.type;
    var text;

    //project
    if(type == 0) {
        text = GP.group;
    } else if (type == 1) {
        text = GP.menuGroup;
    }

    return ''+text+'';
}<commit_msg>Use strict comparing<commit_after>//gisportal common JS stuff

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

function showError(msg) {
    bootbox.alert({
        title: "Error",
        message: msg+"!",
        size: 'small'
    });
}

function onUploadFormSubmit() {

    var form = $('#uploadForm')[0];
    var client = $('#client_id')[0].value;

    if(client === '') {
        showError(GP.clientRequired);
        return false;
    }

    var editingProject = $('#project_name')[0].value;

    if ($('#userfile')[0].files.length === 0) {
        showError(GP.noFile);
        return false;
    }

    var file = $('#userfile')[0].files[0].name;
    var newProject = file.split('.')[0];
    var ext = file.split('.')[1];

    form.action = form.action+client;

    //client side validation
    if (ext.toLowerCase() !== 'qgs') {
        showError(GP.onlyQgs);
        form.reset();
        return false;
    }
    if (editingProject && editingProject !== newProject) {
        showError(GP.differentProjects+" "+editingProject+ ": "+newProject);
        form.reset();
        return false;
    }
}

function confirmLink(msg,name,url) {
    bootbox.confirm(msg.replaceAll('{name}',name), function(doIt){
        if(doIt) {
            window.location = url;
        }
    });
}

function addRole(group, back) {
    //get user and role from ui
    var user = $('input.typeahead').typeahead("getActive");
    var role_id = $('#user_role').val();
    if(!user) {
        showError(GP.userRequired);
        return false;
    }

    window.location = GP.settings.siteUrl + "/users/add_role/"+group+"/"+user.id+"/"+role_id+"/"+back;
}

function addRoleMulti(user) {

    var groups = $('#project_group_id').val();
    var role_id = $('#user_role').val();

    if(!groups || groups.length === 0) {
        showError('Select groups');
        return false
    }

    var arr = encodeURIComponent(groups.map(Number));

    window.location = GP.settings.siteUrl + "/users/add_role_multi/"+arr+"/"+user+"/"+role_id;
}

function addLayerMulti(layer) {

    var groups = $('#project_group_id').val();
    var destination = $('#destination').val();

    if(!groups || groups.length == 0) {
        showError('Select groups');
        return false
    }

    var arr = encodeURIComponent(groups.map(Number));

    window.location = GP.settings.siteUrl + "/project_groups/add_layer/"+arr+"/"+layer+"/"+destination;
}

function addGroup(back) {

    var client_id = $('#client_id').val();

    bootbox.prompt({
        title: GP.addGroupTitle,
        message: GP.addGroupMsg,
        callback: function (name) {
            if(name) {
                window.location = GP.settings.siteUrl + "/project_groups/add_group/"+client_id+"/"+encodeURIComponent(name)+"?back="+back;
            }
        }
    });
}

function chooseGroup(client, target) {

    //disable button
    $('#copyBtn').css("pointer-events", "none");

    var groups = [];

    var url = GP.settings.siteUrl + '/project_groups/get_list/' + client + '/true';

    $.getJSON(url, function (data) {
        $.each(data, function (key, entry) {
            if(entry.id === target) {
                return;
            }
            groups.push({"value": entry.id, "text": entry.name});
        });

        if(groups.length === 0) {
            showError("No available groups!");
            return false;
        }

        bootbox.prompt({
            title: GP.copyTitle,
            message: GP.copyMsg,
            inputType: 'radio',
            inputOptions: groups,
            callback: function (source) {
                //result = group_id or null
                if(source) {
                    window.location = GP.settings.siteUrl + "/users/copy_roles/"+source+"/"+target;
                }
            }
        });

        //enable button back
        $('#copyBtn').css("pointer-events", "auto");
    });
}

function switchRole(group, user, role, back) {
    //assuming we only have roles 20 and 21 to switch between.
    var newRole = 0;

    if (role === 20) {
        newRole = 21;
    } else if (role === 21) {
        newRole = 20;
    }

    if(newRole>0) {
        window.location = GP.settings.siteUrl + "/users/set_role/"+group+"/"+user+"/"+newRole+"/"+back;
    }
}

function onProjectGroupEditClick() {
    var group = $('#project_group_id').val();
    if(group) {
        var url = GP.settings.siteUrl + '/project_groups/edit/' + group;
        window.location = url;
    }
}

function onGroupChange(id,sel) {
    var btn = $('#projectGroupEditBtn');
    var val = sel.value;
    if(id === val) {
        btn.removeClass('disabled');
    } else {
        btn.addClass('disabled');
    }
}

function getParentGroups(sel, group)
{
    var val = sel.value;
    var list = $('#parent_id');

    var url = GP.settings.siteUrl+'/project_groups/get_parents/'+val+'/'+group;

    if (val > 0) {

        //get new parent groups
        list.empty();
        list.append('<option></option>');
        list.prop('selectedIndex', 0);

        $.getJSON(url, function (data) {
            $.each(data, function (key, entry) {
                list.append($('<option></option>').attr('value', entry.id).text(entry.name));
            })
        });
    }
}

function onClientChange(sel,action)
{
    var val = sel.value;
    var div = $('#templateDiv');
    var group = $('#project_group_id');
    var groupDiv = $('#groupDiv');
    var url = GP.settings.siteUrl+'/project_groups/get_list/'+val;

    if(action === 2) {
        div = $('#uploadDiv');
    }

    if (val > 0) {
        div.show();

        //get new client groups
        group.empty();
        if(action !== 3) {
            group.append('<option disabled>' + GP.selectGroup + '</option>');
        }
        group.prop('selectedIndex', 0);

        $.getJSON(url, function (data) {
            $.each(data, function (key, entry) {
                group.append($('<option></option>').attr('value', entry.id).text(entry.name));
            })
        });

        groupDiv.show();

    } else {
        div.hide();
        groupDiv.hide();
    }
}

function checkValues() {
    var baseList = $('#lstBase2').getValues();
    var baseIds = document.getElementById('base_ids');
    baseIds.value = ('{'+baseList.join()+'}');

    var extraList = $('#lstExtra2').getValues();
    var extraIds = document.getElementById('extra_ids');
    extraIds.value = ('{'+extraList.join()+'}');
}

function moveItem(list1, list2) {
    $('select').moveToListAndDelete(list1, list2);
    //e.preventDefault();
}

function moveAllItems(list1, list2) {
    $('select').moveAllToListAndDelete(list1, list2);
    //e.preventDefault();
}

function moveUp(list) {
    $('select').moveUpDown(list, true, false);
}

function moveDown(list) {
    $('select').moveUpDown(list, false, true);
}

//    //example calling over id
//
//    $('#btnAllLeft').click(function (e) {
//        $('select').moveAllToListAndDelete('#lstBox2', '#lstBox1');
//        e.preventDefault();
//    });

function openSubGroups(index, row) {
    return row.gp_type === 1;

}

function makeGroupAction(value, row) {

    var type = row.type;
    var text;

    //project
    if(type === 0) {
        text = GP.group;
    } else if (type === 1) {
        text = GP.menuGroup;
    }

    return ''+text+'';
}<|endoftext|>


<commit_before>// NOTE TO READER:
// According to the blessed qqTimer, the "average" and the "mean" are different
// things. The "mean" is the arithmetic mean, while the average removes the best
// and worst times before computing the mean. I know this is wrong, but I am a
// simple minion who has no free will nor wishes to have it.
(function() {

  function bestAverage(times, count) {
    var best = -1;
    for (var i = 0, len = times.length-count; i <= len; ++i) {
      var subList = times.slice(i, i+count);
      removeBestWorst(subList);
      var average = mean(subList);
      if (average < best || best === -1) {
        best = average;
      }
    }
    return best;
  }

  function bestMean(times, count) {
    var best = -1;
    for (var i = 0, len = times.length-(count-1); i < len; ++i) {
      var subList = times.slice(i, i+count);
      var average = mean(subList);
      if (average < best || best === -1) {
        best = average;
      }
    }
    return best;
  }

  function bestTime(times) {
    var best = -1;
    for (var i = 0, len = times.length; i < len; ++i) {
      if (i === 0 || times[i] < best) {
        best = times[i];
      }
    }
    return best;
  }

  function computeStatistics(times) {
    // Compute the general statistics.
    var average = NaN;
    var best = NaN;
    var count = times.length;
    var worst = NaN;
    if (times.length > 0) {
      best = bestTime(times);
      worst = worstTime(times);
    }
    if (times.length > 2) {
      var t = times.slice();
      removeBestWorst(t);
      average = mean(t);
    }
    var res = {average: average, best: best, count: count, worst: worst,
      averages: []};

    // Compute the averages table
    if (times.length > 2) {
      res.averages.push(["mo3", lastMean(times, 3), bestMean(times, 3)]);
    }
    var averages = [5, 12, 50, 100, 1000];
    for (var i = 0, len = averages.length; i < len; ++i) {
      var avg = averages[i];
      if (avg > times.length) {
        break;
      }
      res.averages.push(['' + avg, lastAverage(times, avg),
        bestAverage(times, avg)]);
    }
    return res;
  }

  function lastAverage(times, count) {
    if (times.length < count) {
      return NaN;
    }
    var subList = times.slice(times.length-count, times.length);
    removeBestWorst(subList);
    return mean(subList);
  }

  function lastMean(times, count) {
    if (times.length < count) {
      return NaN;
    }
    var subList = times.slice(times.length-count, times.length);
    return mean(subList);
  }

  function mean(times) {
    var sum = 0;
    for (var i = 0, len = times.length; i < len; ++i) {
      sum += times[i];
    }
    return sum / times.length;
  }

  function removeBestWorst(times) {
    if (times.length === 0) {
      return;
    }

    // In O(n), find the max and min values.
    var max = 0;
    var maxIdx = -1;
    var min = 0;
    var minIdx = -1;
    for (var i = 0, len = times.length; i < len; ++i) {
      var time = times[i];
      if (time > max || maxIdx === -1) {
        max = time;
        maxIdx = i;
      }
      if (time < min || minIdx === -1) {
        min = time;
        minIdx = i;
      }
    }

    // Remove the max and min values.
    times.splice(maxIdx, 1);
    if (minIdx < maxIdx) {
      times.splice(minIdx, 1);
    } else if (minIdx > maxIdx) {
      times.splice(minIdx-1, 1);
    }
  }

  function statsForSolves(solves) {
    var times = [];
    for (var i = 0, len = solves.length; i < len; ++i) {
      times[i] = window.app.solveTime(solves[i]);
    }
    return computeStatistics(times);
  }

  function worstTime(times) {
    var worst = -1;
    for (var i = 0, len = times.length; i < len; ++i) {
      if (i === 0 || times[i] > worst) {
        worst = times[i];
      }
    }
    return worst;
  }

  if (!window.app) {
    window.app = {};
  }
  window.app.computeStatistics = computeStatistics;
  window.app.statsForSolves = statsForSolves;

})();<commit_msg>compute last average at the top of the list<commit_after>// NOTE TO READER:
// According to the blessed qqTimer, the "average" and the "mean" are different
// things. The "mean" is the arithmetic mean, while the average removes the best
// and worst times before computing the mean. I know this is wrong, but I am a
// simple minion who has no free will nor wishes to have it.
(function() {

  function bestAverage(times, count) {
    var best = -1;
    for (var i = 0, len = times.length-count; i <= len; ++i) {
      var subList = times.slice(i, i+count);
      removeBestWorst(subList);
      var average = mean(subList);
      if (average < best || best === -1) {
        best = average;
      }
    }
    return best;
  }

  function bestMean(times, count) {
    var best = -1;
    for (var i = 0, len = times.length-(count-1); i < len; ++i) {
      var subList = times.slice(i, i+count);
      var average = mean(subList);
      if (average < best || best === -1) {
        best = average;
      }
    }
    return best;
  }

  function bestTime(times) {
    var best = -1;
    for (var i = 0, len = times.length; i < len; ++i) {
      if (i === 0 || times[i] < best) {
        best = times[i];
      }
    }
    return best;
  }

  function computeStatistics(times) {
    // Compute the general statistics.
    var average = NaN;
    var best = NaN;
    var count = times.length;
    var worst = NaN;
    if (times.length > 0) {
      best = bestTime(times);
      worst = worstTime(times);
    }
    if (times.length > 2) {
      var t = times.slice();
      removeBestWorst(t);
      average = mean(t);
    }
    var res = {average: average, best: best, count: count, worst: worst,
      averages: []};

    // Compute the averages table
    if (times.length > 2) {
      res.averages.push(["mo3", lastMean(times, 3), bestMean(times, 3)]);
    }
    var averages = [5, 12, 50, 100, 1000];
    for (var i = 0, len = averages.length; i < len; ++i) {
      var avg = averages[i];
      if (avg > times.length) {
        break;
      }
      res.averages.push(['' + avg, lastAverage(times, avg),
        bestAverage(times, avg)]);
    }
    return res;
  }

  function lastAverage(times, count) {
    if (times.length < count) {
      return NaN;
    }
    var subList = times.slice(0, count);
    removeBestWorst(subList);
    return mean(subList);
  }

  function lastMean(times, count) {
    if (times.length < count) {
      return NaN;
    }
    var subList = times.slice(0, count);
    return mean(subList);
  }

  function mean(times) {
    var sum = 0;
    for (var i = 0, len = times.length; i < len; ++i) {
      sum += times[i];
    }
    return sum / times.length;
  }

  function removeBestWorst(times) {
    if (times.length === 0) {
      return;
    }

    // In O(n), find the max and min values.
    var max = 0;
    var maxIdx = -1;
    var min = 0;
    var minIdx = -1;
    for (var i = 0, len = times.length; i < len; ++i) {
      var time = times[i];
      if (time > max || maxIdx === -1) {
        max = time;
        maxIdx = i;
      }
      if (time < min || minIdx === -1) {
        min = time;
        minIdx = i;
      }
    }

    // Remove the max and min values.
    times.splice(maxIdx, 1);
    if (minIdx < maxIdx) {
      times.splice(minIdx, 1);
    } else if (minIdx > maxIdx) {
      times.splice(minIdx-1, 1);
    }
  }

  function statsForSolves(solves) {
    var times = [];
    for (var i = 0, len = solves.length; i < len; ++i) {
      times[i] = window.app.solveTime(solves[i]);
    }
    return computeStatistics(times);
  }

  function worstTime(times) {
    var worst = -1;
    for (var i = 0, len = times.length; i < len; ++i) {
      if (i === 0 || times[i] > worst) {
        worst = times[i];
      }
    }
    return worst;
  }

  if (!window.app) {
    window.app = {};
  }
  window.app.computeStatistics = computeStatistics;
  window.app.statsForSolves = statsForSolves;

})();
<|endoftext|>


<commit_before>(function() {

  function Header() {
    this._element = $('#header');
    this._puzzles = new Puzzles();
    this._showingDropdown = false;

    this._nameLabel = this._element.find('.name');
    this._nameLabel.click(this._toggle.bind(this));
    this._puzzles.onExit = this._toggle.bind(this);
  }

  Header.prototype.height = function() {
    return 44;
  };

  Header.prototype.layout = function(attrs) {
    if (attrs.headerOpacity === 0) {
      this._element.css({display: 'none'});
    } else {
      this._element.css({
        display: 'block',
        opacity: attrs.headerOpacity,
        top: attrs.headerOffset
      });
    }
  };

  Header.prototype._toggle = function() {
    if (this._showingDropdown) {
      // Hide the dropdown.
      this._puzzles.hide();
    } else {
      // Show the dropdown.
      this._puzzles.show();
    }
    this._showingDropdown = !this._showingDropdown;
  };

  function Puzzles() {
    this._element = $('#puzzles');
    this._showing = false;

    // Setup the shielding.
    this._shielding = $('<div />');
    this._shielding.css({
      position: 'fixed',
      'z-index': this._element.css('z-index') - 1,
      width: '100%',
      height: '100%',
      display: 'none',
      'background-color': 'rgba(0, 0, 0, 0.5)'
    });

    // If they click on the background shield, the puzzles list closes.
    this._shielding.click(function() {
      if (!this._showing) {
        return;
      }
      if ('function' !== typeof this.onExit) {
        throw new Error('invalid onExit handler');
      }
      this.onExit();
    }.bind(this));

    $(document.body).append(this._shielding);

    this.onExit = null;
  }

  Puzzles.prototype.hide = function() {
    this._element.stop(true, false);
    this._shielding.stop(true, false);
    this._element.slideUp();
    this._shielding.fadeOut();

    // Re-enable keyboard events for other things.
    window.app.keyboard.pop();

    this._showing = false;
  };

  Puzzles.prototype.layout = function() {
  };

  Puzzles.prototype.show = function() {
    this._element.stop(true, false);
    this._shielding.stop(true, false);
    this._element.slideDown();
    this._shielding.fadeIn();

    // Disable keyboard events from other things.
    window.app.keyboard.push({});

    this._showing = true;
  };

  window.app.Header = Header;

})();
<commit_msg>started worrying about scrollbars<commit_after>(function() {

  function Header() {
    this._element = $('#header');
    this._puzzles = new Puzzles();
    this._showingDropdown = false;

    this._nameLabel = this._element.find('.name');
    this._nameLabel.click(this._toggle.bind(this));
    this._puzzles.onExit = this._toggle.bind(this);
  }

  Header.prototype.height = function() {
    return 44;
  };

  Header.prototype.layout = function(attrs) {
    if (attrs.headerOpacity === 0) {
      this._element.css({display: 'none'});
    } else {
      this._element.css({
        display: 'block',
        opacity: attrs.headerOpacity,
        top: attrs.headerOffset
      });
    }
  };

  Header.prototype._toggle = function() {
    if (this._showingDropdown) {
      // Hide the dropdown.
      this._puzzles.hide();
    } else {
      // Show the dropdown.
      this._puzzles.show();
    }
    this._showingDropdown = !this._showingDropdown;
  };

  function Puzzles() {
    this._element = $('#puzzles');
    this._showing = false;

    // Setup the shielding.
    this._shielding = $('<div />');
    this._shielding.css({
      position: 'fixed',
      'z-index': this._element.css('z-index') - 1,
      width: '100%',
      height: '100%',
      display: 'none',
      'background-color': 'rgba(0, 0, 0, 0.5)'
    });

    // If they click on the background shield, the puzzles list closes.
    this._shielding.click(function() {
      if (!this._showing) {
        return;
      }
      if ('function' !== typeof this.onExit) {
        throw new Error('invalid onExit handler');
      }
      this.onExit();
    }.bind(this));

    $(document.body).append(this._shielding);

    this.onExit = null;
  }

  Puzzles.prototype.hide = function() {
    // TODO: here, hide the scrollbar.
    this._element.css({'overflow-x': 'hidden'});

    this._element.stop(true, false);
    this._shielding.stop(true, false);
    this._shielding.fadeOut();
    this._element.slideUp();

    // Re-enable keyboard events for other things.
    window.app.keyboard.pop();

    this._showing = false;
  };

  Puzzles.prototype.layout = function() {
  };

  Puzzles.prototype.show = function() {
    this._element.stop(true, false);
    this._shielding.stop(true, false);
    this._element.slideDown({
      complete: function() {
        this._element.css({'overflow-x': 'scroll'});
        this._resizeForScrollbar();
      }.bind(this)
    });
    this._shielding.fadeIn();

    // Disable keyboard events from other things.
    window.app.keyboard.push({});

    this._showing = true;
  };

  Puzzles.prototype._resizeForScrollbar = function() {
    // TODO: here, increase/decrease the size of the puzzles dropdown.
  };

  window.app.Header = Header;

})();
<|endoftext|>