<commit_before>
const ytdl = require('ytdl-core');

// Most braindead play command possible.
// Will play a song to its conclusion with no way to stop it.
// Just a bit of an exercise for now.
module.exports = {
    braindead: (message, config, _, url) => {
        const vc = message.member.voiceChannel;
        if (!vc) {
            return message.reply('Join a voice channel before using the command.');
        }
        if (!url) {
            return message.reply('Provide a valid URL.');
        }

        if (message.guild.voiceConnection) {
            return message.channel.send('Interrupting song...')
                .then(() => {
                    const dispatcher = message.guild.voiceConnection.dispatcher;
                    dispatcher.end();
                    setTimeout(() => {
                        module.exports.braindead(message, config, _, url);
                    }, 500);
                });
        }
        // Adapted from https://github.com/fent/node-ytdl-core/blob/master/example/discord.js
        return vc.join()
            .then((c) => {
                const stream = ytdl(url, {
                    filter: 'audioonly',
                });
                const dispatcher = c.playStream(
                    stream,
                    { passes: config.music.passes },
                );
                dispatcher.setVolume(config.music.volume);
                dispatcher.on('end', () => {
                    vc.leave();
                });
                message.channel.send(`Playing song at url:\n${url}`);
            })
            .catch(console.error);
    },

    pleasestop: (message) => {
        if (message.guild.voiceConnection) {
            return message.channel.send('Interrupting song...')
                .then(() => {
                    const dispatcher = message.guild.voiceConnection.dispatcher;
                    dispatcher.end();
                });
        }
        return message.channel.send('Stop what?');
    },
};
<commit_msg>Ugly (but functional) queue command<commit_after>
const ytdl = require('ytdl-core');

let queue = {};

module.exports = {
    fn: command => (
        (message, ...other) => {
            command(message.guild.voiceConnection, message, ...other);
        }
    ),

    violence: (voiceConn, message, config, _, url) => {
        if (voiceConn) {
            return module.exports.pleasestop(voiceConn, message)
                .then(() => {
                    setTimeout(() => {
                        module.exports.violence(voiceConn, message, config, _, url);
                    }, 500);
                });
        }

        const vc = message.member.voiceChannel;
        if (!vc) {
            return message.reply('Join a voice channel before using the command.');
        }
        if (!url) {
            return message.reply('Provide a valid URL.');
        }
        // Adapted from https://github.com/fent/node-ytdl-core/blob/master/example/discord.js
        return vc.join()
            .then((c) => {
                const stream = ytdl(url, {
                    filter: 'audioonly',
                });
                const dispatcher = c.playStream(
                    stream,
                    { passes: config.music.passes },
                );
                dispatcher.setVolume(config.music.volume);
                dispatcher.on('end', () => {
                    if (queue[message.guild.id] && queue[message.guild.id].length > 0) {
                        const newStream = ytdl(queue[message.guild.id].shift(), {
                            filter: 'audioonly',
                        });
                        c.playStream(
                            newStream,
                            { passes: config.music.passes },
                        ).setVolume(config.music.volume);
                    } else {
                        vc.leave();
                    }
                });
                message.channel.send(`Playing song at url:\n${url}`);
            })
            .catch(console.error);
    },

    pleasestop: (voiceConn, message) => {
        if (voiceConn) {
            return new Promise((resolve, reject) => {
                message.channel.send('Interrupting song...')
                    .then((promiseMessage) => {
                        const dispatcher = voiceConn.dispatcher;
                        dispatcher.end();
                        resolve(promiseMessage);
                    })
                    .catch(reject);
            });
        }
        return message.channel.send('Stop what?');
    },

    play: (voiceConn, message, _, config, url) => {
        if (queue[message.guild.id]) {
            queue[message.guild.id].push(url);
        } else {
            queue[message.guild.id] = [url];
        }
        if (!voiceConn) {
            module.exports.violence(voiceConn, message, _, config, queue[message.guild.id].shift);
        }
        return message.channel.send(`Added this song to the queue:\n${url}`);
            // .then(() => {
            //     const dispatcher = voiceConn.dispatcher;
            //     dispatcher.on('end', () => {
            //         module.exports.violence(voiceConn, message, config, _, url);
            //     });
            // });
    },
};
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

angular.module('mcp.organizations', ['ui.bootstrap'])

    .controller('OrganizationMenuController', ['$scope', 'OrganizationContext',
      function ($scope, OrganizationContext) {

        $scope.organizations = OrganizationContext.list;
        $scope.currentOrganization = OrganizationContext.currentOrganization;
        $scope.OrganizationContext = OrganizationContext;

        $scope.$watch('OrganizationContext.currentOrganization', function () {
          $scope.currentOrganization = OrganizationContext.currentOrganization;
        });

      }])

    .controller('OrganizationListController', ['$scope', '$stateParams', 'OrganizationContext',
      function ($scope, $stateParams, OrganizationContext) {

        $scope.organizations = OrganizationContext.list;
        $scope.currentOrganization = OrganizationContext.currentOrganization;
        $scope.orderProp = 'name';
        $scope.$stateParams = $stateParams;

        $scope.isCurrent = function (organization) {
          return organization === $scope.currentOrganization;
        };

        $scope.$watch('$stateParams.organizationId', function (newOrganizationId) {
          // (HACK: needed to get list updated after organization created)
          $scope.organizations = OrganizationContext.list;

          OrganizationContext.setCurrentOrganization(newOrganizationId);
          $scope.currentOrganization = OrganizationContext.currentOrganization;
        });

      }])

    .controller('OrganizationDetailsController', ['$scope', '$stateParams', 'OrganizationService', 'ServiceSpecificationService', 'ServiceInstanceService',
      function ($scope, $stateParams, OrganizationService, ServiceSpecificationService, ServiceInstanceService) {

        $scope.organization = OrganizationService.get({organizationId: $stateParams.organizationId});
        $scope.specifications = ServiceSpecificationService.query({organizationId: $stateParams.organizationId}, function (specifications) {
        });
        $scope.serviceInstances = ServiceInstanceService.query({organizationId: $stateParams.organizationId}, function (serviceInstances) {
        });

        $scope.userHasWriteAccess = function () {

// FIXME: rewrite to use a list of organizations the user is a member of
          //return UserService.isAdminMemberOf($scope.organization.organizationId);
//          return $scope.organization.teams[0].members[0] === $scope.currentUser.name;
          return true;
        };
      }])

    .controller('OrganizationCreateController', ['$scope', '$location', 'OrganizationService', 'OrganizationContext',
      function ($scope, $location, OrganizationService, OrganizationContext) {
        $scope.organization = {organizationId: null, name: null};
        $scope.message = null;
        $scope.alertMessages = null;
        //$("#rPreferredLogin").focus();
        $scope.isTrue = true;

        /**
         * @returns true when there is enough data in the form
         * to try to submit it. This is not to say that data is
         * valid. pressing submit will cause a series of
         * validator to be evaluated
         */
        $scope.formIsSubmitable = function () {
          return ($scope.organization.organizationId && $scope.organization.name);
        };

        $scope.submit = function () {
          $scope.message = null;
          $scope.alertMessages = null;

          // validate input values
          if ($scope.organization.organizationId) {
            if ($scope.organization.organizationId === "test") {
              $scope.alertMessages = ["Test!? Really? ...You have to be more visionary than that!"];
              return;
            }
          }

          // Send request
          $scope.message = "Sending request to create organization...";

          $scope.busyPromise = OrganizationService.create($scope.organization,
              function (data) {
                $location.path('/orgs/' + $scope.organization.organizationId).replace();
                $scope.message = ["Organization created: " + data];
                OrganizationContext.list = $scope.currentUser ? OrganizationService.query({member: $scope.currentUser.name}) : [];
              },
              function (error) {
                $scope.message = null;
                $scope.alertMessages = ["Error on the serverside :( ", error];
              }
          );

        };
      }])

    // OrganizationContext
    // - the list of organizations the user is a member of
    // - the currently selected organization
    .service("OrganizationContext", [function () {

        // Organizations that the current user is a member of
        this.list = [];
        this.currentOrganization = null;

        this.setUsersOrganizations = function (organizations) {
          this.list = organizations;
        };

        this.setCurrentOrganization = function (target) {
          if (angular.isString(target)) {
            this.currentOrganization = this.getOrganizationById(target);
          } else {
            if (this.containsOrganization(target)) {
              this.currentOrganization = target;
            }
          }
        };

        this.getOrganizationById = function (organizationId) {
          for (var i = 0; i < this.list.length; i++) {
            if (organizationId === this.list[i].organizationId) {
              return this.list[i];
            }
          }
        };

        this.containsOrganization = function (organization) {
          return this.list.indexOf(organization) > -1;
        };

      }])
    ;

<commit_msg>ECLOUD-137: Temporary fix of missing organization URL<commit_after>'use strict';

/* Controllers */

angular.module('mcp.organizations', ['ui.bootstrap'])

    .controller('OrganizationMenuController', ['$scope', 'OrganizationContext',
      function ($scope, OrganizationContext) {

        $scope.organizations = OrganizationContext.list;
        $scope.currentOrganization = OrganizationContext.currentOrganization;
        $scope.OrganizationContext = OrganizationContext;

        $scope.$watch('OrganizationContext.currentOrganization', function () {
          $scope.currentOrganization = OrganizationContext.currentOrganization;
        });

      }])

    .controller('OrganizationListController', ['$scope', '$stateParams', 'OrganizationContext',
      function ($scope, $stateParams, OrganizationContext) {

        $scope.organizations = OrganizationContext.list;
        $scope.currentOrganization = OrganizationContext.currentOrganization;
        $scope.orderProp = 'name';
        $scope.$stateParams = $stateParams;

        $scope.isCurrent = function (organization) {
          return organization === $scope.currentOrganization;
        };

        $scope.$watch('$stateParams.organizationId', function (newOrganizationId) {
          // (HACK: needed to get list updated after organization created)
          $scope.organizations = OrganizationContext.list;

          OrganizationContext.setCurrentOrganization(newOrganizationId);
          $scope.currentOrganization = OrganizationContext.currentOrganization;
        });

      }])

    .controller('OrganizationDetailsController', ['$scope', '$stateParams', 'OrganizationService', 'ServiceSpecificationService', 'ServiceInstanceService',
      function ($scope, $stateParams, OrganizationService, ServiceSpecificationService, ServiceInstanceService) {

        $scope.organization = OrganizationService.get({organizationId: $stateParams.organizationId});
        $scope.specifications = ServiceSpecificationService.query({organizationId: $stateParams.organizationId}, function (specifications) {
        });
        $scope.serviceInstances = ServiceInstanceService.query({organizationId: $stateParams.organizationId}, function (serviceInstances) {
        });

        $scope.userHasWriteAccess = function () {

// FIXME: rewrite to use a list of organizations the user is a member of
          //return UserService.isAdminMemberOf($scope.organization.organizationId);
//          return $scope.organization.teams[0].members[0] === $scope.currentUser.name;
          return true;
        };
      }])

    .controller('OrganizationCreateController', ['$scope', '$location', 'OrganizationService', 'OrganizationContext',
      function ($scope, $location, OrganizationService, OrganizationContext) {
        $scope.organization = {organizationId: null, name: null, url: "http://hardcoded.bwah.org"};
        $scope.message = null;
        $scope.alertMessages = null;
        //$("#rPreferredLogin").focus();
        $scope.isTrue = true;

        /**
         * @returns true when there is enough data in the form
         * to try to submit it. This is not to say that data is
         * valid. pressing submit will cause a series of
         * validator to be evaluated
         */
        $scope.formIsSubmitable = function () {
          return ($scope.organization.organizationId && $scope.organization.name);
        };

        $scope.submit = function () {
          $scope.message = null;
          $scope.alertMessages = null;

          // validate input values
          if ($scope.organization.organizationId) {
            if ($scope.organization.organizationId === "test") {
              $scope.alertMessages = ["Test!? Really? ...You have to be more visionary than that!"];
              return;
            }
          }

          // Send request
          $scope.message = "Sending request to create organization...";

          $scope.busyPromise = OrganizationService.create($scope.organization,
              function (data) {
                $location.path('/orgs/' + $scope.organization.organizationId).replace();
                $scope.message = ["Organization created: " + data];
                OrganizationContext.list = $scope.currentUser ? OrganizationService.query({member: $scope.currentUser.name}) : [];
              },
              function (error) {
                $scope.message = null;
                $scope.alertMessages = ["Error on the serverside :( ", error];
              }
          );

        };
      }])

    // OrganizationContext
    // - the list of organizations the user is a member of
    // - the currently selected organization
    .service("OrganizationContext", [function () {

        // Organizations that the current user is a member of
        this.list = [];
        this.currentOrganization = null;

        this.setUsersOrganizations = function (organizations) {
          this.list = organizations;
        };

        this.setCurrentOrganization = function (target) {
          if (angular.isString(target)) {
            this.currentOrganization = this.getOrganizationById(target);
          } else {
            if (this.containsOrganization(target)) {
              this.currentOrganization = target;
            }
          }
        };

        this.getOrganizationById = function (organizationId) {
          for (var i = 0; i < this.list.length; i++) {
            if (organizationId === this.list[i].organizationId) {
              return this.list[i];
            }
          }
        };

        this.containsOrganization = function (organization) {
          return this.list.indexOf(organization) > -1;
        };

      }])
    ;

<|endoftext|>


<commit_before>import { Alert, Linking } from 'react-native';
import { GoogleSignin } from 'react-native-google-signin';
import * as Analytics from 'app/utility/Analytics';

import {
    LOGIN_REQUEST,
    UPDATE_HISTORY_FILTER,
    ATTEMPT_EXPORTING_CSV,
    EXPORTING_CSV
} from 'app/ActionTypes';
import * as AuthActionCreators from 'app/redux/shared_actions/AuthActionCreators';
import * as GoogleDriveUploader from 'app/services/GoogleDriveUploader';
import * as CSVConverter from 'app/utility/transforms/CSVConverter';
import * as SetsSelectors from 'app/redux/selectors/SetsSelectors';
import * as SettingsSelectors from 'app/redux/selectors/SettingsSelectors';
import * as DurationCalculator from 'app/utility/transforms/DurationCalculator';

export const signIn = () => ({ type: LOGIN_REQUEST });

export const signOut = () => {
    return AuthActionCreators.logout();
};

export const showRemovedData = () => ({
    type: UPDATE_HISTORY_FILTER,
    showRemoved: true
});

export const hideRemovedData = () => ({
    type: UPDATE_HISTORY_FILTER,
    showRemoved: false
});

// TODO: refactor this into a saga
export const exportCSV = () => (dispatch, getState) => {
    // logged in check
    let state = getState();
    if (state.auth.email === null) {
        Alert.alert('Sign in Required', 'Please sign in via Settings to use this feature.');
        return;
    }

    GoogleSignin.currentUserAsync().then(async (user) => {
        if (user === null) {
            dispatch({ type: EXPORTING_CSV_ERROR });
            Alert.alert('Error Exporting CSV', 'Tip: Is your internet connection working?\n\nTip: Try Logging out then logging in again as this feature requires additional Google Drive permissions.');
        } else {
            //ATTEMPT
            logAttemptCSVAnalytics(state);
            dispatch(updateIsExportingCSV(true));
            try {
                let date = new Date();
                let name = 'OpenBarbell Data -- Exported on ' + date.toLocaleString() + '.csv';
                // TODO: use a more efficient method of generating the name, perhaps an actual date format
                name = name.split('/').join('-');
                name = name.split(',').join('');
                name = name.split(':').join('.');
                let state = getState();
                let sets = SetsSelectors.getHistorySetsChronological(state);
                let csv = CSVConverter.convert(sets);
                console.tron.log("google access token " + user.accessToken);
                await GoogleDriveUploader.upload(user.accessToken, name, csv, (fileID) => {
                    dispatch(updateIsExportingCSV(false));
                    Linking.openURL('https://drive.google.com/open?id=' + fileID).catch(err => {
                        Alert.alert('Upload Succeeded', 'CSV uploaded to your Google Drive!');
                    });
                    logExportCSVAnalytics(state);
                });
            } catch(err) {
                console.tron.log("Error uploading csv file " + typeof err + " " + err);
                if (err.message == 'Insufficient Permission') { // TODO: should do typeof check but it's not working
                    Alert.alert('Google Drive Permissions Error', 'Please log out and log in again. This feature requires additional Google Drive permissions.');
                } else {
                    Alert.alert('Error exporting CSV', 'Please try again later.\n\nTip: Is your internet connection working?');
                }
                dispatch(updateIsExportingCSV(false));
                let state = getState();
                logExportCSVErrorAnalytics(state);
            }
        }
    })
    .catch((err) => {
        // error here
        console.tron.log("EXPORT HISTORY ERROR " + err);
    })
    .done();
};

const updateIsExportingCSV = (isExportingCSV) => ({ type: EXPORTING_CSV, isExportingCSV: isExportingCSV });

const logAttemptCSVAnalytics = (state) => {
    let num_sets = SetsSelectors.getNumHistorySets(state);
    let num_reps = SetsSelectors.getNumHistoryReps(state);
    let num_workouts = SetsSelectors.getNumHistoryWorkouts(state);
    let time_since_last_export = getlastExportCSVDuration(state);
    let time_since_last_workout = SetsSelectors.getTimeSinceLastWorkout(state);

    Analytics.logEventWithAppState('attempt_export_csv', {
        value: time_since_last_export,
        num_sets: num_sets,
        num_reps: num_reps,
        num_workouts: num_workouts,
        time_since_last_workout: time_since_last_workout,
        time_since_last_export: time_since_last_export,
    }, state);
};

const logExportCSVAnalytics = (state) => {
    let num_sets = SetsSelectors.getNumHistorySets(state);
    let num_reps = SetsSelectors.getNumHistoryReps(state);
    let num_workouts = SetsSelectors.getNumHistoryWorkouts(state);
    let time_since_last_export = getlastExportCSVDuration(state);
    let time_since_last_workout = SetsSelectors.getTimeSinceLastWorkout(state);

    Analytics.logEventWithAppState('export_csv', {
        value: time_since_last_export,
        num_sets: num_sets,
        num_reps: num_reps,
        num_workouts: num_workouts,
        time_since_last_workout: time_since_last_workout,
        time_since_last_export: time_since_last_export,
    }, state);
};

const logExportCSVErrorAnalytics = (state) => {
    let num_sets = SetsSelectors.getNumHistorySets(state);
    let num_reps = SetsSelectors.getNumHistoryReps(state);
    let num_workouts = SetsSelectors.getNumHistoryWorkouts(state);
    let time_since_last_export = getlastExportCSVDuration(state);
    let time_since_last_workout = SetsSelectors.getTimeSinceLastWorkout(state);

    Analytics.logEventWithAppState('export_csv_error', {
        num_sets: num_sets,
        num_reps: num_reps,
        num_workouts: num_workouts,
        time_since_last_workout: time_since_last_workout,
        time_since_last_export: time_since_last_export,
    }, state);
};

const getlastExportCSVDuration = (state) => {
    let startDate = SettingsSelectors.getLastExportCSVDate(state);
    if (Boolean(startDate)) {
        return Date.parse(new Date()) - Date.parse(startDate);
    } else {
        return 0;
    }
};
<commit_msg>Renamed to getTimeSinceLastExport<commit_after>import { Alert, Linking } from 'react-native';
import { GoogleSignin } from 'react-native-google-signin';
import * as Analytics from 'app/utility/Analytics';

import {
    LOGIN_REQUEST,
    UPDATE_HISTORY_FILTER,
    ATTEMPT_EXPORTING_CSV,
    EXPORTING_CSV
} from 'app/ActionTypes';
import * as AuthActionCreators from 'app/redux/shared_actions/AuthActionCreators';
import * as GoogleDriveUploader from 'app/services/GoogleDriveUploader';
import * as CSVConverter from 'app/utility/transforms/CSVConverter';
import * as SetsSelectors from 'app/redux/selectors/SetsSelectors';
import * as SettingsSelectors from 'app/redux/selectors/SettingsSelectors';
import * as DurationCalculator from 'app/utility/transforms/DurationCalculator';

export const signIn = () => ({ type: LOGIN_REQUEST });

export const signOut = () => {
    return AuthActionCreators.logout();
};

export const showRemovedData = () => ({
    type: UPDATE_HISTORY_FILTER,
    showRemoved: true
});

export const hideRemovedData = () => ({
    type: UPDATE_HISTORY_FILTER,
    showRemoved: false
});

// TODO: refactor this into a saga
export const exportCSV = () => (dispatch, getState) => {
    // logged in check
    let state = getState();
    if (state.auth.email === null) {
        Alert.alert('Sign in Required', 'Please sign in via Settings to use this feature.');
        return;
    }

    GoogleSignin.currentUserAsync().then(async (user) => {
        if (user === null) {
            dispatch({ type: EXPORTING_CSV_ERROR });
            Alert.alert('Error Exporting CSV', 'Tip: Is your internet connection working?\n\nTip: Try Logging out then logging in again as this feature requires additional Google Drive permissions.');
        } else {
            //ATTEMPT
            logAttemptCSVAnalytics(state);
            dispatch(updateIsExportingCSV(true));
            try {
                let date = new Date();
                let name = 'OpenBarbell Data -- Exported on ' + date.toLocaleString() + '.csv';
                // TODO: use a more efficient method of generating the name, perhaps an actual date format
                name = name.split('/').join('-');
                name = name.split(',').join('');
                name = name.split(':').join('.');
                let state = getState();
                let sets = SetsSelectors.getHistorySetsChronological(state);
                let csv = CSVConverter.convert(sets);
                console.tron.log("google access token " + user.accessToken);
                await GoogleDriveUploader.upload(user.accessToken, name, csv, (fileID) => {
                    dispatch(updateIsExportingCSV(false));
                    Linking.openURL('https://drive.google.com/open?id=' + fileID).catch(err => {
                        Alert.alert('Upload Succeeded', 'CSV uploaded to your Google Drive!');
                    });
                    logExportCSVAnalytics(state);
                });
            } catch(err) {
                console.tron.log("Error uploading csv file " + typeof err + " " + err);
                if (err.message == 'Insufficient Permission') { // TODO: should do typeof check but it's not working
                    Alert.alert('Google Drive Permissions Error', 'Please log out and log in again. This feature requires additional Google Drive permissions.');
                } else {
                    Alert.alert('Error exporting CSV', 'Please try again later.\n\nTip: Is your internet connection working?');
                }
                dispatch(updateIsExportingCSV(false));
                let state = getState();
                logExportCSVErrorAnalytics(state);
            }
        }
    })
    .catch((err) => {
        // error here
        console.tron.log("EXPORT HISTORY ERROR " + err);
    })
    .done();
};

const updateIsExportingCSV = (isExportingCSV) => ({ type: EXPORTING_CSV, isExportingCSV: isExportingCSV });

const logAttemptCSVAnalytics = (state) => {
    let num_sets = SetsSelectors.getNumHistorySets(state);
    let num_reps = SetsSelectors.getNumHistoryReps(state);
    let num_workouts = SetsSelectors.getNumHistoryWorkouts(state);
    let time_since_last_export = getTimeSinceLastExport(state);
    let time_since_last_workout = SetsSelectors.getTimeSinceLastWorkout(state);

    Analytics.logEventWithAppState('attempt_export_csv', {
        value: time_since_last_export,
        num_sets: num_sets,
        num_reps: num_reps,
        num_workouts: num_workouts,
        time_since_last_workout: time_since_last_workout,
        time_since_last_export: time_since_last_export,
    }, state);
};

const logExportCSVAnalytics = (state) => {
    let num_sets = SetsSelectors.getNumHistorySets(state);
    let num_reps = SetsSelectors.getNumHistoryReps(state);
    let num_workouts = SetsSelectors.getNumHistoryWorkouts(state);
    let time_since_last_export = getTimeSinceLastExport(state);
    let time_since_last_workout = SetsSelectors.getTimeSinceLastWorkout(state);

    Analytics.logEventWithAppState('export_csv', {
        value: time_since_last_export,
        num_sets: num_sets,
        num_reps: num_reps,
        num_workouts: num_workouts,
        time_since_last_workout: time_since_last_workout,
        time_since_last_export: time_since_last_export,
    }, state);
};

const logExportCSVErrorAnalytics = (state) => {
    let num_sets = SetsSelectors.getNumHistorySets(state);
    let num_reps = SetsSelectors.getNumHistoryReps(state);
    let num_workouts = SetsSelectors.getNumHistoryWorkouts(state);
    let time_since_last_export = getTimeSinceLastExport(state);
    let time_since_last_workout = SetsSelectors.getTimeSinceLastWorkout(state);

    Analytics.logEventWithAppState('export_csv_error', {
        num_sets: num_sets,
        num_reps: num_reps,
        num_workouts: num_workouts,
        time_since_last_workout: time_since_last_workout,
        time_since_last_export: time_since_last_export,
    }, state);
};

const getTimeSinceLastExport = (state) => {
    let startDate = SettingsSelectors.getLastExportCSVDate(state);
    if (Boolean(startDate)) {
        return Date.parse(new Date()) - Date.parse(startDate);
    } else {
        return 0;
    }
};
<|endoftext|>


<commit_before>import Ember from 'ember';

var get      = Ember.get;
var computed = Ember.computed;
var observer = Ember.observer;

export default Ember.ContainerView.extend(Ember._Metamorph, {
  type: null,

  childViews: computed(function() {
    return [this.componentForType()];
  }),

  changeChild: observer('type', function() {
    this.clear();
    this.pushObject(this.componentForType());
  }),

  componentForType: function() {
    var type = get(this, 'type');

    var container       = get(this, 'container');
    var componentLookup = container.lookup('component-lookup:main');
    var customComponent = componentLookup.lookupFactory(type, container);

    var options = this.get("_dynamicOptions");
    var hash    = options.hash;

    var ignore = ["templateData", "_dynamicOptions", "_context", "_parentView", "helperName", "container"];
    var props = {};

    var prop, bindingTarget;
    for (prop in hash) {
      if (ignore.indexOf(prop) !== -1) { continue; }
      if (prop.match(/Binding$/)) {
        bindingTarget = prop.replace("Binding", '');
        props[prop]   = "_parentView."+bindingTarget;
      } else {
        props[prop] = hash[prop];
      }
    }

    console.log(props);

    return customComponent.create(props);
  }
});<commit_msg>remove debug console.log<commit_after>import Ember from 'ember';

var get      = Ember.get;
var computed = Ember.computed;
var observer = Ember.observer;

export default Ember.ContainerView.extend(Ember._Metamorph, {
  type: null,

  childViews: computed(function() {
    return [this.componentForType()];
  }),

  changeChild: observer('type', function() {
    this.clear();
    this.pushObject(this.componentForType());
  }),

  componentForType: function() {
    var type = get(this, 'type');

    var container       = get(this, 'container');
    var componentLookup = container.lookup('component-lookup:main');
    var customComponent = componentLookup.lookupFactory(type, container);

    var options = this.get("_dynamicOptions");
    var hash    = options.hash;
    var ignore  = ["templateData", "_dynamicOptions", "_context", "_parentView", "helperName", "container"];
    var props   = {};

    var prop, bindingTarget;
    for (prop in hash) {
      if (ignore.indexOf(prop) !== -1) { continue; }
      if (prop.match(/Binding$/)) {
        bindingTarget = prop.replace("Binding", '');
        props[prop]   = "_parentView."+bindingTarget;
      } else {
        props[prop] = hash[prop];
      }
    }

    return customComponent.create(props);
  }
});<|endoftext|>


<commit_before>var io = require('./io');
var modm = require('modm');

// TODO let the user define this configs
var config = {
    dbName: 'dms', // TODO handle with datasources
    templateId: modm.ObjectId('000000000000000000000000'), // TODO handle with datasources
    roleTemplateId: modm.ObjectId('000000000000000000000002'),
    templateColName: 'd_templates', // TODO handle with datasources
    templateSchema: {
        _id: {type: 'objectid'},
        _tp: {type: 'objectid', required: true},
        db: {type: 'string', required: true},
        collection: {type: 'string', required: true},
        name: {type: 'string', required: true},
        schema: {type: 'object', required: true}
    }
};

var templateSchema = new modm.Schema(config.templateSchema);

// template cache
var templateCache = {
    // template's template must be in the cache, otherwise
    // it's impossible to create the first template item
    '000000000000000000000000': {
        _id: modm.ObjectId('000000000000000000000000'),
        label: 'Templates',
        db: config.dbName,
        collection: config.templateColName,
        schema: templateSchema,
        model: modm(config.dbName, {
            server: {pooSize: 3},
            db: {w: 1}
        })
    }
};
// init collection
templateCache[config.templateId].collection = templateCache[config.templateId].model(config.templateColName, templateSchema);

function ObjectId (id) {
    try {
        return modm.ObjectId(id);
    } catch (err) {
        return null;
    }
}

// check access
function checkAccess (template, role, access) {

    // grant access for templates without roles
    if (!template.roles) {
        return true;
    }

    if (template.roles[role] < access) {
        return false;
    }

    return true;
}

function initAndCache (template) {

    if (typeof template.db !== 'string') {
        return;
    };

    template.model = modm(template.db, {
        server: {pooSize: 3},
        db: {w: 1}
    });

    // add mandatory field _tp
    template.schema._tp = {
        type: 'objectid',
        required: true
    };

    // add mandatory field _id
    template.schema._id = {
        type: 'objectid',
        required: true
    };

    template.schema = new modm.Schema(template.schema);
    template.collection = template.model(template.collection, template.schema);
    return templateCache[template._id] = template;
}

function getCachedTemplates (templates, role) {

    if (!templates || templates.length === 0) {
        return;
    }

    var resultTemplates = {};
    var queryTemplates = [];
    var addedTemplates = {};

    if (templates && templates.length > 0) {
        // check cached templates
        for (var i = 0, l = templates.length; i < l; ++i) {
            // add to result if role has access
            if (templateCache[templates[i]] && checkAccess(templateCache[templates[i]], role, 1)) {
                resultTemplates[templates[i]] = templateCache[templates[i]];
            } else if (!addedTemplates[templates[i]]) {
                addedTemplates[templates[i]] = true;
                queryTemplates.push(templates[i]);
            }
        }
    }

    return {
        query: queryTemplates,
        cached: resultTemplates
    }
}

function fetchTemplatesFromDb (templates, role, fields, callback) {

    var tpls = getCachedTemplates(templates, role);
    var resultTemplates = {};

    // build query
    var dbReq = {
        query: {_tp: config.templateId},
        options: {fields: fields || {}},
        template: templateCache[config.templateId]
    };

    if (tpls) {
        var templates = tpls.query;
        resultTemplates = tpls.cached;

        // check if role has access
        dbReq.query['roles.' + role] = {$gt: 0};

        if (templates.length > 1) {

            dbReq.query._id = {$in: []};
            dbReq.options.limit = templates.length;

            for (var i = 0, l = templates.length; i < l; ++i) {
                templates[i] = ObjectId(templates[i]);
                if (!templates[i]) {
                    var err = new Error('Invalid templates.');
                    err.statusCode = 400;
                    return callback(err);
                }

                dbReq.query._id.$in.push(templates[i]);
            }
        } else if (templates.length > 0) {

            if (templates[0] = ObjectId(templates[0])) {
                dbReq.options.limit = 1;
                dbReq.query._id = templates[0];
            } else {
                var err = new Error('Invalid templates.');
                err.statusCode = 400;
                return callback(err);
            }
        }
    }

    if (!tpls || tpls.query.length > 0) {
        io.find(null, dbReq, function (err, cursor) {

            if (err) {
                err.statusCode = 500;
                return callback(err);
            }

            if (!cursor) {
                var err = new Error('Templates not found.');
                err.statusCode = 404;
                return callback(err);
            }

            cursor.toArray(function (err, templates) {

                if (err) {
                    err.statusCode = 500;
                    return callback(err);
                }

                if (!templates || templates.length === 0) {
                    var err = new Error('Templates not found.');
                    err.statusCode = 404;
                    return callback(err);
                }

                for (var i = 0, l = templates.length; i < l; ++i) {
                    var temp = initAndCache(templates[i]);
                    if (temp) {
                        resultTemplates[templates[i]._id] = temp;
                    }
                }

                callback(null, resultTemplates);
            });
        });
    } else {
        callback(null, tpls.cached);
    }
}

function getTemplate (request, callback) {

    fetchTemplatesFromDb([request.templateId], request.role, {}, function (err, template) {

        if (err) {
            err.statusCode = err.statusCode || 500;
            return callback(err);
        }

        request.template = template[request.templateId];

        if (!request.template) {
            err = new Error('Bad template object.');
            err.statusCode = 500;
            return callback(err);
        }

        callback(null, request);
    });
}

function getMergeTemplates (templates, role, callback) {

    fetchTemplatesFromDb(templates, role, {}, function (err, templates) {

        if (err) {
            return callback(err);
        }

        callback(null, templates);
    });
}

// TODO add more core templates here when necessary
var CORE_TMPL_RE = new RegExp('00000000000000000000000(0|1|2)');

function getTemplates (templates, role, callback) {

    var myRoleString = role ? role.toString() : '';

    fetchTemplatesFromDb(templates, role, {}, function (err, templates) {

        if (err) {
            return callback(err);
        }

        var result = {};
        for (var id in templates) {
            // if this is a core template
            if (CORE_TMPL_RE.test(id) && templates[id].roles) {
                // do not return templates for users that cannot modify them
                // (only super-admins will have at least access 2)
                if (templates[id].roles[myRoleString] < 2) {
                    continue;
                }
            }

            result[id] = {
                id: templates[id]._id,
                //name: templates[id].name,
                schema: templates[id].schema.paths
            };

            // let the UI template information go through
            var uiElems = ['label', 'html', 'filters', 'sort', 'links'];
            for (var i in uiElems) {
                if (templates[id][uiElems[i]]) {
                    result[id][uiElems[i]] = templates[id][uiElems[i]];
                }
            }
        }

        callback(null, result);
    });
}

M.on('crud_getTemplate', getTemplate);

exports.getTemplate = getTemplate;
exports.getTemplates = getTemplates;
exports.getMergeTemplates = getMergeTemplates;
<commit_msg>extended the template of templates with links, roles and label<commit_after>var io = require('./io');
var modm = require('modm');

// TODO let the user define this configs
var config = {
    dbName: 'dms', // TODO handle with datasources
    templateId: modm.ObjectId('000000000000000000000000'), // TODO handle with datasources
    roleTemplateId: modm.ObjectId('000000000000000000000002'),
    templateColName: 'd_templates', // TODO handle with datasources
    templateSchema: {
        _id: {type: 'objectid'},
        _tp: {type: 'objectid', required: true},
        db: {type: 'string', required: true},
        collection: {type: 'string', required: true},
        name: {type: 'string', required: true},
        roles: {type: 'object', required: true},
        schema: {type: 'object', required: true},
        label: {type: 'string'},
        links: {type: 'array'}
    }
};

var templateSchema = new modm.Schema(config.templateSchema);

// template cache
var templateCache = {
    // template's template must be in the cache, otherwise
    // it's impossible to create the first template item
    '000000000000000000000000': {
        _id: modm.ObjectId('000000000000000000000000'),
        label: 'Templates',
        db: config.dbName,
        collection: config.templateColName,
        schema: templateSchema,
        model: modm(config.dbName, {
            server: {pooSize: 3},
            db: {w: 1}
        })
    }
};
// init collection
templateCache[config.templateId].collection = templateCache[config.templateId].model(config.templateColName, templateSchema);

function ObjectId (id) {
    try {
        return modm.ObjectId(id);
    } catch (err) {
        return null;
    }
}

// check access
function checkAccess (template, role, access) {

    // grant access for templates without roles
    if (!template.roles) {
        return true;
    }

    if (template.roles[role] < access) {
        return false;
    }

    return true;
}

function initAndCache (template) {

    if (typeof template.db !== 'string') {
        return;
    };

    template.model = modm(template.db, {
        server: {pooSize: 3},
        db: {w: 1}
    });

    // add mandatory field _tp
    template.schema._tp = {
        type: 'objectid',
        required: true
    };

    // add mandatory field _id
    template.schema._id = {
        type: 'objectid',
        required: true
    };

    template.schema = new modm.Schema(template.schema);
    template.collection = template.model(template.collection, template.schema);
    return templateCache[template._id] = template;
}

function getCachedTemplates (templates, role) {

    if (!templates || templates.length === 0) {
        return;
    }

    var resultTemplates = {};
    var queryTemplates = [];
    var addedTemplates = {};

    if (templates && templates.length > 0) {
        // check cached templates
        for (var i = 0, l = templates.length; i < l; ++i) {
            // add to result if role has access
            if (templateCache[templates[i]] && checkAccess(templateCache[templates[i]], role, 1)) {
                resultTemplates[templates[i]] = templateCache[templates[i]];
            } else if (!addedTemplates[templates[i]]) {
                addedTemplates[templates[i]] = true;
                queryTemplates.push(templates[i]);
            }
        }
    }

    return {
        query: queryTemplates,
        cached: resultTemplates
    }
}

function fetchTemplatesFromDb (templates, role, fields, callback) {

    var tpls = getCachedTemplates(templates, role);
    var resultTemplates = {};

    // build query
    var dbReq = {
        query: {_tp: config.templateId},
        options: {fields: fields || {}},
        template: templateCache[config.templateId]
    };

    if (tpls) {
        var templates = tpls.query;
        resultTemplates = tpls.cached;

        // check if role has access
        dbReq.query['roles.' + role] = {$gt: 0};

        if (templates.length > 1) {

            dbReq.query._id = {$in: []};
            dbReq.options.limit = templates.length;

            for (var i = 0, l = templates.length; i < l; ++i) {
                templates[i] = ObjectId(templates[i]);
                if (!templates[i]) {
                    var err = new Error('Invalid templates.');
                    err.statusCode = 400;
                    return callback(err);
                }

                dbReq.query._id.$in.push(templates[i]);
            }
        } else if (templates.length > 0) {

            if (templates[0] = ObjectId(templates[0])) {
                dbReq.options.limit = 1;
                dbReq.query._id = templates[0];
            } else {
                var err = new Error('Invalid templates.');
                err.statusCode = 400;
                return callback(err);
            }
        }
    }

    if (!tpls || tpls.query.length > 0) {
        io.find(null, dbReq, function (err, cursor) {

            if (err) {
                err.statusCode = 500;
                return callback(err);
            }

            if (!cursor) {
                var err = new Error('Templates not found.');
                err.statusCode = 404;
                return callback(err);
            }

            cursor.toArray(function (err, templates) {

                if (err) {
                    err.statusCode = 500;
                    return callback(err);
                }

                if (!templates || templates.length === 0) {
                    var err = new Error('Templates not found.');
                    err.statusCode = 404;
                    return callback(err);
                }

                for (var i = 0, l = templates.length; i < l; ++i) {
                    var temp = initAndCache(templates[i]);
                    if (temp) {
                        resultTemplates[templates[i]._id] = temp;
                    }
                }

                callback(null, resultTemplates);
            });
        });
    } else {
        callback(null, tpls.cached);
    }
}

function getTemplate (request, callback) {

    fetchTemplatesFromDb([request.templateId], request.role, {}, function (err, template) {

        if (err) {
            err.statusCode = err.statusCode || 500;
            return callback(err);
        }

        request.template = template[request.templateId];

        if (!request.template) {
            err = new Error('Bad template object.');
            err.statusCode = 500;
            return callback(err);
        }

        callback(null, request);
    });
}

function getMergeTemplates (templates, role, callback) {

    fetchTemplatesFromDb(templates, role, {}, function (err, templates) {

        if (err) {
            return callback(err);
        }

        callback(null, templates);
    });
}

// TODO add more core templates here when necessary
var CORE_TMPL_RE = new RegExp('00000000000000000000000(0|1|2)');

function getTemplates (templates, role, callback) {

    var myRoleString = role ? role.toString() : '';

    fetchTemplatesFromDb(templates, role, {}, function (err, templates) {

        if (err) {
            return callback(err);
        }

        var result = {};
        for (var id in templates) {
            // if this is a core template
            if (CORE_TMPL_RE.test(id) && templates[id].roles) {
                // do not return templates for users that cannot modify them
                // (only super-admins will have at least access 2)
                if (templates[id].roles[myRoleString] < 2) {
                    continue;
                }
            }

            result[id] = {
                id: templates[id]._id,
                //name: templates[id].name,
                schema: templates[id].schema.paths
            };

            // let the UI template information go through
            var uiElems = ['label', 'html', 'filters', 'sort', 'links'];
            for (var i in uiElems) {
                if (templates[id][uiElems[i]]) {
                    result[id][uiElems[i]] = templates[id][uiElems[i]];
                }
            }
        }

        callback(null, result);
    });
}

M.on('crud_getTemplate', getTemplate);

exports.getTemplate = getTemplate;
exports.getTemplates = getTemplates;
exports.getMergeTemplates = getMergeTemplates;
<|endoftext|>


<commit_before>var topic_list = (function () {

var exports = {};

function iterate_to_find(selector, name_to_find, context) {
    // This code is duplicated with stream_list.js, but we should
    // not try to de-dup this; instead, we should try to make it sane
    // for topics and avoid O(N) iteration.
    //
    // We could start by using canonical lowercase values for the
    // data-name attributes (and eventually use topic ids when the
    // back end allows).  Either that, or we should have a data
    // structure that links topic names to list items, so that we
    // don't have to search the DOM at all.
    var lowercase_name = name_to_find.toLowerCase();
    var found = _.find($(selector, context), function (elem) {
        return $(elem).attr('data-name').toLowerCase() === lowercase_name;
    });
    return found ? $(found) : $();
}

exports.remove_expanded_topics = function () {
    popovers.hide_topic_sidebar_popover();
    $("ul.expanded_subjects").remove();
};

function get_topic_filter_li(stream_li, topic) {
    return iterate_to_find(".expanded_subjects li.expanded_subject", topic, stream_li);
}

exports.activate_topic = function (stream_li, active_topic) {
    get_topic_filter_li(stream_li, active_topic).addClass('active-sub-filter');
};

exports.update_count_in_dom = function (count_span, value_span, count) {
    if (count === 0) {
        count_span.hide();
        value_span.text('');
    } else {
        count_span.removeClass("zero_count");
        count_span.show();
        value_span.text(count);
    }
};

exports.set_count = function (stream_li, topic, count) {
    var topic_li = get_topic_filter_li(stream_li, topic);
    var count_span = topic_li.find('.subject_count');
    var value_span = count_span.find('.value');

    if (count_span.length === 0 || value_span.length === 0) {
        return;
    }

    exports.update_count_in_dom(count_span, value_span, count);
};

exports.build_list = function (stream, active_topic, max_topics) {
    var subjects = stream_data.get_recent_topics(stream) || [];

    if (active_topic) {
        active_topic = active_topic.toLowerCase();
    }

    var display_subjects = [];
    var hiding_topics = false;

    _.each(subjects, function (subject_obj, idx) {
        var topic_name = subject_obj.subject;
        var num_unread = unread.num_unread_for_subject(stream, subject_obj.canon_subject);

        // Show the most recent subjects, as well as any with unread messages
        var always_visible = (idx < max_topics) || (num_unread > 0) || (active_topic === topic_name);

        if (!always_visible) {
            hiding_topics = true;
        }

        var display_subject = {
            topic_name: topic_name,
            unread: num_unread,
            is_zero: num_unread === 0,
            is_muted: muting.is_topic_muted(stream, topic_name),
            zoom_out_hide: !always_visible,
            url: narrow.by_stream_subject_uri(stream, topic_name)
        };
        display_subjects.push(display_subject);
    });

    var topic_dom = templates.render('sidebar_subject_list',
                                      {subjects: display_subjects,
                                       want_show_more_topics_links: hiding_topics,
                                       stream: stream});

    return topic_dom;
};

exports.rebuild = function (stream_li, stream, active_topic) {
    var max_topics = 5;

    exports.remove_expanded_topics();

    var topic_dom = exports.build_list(stream, active_topic, max_topics);
    stream_li.append(topic_dom);

    if (active_topic) {
        exports.activate_topic(stream_li, active_topic);
    }
};

exports.set_click_handlers = function (callbacks) {
    $('#stream_filters').on('click', '.show-more-topics', function (e) {
        callbacks.zoom_in();

        e.preventDefault();
        e.stopPropagation();
    });

    $('.show-all-streams').on('click', function (e) {
        callbacks.zoom_out();

        e.preventDefault();
        e.stopPropagation();
    });

    $('#stream_filters').on('click', '.subject_box', function (e) {
        if (e.metaKey || e.ctrlKey) {
            return;
        }

        // In a more componentized world, we would delegate some
        // of this stuff back up to our parents.
        if (ui.home_tab_obscured()) {
            ui.change_tab_to('#home');
        }

        var stream = $(e.target).parents('ul').attr('data-stream');
        var topic = $(e.target).parents('li').attr('data-name');

        narrow.activate([{operator: 'stream',  operand: stream},
                         {operator: 'topic', operand: topic}],
                        {select_first_unread: true, trigger: 'sidebar'});

        e.preventDefault();
    });
};

return exports;
}());
if (typeof module !== 'undefined') {
    module.exports = topic_list;
}
<commit_msg>Rename variables in topic_list.build_list().<commit_after>var topic_list = (function () {

var exports = {};

function iterate_to_find(selector, name_to_find, context) {
    // This code is duplicated with stream_list.js, but we should
    // not try to de-dup this; instead, we should try to make it sane
    // for topics and avoid O(N) iteration.
    //
    // We could start by using canonical lowercase values for the
    // data-name attributes (and eventually use topic ids when the
    // back end allows).  Either that, or we should have a data
    // structure that links topic names to list items, so that we
    // don't have to search the DOM at all.
    var lowercase_name = name_to_find.toLowerCase();
    var found = _.find($(selector, context), function (elem) {
        return $(elem).attr('data-name').toLowerCase() === lowercase_name;
    });
    return found ? $(found) : $();
}

exports.remove_expanded_topics = function () {
    popovers.hide_topic_sidebar_popover();
    $("ul.expanded_subjects").remove();
};

function get_topic_filter_li(stream_li, topic) {
    return iterate_to_find(".expanded_subjects li.expanded_subject", topic, stream_li);
}

exports.activate_topic = function (stream_li, active_topic) {
    get_topic_filter_li(stream_li, active_topic).addClass('active-sub-filter');
};

exports.update_count_in_dom = function (count_span, value_span, count) {
    if (count === 0) {
        count_span.hide();
        value_span.text('');
    } else {
        count_span.removeClass("zero_count");
        count_span.show();
        value_span.text(count);
    }
};

exports.set_count = function (stream_li, topic, count) {
    var topic_li = get_topic_filter_li(stream_li, topic);
    var count_span = topic_li.find('.subject_count');
    var value_span = count_span.find('.value');

    if (count_span.length === 0 || value_span.length === 0) {
        return;
    }

    exports.update_count_in_dom(count_span, value_span, count);
};

exports.build_list = function (stream, active_topic, max_topics) {
    var topics = stream_data.get_recent_topics(stream) || [];

    if (active_topic) {
        active_topic = active_topic.toLowerCase();
    }

    var display_topics = [];
    var hiding_topics = false;

    _.each(topics, function (subject_obj, idx) {
        var topic_name = subject_obj.subject;
        var num_unread = unread.num_unread_for_subject(stream, subject_obj.canon_subject);

        // Show the most recent topics, as well as any with unread messages
        var always_visible = (idx < max_topics) || (num_unread > 0) || (active_topic === topic_name);

        if (!always_visible) {
            hiding_topics = true;
        }

        var display_subject = {
            topic_name: topic_name,
            unread: num_unread,
            is_zero: num_unread === 0,
            is_muted: muting.is_topic_muted(stream, topic_name),
            zoom_out_hide: !always_visible,
            url: narrow.by_stream_subject_uri(stream, topic_name)
        };
        display_topics.push(display_subject);
    });

    var topic_dom = templates.render('sidebar_subject_list',
                                      {subjects: display_topics,
                                       want_show_more_topics_links: hiding_topics,
                                       stream: stream});

    return topic_dom;
};

exports.rebuild = function (stream_li, stream, active_topic) {
    var max_topics = 5;

    exports.remove_expanded_topics();

    var topic_dom = exports.build_list(stream, active_topic, max_topics);
    stream_li.append(topic_dom);

    if (active_topic) {
        exports.activate_topic(stream_li, active_topic);
    }
};

exports.set_click_handlers = function (callbacks) {
    $('#stream_filters').on('click', '.show-more-topics', function (e) {
        callbacks.zoom_in();

        e.preventDefault();
        e.stopPropagation();
    });

    $('.show-all-streams').on('click', function (e) {
        callbacks.zoom_out();

        e.preventDefault();
        e.stopPropagation();
    });

    $('#stream_filters').on('click', '.subject_box', function (e) {
        if (e.metaKey || e.ctrlKey) {
            return;
        }

        // In a more componentized world, we would delegate some
        // of this stuff back up to our parents.
        if (ui.home_tab_obscured()) {
            ui.change_tab_to('#home');
        }

        var stream = $(e.target).parents('ul').attr('data-stream');
        var topic = $(e.target).parents('li').attr('data-name');

        narrow.activate([{operator: 'stream',  operand: stream},
                         {operator: 'topic', operand: topic}],
                        {select_first_unread: true, trigger: 'sidebar'});

        e.preventDefault();
    });
};

return exports;
}());
if (typeof module !== 'undefined') {
    module.exports = topic_list;
}
<|endoftext|>


<commit_before>import {
    DELETE_WORKOUT_VIDEO,
    DISMISS_WORKOUT_VIDEO_PLAYER
} from 'app/ActionTypes';
import * as Analytics from 'app/utility/Analytics';

export const deleteVideo = (setID) => (dispatch, getState) => {
    var state = getState();

    deleteVideoAnalytics(state);

    return {
        type: DELETE_WORKOUT_VIDEO,
        setID: setID
    }
};

export const closeModal = () => (dispatch, getState) => {
    var state = getState();

    cancelWatchVideoAnalytics(state);

    Analytics.setCurrentScreen('workout');

    return {
        type: DISMISS_WORKOUT_VIDEO_PLAYER
    }
};

const deleteVideoAnalytics = (state) => {
    let startDate = DurationsSelectors.getWorkoutVideoPlayerStart(state);
    let duration = DurationCalculator.getDurationTime(startDate, new Date());

    Analytics.logEventWithAppState('delete_video', {
        duration: duration
    }, state);
}

const cancelWatchVideoAnalytics = (state) => {
    let startDate = DurationsSelectors.getWorkoutVideoPlayerStart(state);
    let duration = DurationCalculator.getDurationTime(startDate, new Date());

    Analytics.logEventWithAppState('cancel_watch_video', {
        duration: duration
    }, state);
};<commit_msg>fixed dispathces in workoutvideoplayeractions<commit_after>import {
    DELETE_WORKOUT_VIDEO,
    DISMISS_WORKOUT_VIDEO_PLAYER
} from 'app/ActionTypes';
import * as Analytics from 'app/utility/Analytics';

export const deleteVideo = (setID) => (dispatch, getState) => {
    var state = getState();

    deleteVideoAnalytics(state);

    dispatch({
        type: DELETE_WORKOUT_VIDEO,
        setID: setID
    });
};

export const closeModal = () => (dispatch, getState) => {
    var state = getState();

    cancelWatchVideoAnalytics(state);

    Analytics.setCurrentScreen('workout');

    dispatch({
        type: DISMISS_WORKOUT_VIDEO_PLAYER
    });
};

const deleteVideoAnalytics = (state) => {
    let startDate = DurationsSelectors.getWorkoutVideoPlayerStart(state);
    let duration = DurationCalculator.getDurationTime(startDate, new Date());

    Analytics.logEventWithAppState('delete_video', {
        duration: duration
    }, state);
}

const cancelWatchVideoAnalytics = (state) => {
    let startDate = DurationsSelectors.getWorkoutVideoPlayerStart(state);
    let duration = DurationCalculator.getDurationTime(startDate, new Date());

    Analytics.logEventWithAppState('cancel_watch_video', {
        duration: duration
    }, state);
};<|endoftext|>


<commit_before>import { Alert, Button, Form, Input, Select } from 'antd';
import autobind from 'autobind-decorator';
import { is, Map } from 'immutable';
import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';

import FormItem from 'control/components/forms/FormItem';
import FormActions from 'control/components/forms/FormActions';
import ConsoleLogFields from 'control/components/recipes/ConsoleLogFields';
import PreferenceExperimentFields from 'control/components/recipes/PreferenceExperimentFields';
import ShowHeartbeatFields from 'control/components/recipes/ShowHeartbeatFields';
import OptOutStudyFields from 'control/components/recipes/OptOutStudyFields';
import { getAction, getAllActions } from 'control/state/app/actions/selectors';
import { areAnyRequestsInProgress } from 'control/state/app/requests/selectors';
import { getGithubUrl } from 'control/state/app/serviceInfo/selectors';
import { createForm } from 'control/utils/forms';
import QueryServiceInfo from 'control/components/data/QueryServiceInfo';

/**
 * Form for editing recipes.
 */
@createForm({})
@connect(
  (state, props) => {
    const actionId = props.form.getFieldValue('action_id');
    const selectedAction = getAction(state, actionId, new Map());
    return {
      selectedActionName: selectedAction.get('name'),
      isLoading: areAnyRequestsInProgress(state),
    };
  },
)
@autobind
export default class RecipeForm extends React.PureComponent {
  static propTypes = {
    form: PropTypes.object.isRequired,
    isLoading: PropTypes.bool,
    onSubmit: PropTypes.func.isRequired,
    recipe: PropTypes.instanceOf(Map),
    selectedActionName: PropTypes.string.isRequired,
  };

  static defaultProps = {
    isLoading: false,
    recipe: new Map(),
  };

  static argumentsFields = {
    'console-log': ConsoleLogFields,
    'show-heartbeat': ShowHeartbeatFields,
    'preference-experiment': PreferenceExperimentFields,
    'opt-out-study': OptOutStudyFields,
  };

  componentWillReceiveProps(newProps) {
    // Initial values are mostly handled via props, but if the recipe
    // changes, we need to reset the values stored in the state.
    if (!is(newProps.recipe, this.props.recipe)) {
      this.props.form.resetFields();
    }
  }

  render() {
    const {
      isLoading,
      onSubmit,
      recipe,
      selectedActionName,
    } = this.props;

    const ArgumentsFields = RecipeForm.argumentsFields[selectedActionName];

    return (
      <Form onSubmit={onSubmit} className="recipe-form">
        <FormItem
          name="name"
          label="Name"
          initialValue={recipe.get('name')}
        >
          <Input disabled={isLoading} />
        </FormItem>
        <FormItem
          name="extra_filter_expression"
          label="Filter Expression"
          initialValue={recipe.get('extra_filter_expression')}
        >
          <Input disabled={isLoading} type="textarea" rows="4" />
        </FormItem>
        <FormItem
          name="action_id"
          label="Action"
          initialValue={recipe.getIn(['action', 'id'])}
        >
          <ActionSelect disabled={isLoading} />
        </FormItem>
        {ArgumentsFields && (
          <fieldset>
            <legend>Action Arguments</legend>
            <ArgumentsFields
              recipeArguments={recipe.get('arguments')}
              disabled={isLoading}
            />
          </fieldset>
        )}
        {selectedActionName && !ArgumentsFields &&
          <ArgumentEditorMissingError name={selectedActionName} />}
        <FormActions>
          <FormActions.Primary>
            <Button
              type="primary"
              htmlType="submit"
              disabled={isLoading}
              id="rf-save-button"
            >
              Save
            </Button>
          </FormActions.Primary>
        </FormActions>
      </Form>
    );
  }
}

@connect(
  state => ({
    actions: getAllActions(state, new Map()),
  }),
)
class ActionSelect extends React.PureComponent {
  static propTypes = {
    actions: PropTypes.instanceOf(Map).isRequired,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  };

  static defaultProps = {
    value: null,
  };

  render() {
    const { actions, value, ...props } = this.props;

    // Select values have to be strings or else we get propType errors.
    const stringValue = value ? value.toString(10) : undefined;

    return (

        <Select placeholder="Select an action..." value={stringValue} {...props}>
          {actions.toList().map(action => (
            <Select.Option
              key={action.get('id')}
              value={action.get('id').toString(10)}
              className={`rf-${action.get('name')}`}
            >
              {action.get('name')}
            </Select.Option>
          ))}
        </Select>

    );
  }
}

@connect(
  state => ({
    githubUrl: getGithubUrl(state),
  }),
)
class ArgumentEditorMissingError extends React.PureComponent {
  static propTypes = {
    githubUrl: PropTypes.string,
    name: PropTypes.string.isRequired,
  }

  static defaultProps = {
    githubUrl: null,
  }

  render() {
    const { githubUrl, name } = this.props;
    let fileIssueUrl;
    if (githubUrl) {
      const url = new URL(githubUrl);
      url.pathname += '/issues/new';
      url.searchParams.set('title', `Argument fields missing for action "${name}"`);
      fileIssueUrl = url.toString();
    }

    return (

        <QueryServiceInfo />
        <Alert
          message="Error - Argument editor not available"
          description={

              This is a bug. Please file an issue on GitHub for it.

          }
          type="error"
          showIcon
        />

    );
  }
}
<commit_msg>Fix #1019: double clicking on new recipe button.<commit_after>import { Alert, Button, Form, Input, Select } from 'antd';
import autobind from 'autobind-decorator';
import { is, Map } from 'immutable';
import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';

import FormItem from 'control/components/forms/FormItem';
import FormActions from 'control/components/forms/FormActions';
import ConsoleLogFields from 'control/components/recipes/ConsoleLogFields';
import PreferenceExperimentFields from 'control/components/recipes/PreferenceExperimentFields';
import ShowHeartbeatFields from 'control/components/recipes/ShowHeartbeatFields';
import OptOutStudyFields from 'control/components/recipes/OptOutStudyFields';
import { getAction, getAllActions } from 'control/state/app/actions/selectors';
import { areAnyRequestsInProgress } from 'control/state/app/requests/selectors';
import { getGithubUrl } from 'control/state/app/serviceInfo/selectors';
import { createForm } from 'control/utils/forms';
import QueryServiceInfo from 'control/components/data/QueryServiceInfo';

/**
 * Form for editing recipes.
 */
@createForm({})
@connect(
  (state, props) => {
    const actionId = props.form.getFieldValue('action_id');
    const selectedAction = getAction(state, actionId, new Map());
    return {
      selectedActionName: selectedAction.get('name'),
      isLoading: areAnyRequestsInProgress(state),
    };
  },
)
@autobind
export default class RecipeForm extends React.PureComponent {
  static propTypes = {
    form: PropTypes.object.isRequired,
    isLoading: PropTypes.bool,
    onSubmit: PropTypes.func.isRequired,
    recipe: PropTypes.instanceOf(Map),
    selectedActionName: PropTypes.string.isRequired,
  };

  static defaultProps = {
    isLoading: false,
    recipe: new Map(),
  };

  static argumentsFields = {
    'console-log': ConsoleLogFields,
    'show-heartbeat': ShowHeartbeatFields,
    'preference-experiment': PreferenceExperimentFields,
    'opt-out-study': OptOutStudyFields,
  };

  componentWillReceiveProps(newProps) {
    // Initial values are mostly handled via props, but if the recipe
    // changes, we need to reset the values stored in the state.
    if (!is(newProps.recipe, this.props.recipe)) {
      this.props.form.resetFields();
    }
  }

  render() {
    const {
      isLoading,
      onSubmit,
      recipe,
      selectedActionName,
    } = this.props;

    const ArgumentsFields = RecipeForm.argumentsFields[selectedActionName];

    return (
      <Form onSubmit={onSubmit} className="recipe-form">
        <FormItem
          name="name"
          label="Name"
          initialValue={recipe.get('name')}
        >
          <Input disabled={isLoading} />
        </FormItem>
        <FormItem
          name="extra_filter_expression"
          label="Filter Expression"
          initialValue={recipe.get('extra_filter_expression')}
        >
          <Input disabled={isLoading} type="textarea" rows="4" />
        </FormItem>
        <FormItem
          name="action_id"
          label="Action"
          initialValue={recipe.getIn(['action', 'id'])}
        >
          <ActionSelect disabled={isLoading} />
        </FormItem>
        {ArgumentsFields && (
          <fieldset>
            <legend>Action Arguments</legend>
            <ArgumentsFields
              recipeArguments={recipe.get('arguments')}
              disabled={isLoading}
            />
          </fieldset>
        )}
        {selectedActionName && !ArgumentsFields &&
          <ArgumentEditorMissingError name={selectedActionName} />}
        <FormActions>
          <FormActions.Primary>
            <Button
              type="primary"
              htmlType="submit"
              disabled={isLoading}
              id="rf-save-button"
            >
              Save
            </Button>
          </FormActions.Primary>
        </FormActions>
      </Form>
    );
  }
}

@connect(
  state => ({
    actions: getAllActions(state, new Map()),
  }),
)
class ActionSelect extends React.PureComponent {
  static propTypes = {
    actions: PropTypes.instanceOf(Map).isRequired,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  };

  static defaultProps = {
    value: null,
  };

  render() {
    const { actions, value, ...props } = this.props;

    // Select values have to be strings or else we get propType errors.
    const stringValue = value ? value.toString(10) : undefined;

    return (

        <Select placeholder="Select an action..." value={stringValue} {...props}>
          {actions.toList().map(action => (
            <Select.Option
              key={action.get('id')}
              value={action.get('id', '').toString(10)}
              className={`rf-${action.get('name')}`}
            >
              {action.get('name')}
            </Select.Option>
          ))}
        </Select>

    );
  }
}

@connect(
  state => ({
    githubUrl: getGithubUrl(state),
  }),
)
class ArgumentEditorMissingError extends React.PureComponent {
  static propTypes = {
    githubUrl: PropTypes.string,
    name: PropTypes.string.isRequired,
  }

  static defaultProps = {
    githubUrl: null,
  }

  render() {
    const { githubUrl, name } = this.props;
    let fileIssueUrl;
    if (githubUrl) {
      const url = new URL(githubUrl);
      url.pathname += '/issues/new';
      url.searchParams.set('title', `Argument fields missing for action "${name}"`);
      fileIssueUrl = url.toString();
    }

    return (

        <QueryServiceInfo />
        <Alert
          message="Error - Argument editor not available"
          description={

              This is a bug. Please file an issue on GitHub for it.

          }
          type="error"
          showIcon
        />

    );
  }
}
<|endoftext|>


<commit_before>// The contents of this file will be executed before any of
// your view controllers are ever executed, including the index.
// You have access to all functionality on the `Alloy` namespace.
//
// This is a great place to do any initialization for your app
// or create any global variables/functions that you'd like to
// make available throughout your app. You can easily make things
// accessible globally by attaching them to the `Alloy.Globals`
// object. For example:

if (Ti.Locale.currentLanguage == 'sv') {
	Ti.App.Properties.setString('baseSavePath', Titanium.Filesystem.applicationDataDirectory + '/data/sv/');
} else {
	Ti.API.info(Ti.Locale.currentLanguage);
	Ti.App.Properties.setString('baseSavePath', Titanium.Filesystem.applicationDataDirectory + '/data/en/');
}

//-----------------------------------------------------------
// Globala variabler
//-----------------------------------------------------------
var gLat = 0;
var gLon = 0;
var lat = null;
var lon = null;
var foundId = 1;
var nextId = 1;
var foundJSON = [];
var alertedArray = [];
var foundLetterId = 1;
var letterJSON;
var alerted = false;

var globalTrailID = 0;
var word = 'ÖRONMANET';

var interactiveVisible = false;
var menuMapVisible = false;

var hotspotGPS = false;
var interactiveGPS = false;
var boatGPS = false;

var infospotArray = [];
var markerHotspotArray = [];
var clueZoneArray = [];

//-----------------------------------------------------------
// Globala variabler för att visa och släcka infospots
//-----------------------------------------------------------
var farjelage = false;
var snorkel = false;
var torrdass = false;
var utsiktsplats = false;
var rastplats = false;
var taltplats = false;
var badplats = false;
var information = false;
var eldplats = false;

//-----------------------------------------------------------
// Variabel för kartvyer
//-----------------------------------------------------------
var MapModule = require('ti.map');
var map = MapModule.createView({
	mapType : MapModule.HYBRID_TYPE,
	animate : true,
	height : '100%',
	width : Ti.UI.FILL
});
var detailMap = MapModule.createView({
	mapType : MapModule.HYBRID_TYPE,
	animate : true,
	height : '100%',
	width : Ti.UI.FILL
});
var interactiveMap = MapModule.createView({
	mapType : MapModule.HYBRID_TYPE,
	animate : true,
	height : '100%',
	width : Ti.UI.FILL,
	userLocation : true
});
var hotspotMap = MapModule.createView({
	mapType : MapModule.HYBRID_TYPE,
	animate : true,
	height : '100%',
	width : Ti.UI.FILL,
	userLocation : true
});
//-----------------------------------------------------------
// Felhantering
//-----------------------------------------------------------
function newError(errorMsg, pageName) {
	try {
		var er = new Error(errorMsg);
		er.myObject = pageName;
		throw er;
	} catch (e) {
		alert("Error:[" + e.message + "] has occured on " + e.myObject);
	}
}

//-----------------------------------------------------------
// Avsluta GPS när man stänger appen
//-----------------------------------------------------------
Titanium.App.addEventListener('close', function() {

	gLat = null;
	gLon = null;

	if(hotspotGPS){
		Alloy.Globals.stopGPS();
	}
	if(interactiveGPS){
		Alloy.Globals.stopGame();
	}
	if(boatGPS){
		Alloy.Globals.stopBoatGPS();
	}
});<commit_msg>KOS-35<commit_after>// The contents of this file will be executed before any of
// your view controllers are ever executed, including the index.
// You have access to all functionality on the `Alloy` namespace.
//
// This is a great place to do any initialization for your app
// or create any global variables/functions that you'd like to
// make available throughout your app. You can easily make things
// accessible globally by attaching them to the `Alloy.Globals`
// object. For example:

if (Ti.Locale.currentLanguage == 'sv') {
	Ti.App.Properties.setString('baseSavePath', Titanium.Filesystem.applicationDataDirectory + '/data/sv/');
} else {
	Ti.API.info(Ti.Locale.currentLanguage);
	Ti.App.Properties.setString('baseSavePath', Titanium.Filesystem.applicationDataDirectory + '/data/en/');
}

var languageWindow = Ti.UI.createWindow({
	backgroundColor: 'white',
	layout: 'vertical'
});

var lbl = Ti.UI.createLabel({
	text: 'Välj språk',
	top: 30
});
var lblSwe = Ti.UI.createLabel({
	text: 'Svenska'
});
var lblEng = Ti.UI.createLabel({
	text: 'Engelska'
});

lblSwe.addEventListener('click', function(e){
	languageWindow.close();
});

languageWindow.add(lbl);
languageWindow.add(lblSwe);
languageWindow.add(lblEng);
languageWindow.open({
	modal:true
});

//-----------------------------------------------------------
// Globala variabler
//-----------------------------------------------------------
var gLat = 0;
var gLon = 0;
var lat = null;
var lon = null;
var foundId = 1;
var nextId = 1;
var foundJSON = [];
var alertedArray = [];
var foundLetterId = 1;
var letterJSON;
var alerted = false;

var globalTrailID = 0;
var word = 'ÖRONMANET';

var interactiveVisible = false;
var menuMapVisible = false;

var hotspotGPS = false;
var interactiveGPS = false;
var boatGPS = false;

var infospotArray = [];
var markerHotspotArray = [];
var clueZoneArray = [];

//-----------------------------------------------------------
// Globala variabler för att visa och släcka infospots
//-----------------------------------------------------------
var farjelage = false;
var snorkel = false;
var torrdass = false;
var utsiktsplats = false;
var rastplats = false;
var taltplats = false;
var badplats = false;
var information = false;
var eldplats = false;

//-----------------------------------------------------------
// Variabel för kartvyer
//-----------------------------------------------------------
var MapModule = require('ti.map');
var map = MapModule.createView({
	mapType : MapModule.HYBRID_TYPE,
	animate : true,
	height : '100%',
	width : Ti.UI.FILL
});
var detailMap = MapModule.createView({
	mapType : MapModule.HYBRID_TYPE,
	animate : true,
	height : '100%',
	width : Ti.UI.FILL
});
var interactiveMap = MapModule.createView({
	mapType : MapModule.HYBRID_TYPE,
	animate : true,
	height : '100%',
	width : Ti.UI.FILL,
	userLocation : true
});
var hotspotMap = MapModule.createView({
	mapType : MapModule.HYBRID_TYPE,
	animate : true,
	height : '100%',
	width : Ti.UI.FILL,
	userLocation : true
});
//-----------------------------------------------------------
// Felhantering
//-----------------------------------------------------------
function newError(errorMsg, pageName) {
	try {
		var er = new Error(errorMsg);
		er.myObject = pageName;
		throw er;
	} catch (e) {
		alert("Error:[" + e.message + "] has occured on " + e.myObject);
	}
}

//-----------------------------------------------------------
// Avsluta GPS när man stänger appen
//-----------------------------------------------------------
Titanium.App.addEventListener('close', function() {

	gLat = null;
	gLon = null;

	if(hotspotGPS){
		Alloy.Globals.stopGPS();
	}
	if(interactiveGPS){
		Alloy.Globals.stopGame();
	}
	if(boatGPS){
		Alloy.Globals.stopBoatGPS();
	}
});<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const dicomParser = require('dicom-parser');
const TAG_DICT = require('./dataDictionary.js').TAG_DICT;

const REVERSE_TAG_DICT = new Map(
  Object.keys(TAG_DICT).map(k => [TAG_DICT[k].name, TAG_DICT[k]])
);

const parse = (filePath) => {
  const dicomFileAsBuffer = fs.readFileSync(filePath);
  return dicomParser.parseDicom(dicomFileAsBuffer);
};

const getTag = (key) => {
  const group = key.substring(1,5);
  const element = key.substring(5,9);
  const tagIndex = ('(' + group + ',' + element + ')').toUpperCase();
  return TAG_DICT[tagIndex];
};

const getKeyFromName = name => {
  if (REVERSE_TAG_DICT.get(name) !== undefined){
    const tag = REVERSE_TAG_DICT.get(name).tag;
    return ('x' + tag.substring(1,5) + tag.substring(6,10)).toLowerCase();
  }
};

const dicomDump = (filePath) => {
  const dp = parse(filePath);
  let dump = [];
  for (let key of Object.keys(dp.elements)) {
    let tag = getTag(key);
    let value = dp.string(key);
    let line = (tag && (tag.name + ': ' + value)) || (key + ': ' + value);
    dump.push(line);
  }
  return dump;
};

const dicomSort = (files) => files.map(
  (f) => {
    let dp;
    try {
      dp = parse(f);
    } catch (exc) {
      return {name: f};
    }
    const session = dp.string(getKeyFromName('StudyInstanceUID'));
    const acquisition = dp.string(getKeyFromName('SeriesInstanceUID'));
    return {
      name: f,
      session: session,
      acquisition: acquisition
    };
  }
).filter(
  (o) => {
    return o.session !== undefined && o.acquisition !== undefined;
  }
);

module.exports = {
  dicomDump: dicomDump,
  dicomSort: dicomSort
};
<commit_msg>Improve DICOM sorting<commit_after>'use strict';

const fs = require('fs');
const dicomParser = require('dicom-parser');
const TAG_DICT = require('./dataDictionary.js').TAG_DICT;

const REVERSE_TAG_DICT = new Map(
  Object.keys(TAG_DICT).map(k => [TAG_DICT[k].name, TAG_DICT[k]])
);

const parse = (filePath) => {
  const dicomFileAsBuffer = fs.readFileSync(filePath);
  return dicomParser.parseDicom(dicomFileAsBuffer);
};

const getTag = (key) => {
  const group = key.substring(1,5);
  const element = key.substring(5,9);
  const tagIndex = ('(' + group + ',' + element + ')').toUpperCase();
  return TAG_DICT[tagIndex];
};

const getKeyFromName = name => {
  if (REVERSE_TAG_DICT.get(name) !== undefined){
    const tag = REVERSE_TAG_DICT.get(name).tag;
    return ('x' + tag.substring(1,5) + tag.substring(6,10)).toLowerCase();
  }
};

const dicomDump = (filePath) => {
  const dp = parse(filePath);
  let dump = [];
  for (let key of Object.keys(dp.elements)) {
    let tag = getTag(key);
    let value = dp.string(key);
    let line = (tag && (tag.name + ': ' + value)) || (key + ': ' + value);
    dump.push(line);
  }
  return dump;
};

const dicomSort = (files) => files.map(
  (f) => {
    let dp;
    try {
      dp = parse(f);
    } catch (exc) {
      return {name: f};
    }
    const sessionUID = dp.string(getKeyFromName('StudyInstanceUID'));
    const seriesUID = dp.string(getKeyFromName('SeriesInstanceUID'));
    const manufacturer = dp.string(getKeyFromName('Manufacturer'));
    const acquisitionNumber = dp.string(getKeyFromName('AcquisitionNumber'));
    var acquisitionUID;
    if (manufacturer.toUpperCase() != 'SIEMENS') {
      acquisitionUID = seriesUID + '_' + acquisitionNumber;
    } else {
      acquisitionUID = seriesUID;
    }
    return {
      name: f,
      session: sessionUID,
      acquisition: acquisitionUID
    };
  }
).filter(
  (o) => {
    return o.session !== undefined && o.acquisition !== undefined;
  }
);

module.exports = {
  dicomDump: dicomDump,
  dicomSort: dicomSort
};
<|endoftext|>