<commit_before>'use strict';
require('ts-node/register');

const
    path         = require('path'),
    protractor   = require.resolve('protractor'),
    node_modules = protractor.substring(0, protractor.lastIndexOf('node_modules') + 12);

const isPullRequest      = () => !! process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== 'false';
const canUseBrowserStack = () => !! process.env.BROWSERSTACK_USERNAME && !! process.env.BROWSERSTACK_KEY;

const shouldUseBrowserStack   = () => ! isPullRequest() && canUseBrowserStack();
const shouldUsePhantomJS      = () =>   isPullRequest();
const shouldUseRegularChrome  = () => ! isPullRequest() && ! canUseBrowserStack();
const shouldUseHeadlessChrome = () => false;  // not ready for prime time: https://bugs.chromium.org/p/chromedriver/issues/detail?id=1772#c12

const capabilities = () => {
    switch (true) {
        case shouldUseBrowserStack():
            console.log('[Cookbook] Using BrowserStack');
            return {
                browserName: 'chrome',
                build:   process.env.BROWSERSTACK_AUTOMATE_BUILD,
                project: process.env.BROWSERSTACK_AUTOMATE_PROJECT,

                chromeOptions: {
                    args: ['--disable-infobars']
                },

                'browserstack.localIdentifier': process.env.BROWSERSTACK_LOCAL_IDENTIFIER,
                'browserstack.local': true,
            };
        case shouldUseHeadlessChrome():
            console.log('[Cookbook] Using headless Chrome');
            return {
                browserName: 'chrome',
                chromeOptions: {
                    args: ['--headless', '--disable-gpu', '--window-size=800,600']
                }
            };
        case shouldUsePhantomJS():
            console.log('[Cookbook] Using PhantomJS');
            return {
                'browserName': 'phantomjs',
                'phantomjs.binary.path': path.resolve(node_modules, 'phantomjs-prebuilt/lib/phantom/bin/phantomjs'),
            };
        case shouldUseRegularChrome():
        default:
            console.log('[Cookbook]: Using regular Chrome');
            return {
                browserName: 'chrome',
                chromeOptions: {
                    args: ['--disable-infobars']
                }
            };
    }
}

exports.config = {
    seleniumServerJar: path.resolve(node_modules, 'protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-2.53.1.jar'),

    directConnect: shouldUseRegularChrome() || shouldUseHeadlessChrome(),
    framework: 'mocha',
    specs: ['cookbook/**/*.recipe.ts'],

    browserstackUser: process.env.BROWSERSTACK_USERNAME,
    browserstackKey:  process.env.BROWSERSTACK_KEY,

    restartBrowserBetweenTests: false,

    capabilities: capabilities()
};
<commit_msg>Fixed the location of phantomJs<commit_after>'use strict';
require('ts-node/register');

const
    path         = require('path'),
    protractor   = require.resolve('protractor'),
    node_modules = protractor.substring(0, protractor.lastIndexOf('node_modules') + 12);

const isPullRequest      = () => !! process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== 'false';
const canUseBrowserStack = () => !! process.env.BROWSERSTACK_USERNAME && !! process.env.BROWSERSTACK_KEY;

const shouldUseBrowserStack   = () => ! isPullRequest() && canUseBrowserStack();
const shouldUsePhantomJS      = () =>   isPullRequest();
const shouldUseRegularChrome  = () => ! isPullRequest() && ! canUseBrowserStack();
const shouldUseHeadlessChrome = () => false;  // not ready for prime time: https://bugs.chromium.org/p/chromedriver/issues/detail?id=1772#c12

const capabilities = () => {
    switch (true) {
        case shouldUseBrowserStack():
            console.log('[Cookbook] Using BrowserStack');
            return {
                browserName: 'chrome',
                build:   process.env.BROWSERSTACK_AUTOMATE_BUILD,
                project: process.env.BROWSERSTACK_AUTOMATE_PROJECT,

                chromeOptions: {
                    args: ['--disable-infobars']
                },

                'browserstack.localIdentifier': process.env.BROWSERSTACK_LOCAL_IDENTIFIER,
                'browserstack.local': true,
            };
        case shouldUseHeadlessChrome():
            console.log('[Cookbook] Using headless Chrome');
            return {
                browserName: 'chrome',
                chromeOptions: {
                    args: ['--headless', '--disable-gpu', '--window-size=800,600']
                }
            };
        case shouldUsePhantomJS():
            console.log('[Cookbook] Using PhantomJS');
            return {
                'browserName': 'phantomjs',
                'phantomjs.binary.path': path.resolve(node_modules, 'phantomjs-prebuilt/bin/phantomjs'),
            };
        case shouldUseRegularChrome():
        default:
            console.log('[Cookbook]: Using regular Chrome');
            return {
                browserName: 'chrome',
                chromeOptions: {
                    args: ['--disable-infobars']
                }
            };
    }
}

exports.config = {
    seleniumServerJar: path.resolve(node_modules, 'protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-2.53.1.jar'),

    directConnect: shouldUseRegularChrome() || shouldUseHeadlessChrome(),
    framework: 'mocha',
    specs: ['cookbook/**/*.recipe.ts'],

    browserstackUser: process.env.BROWSERSTACK_USERNAME,
    browserstackKey:  process.env.BROWSERSTACK_KEY,

    restartBrowserBetweenTests: false,

    capabilities: capabilities()
};
<|endoftext|>


<commit_before>#! /usr/bin/env node

const sh = require('shelljs');

const docsDir = './docs/gaiden-css';
const sourceDocsDir = './docs/demo/gaiden-css/scss';
const sourceDir = './src/scss';
const minifiedDocsFile = `${docsDir}/ninja-demo.css`;

const options = {
  sass: ` --include-path ${sourceDocsDir} \
    --include-path ${sourceDir} \
    --output-style expanded \
    --sourceComments true \
    -o ${docsDir} \
    --recursive `
}

sh.exec(`node-sass ${sourceDocsDir} ${options.sass} ${minifiedDocsFile}`);
sh.exec(`documentjs`);
sh.cp('./build/stylesheets/gaiden.css', `${docsDir}/`)
<commit_msg>Missing comma<commit_after>#! /usr/bin/env node

const sh = require('shelljs');

const docsDir = './docs/gaiden-css';
const sourceDocsDir = './docs/demo/gaiden-css/scss';
const sourceDir = './src/scss';
const minifiedDocsFile = `${docsDir}/ninja-demo.css`;

const options = {
  sass: ` --include-path ${sourceDocsDir} \
    --include-path ${sourceDir} \
    --output-style expanded \
    --sourceComments true \
    -o ${docsDir} \
    --recursive `
}

sh.exec(`node-sass ${sourceDocsDir} ${options.sass} ${minifiedDocsFile}`);
sh.exec(`documentjs`);
sh.cp('./build/stylesheets/gaiden.css', `${docsDir}/`);
<|endoftext|>


<commit_before>Events = new Mongo.Collection('events');

Events.before.insert(function(userId, doc) {
    doc.dateCreated = new Date();

    if (userId) { //checks if request comes from frontend
        var user = Meteor.user();
        doc.organiser = {
            _id: userId,
            name: user.profile.name
        }
    }
});

Events.before.update(function(userId, doc, fieldNames, modifier) {
  // Check is the update comes from reporting the event or updating attendence
  if (userId && modifier['$set']['engagement'] === undefined && modifier['$set']['reported'] === undefined) {
    // Check for week enable checkbox
    if (doc['week_enable'] === true && modifier['$set']['week_enable'] !== false || modifier['$set']['week_enable'] === true) {
      if ((doc['repetition']['forever_enable'] === true && modifier['$set']['repetition.forever_enable'] !== false) || modifier['$set']['repetition.forever_enable'] === true) {

        // Removes the end date so that the event query returns the correct events.

        if (modifier['$unset']['repetition.lifetime_date'] !== undefined) {
          delete modifier['$unset']['repetition.lifetime_date'];
        }

        modifier['$set']['repetition.lifetime_date'] = '';
      }
    } else {

      // Removes both to make sure that the event query returns the correct events

      if (modifier['$unset']['repetition.lifetime_date'] !== undefined) {
        delete modifier['$unset']['repetition.lifetime_date'];
      }

      modifier['$set']['repetition.lifetime_date'] = '';

      if ( modifier['$unset']['repetition.forever_enable'] !== undefined) {
        delete modifier['$unset']['repetition.forever_enable'];
      }

      modifier['$set']['repetition.forever_enable'] = false;
    }
  }
});

WeekDay = new SimpleSchema({
    enable: {
        type: Boolean,
        defaultValue: false,
        autoform: {
            class: 'day-enable'
        }
    },
    time: {
        type: String,
        label: 'Opening Time *',
        optional: true,
        custom: function() {
            return weekDayValidation.call(this);
        },
        autoform: {
          defaultValue: "Pick a Time!",
          class: "required-label-tag selection-trigger-time"
        }
    },
    time_end: {
        type: String,
        label: 'Closing Time *',
        optional: true,
        custom: function() {
            return weekDayValidation.call(this);
        },
        autoform: {
          defaultValue: "Pick a Time!",
          class: "required-label-tag selection-trigger-time"
        }
    }
});

Week = new SimpleSchema({
    sunday: {
        type: WeekDay
    },
    monday: {
        type: WeekDay
    },
    tuesday: {
        type: WeekDay
    },
    wednesday: {
        type: WeekDay
    },
    thursday: {
        type: WeekDay
    },
    friday: {
        type: WeekDay
    },
    saturday: {
        type: WeekDay
    }
});

Repetition = new SimpleSchema({
    enable: {
        label: 'Recurring?',
        type: Boolean,
        defaultValue: false,
        autoform: {
            class: 'repeating_enable_check'
        }
    },
    frequency: {
        label: 'Frequency',
        type: String,
        optional: true,
        custom: function() {
            if (this.siblingField("enable").value && !this.isSet) {
                return "required";
            }
        },
        autoform: {
            type: 'select-radio',
            label: false,
            options: function () {
                return ["Weekly", "Biweekly", "Monthly"].map(function (entry) {
                    return {label: entry, value: entry};
                });
            },
            class: 'frequency'
        }
    },
    monthlyDays: {
        'label': 'Day',
        type: Number,
        optional: true,
        custom: function() {
            if (this.siblingField("enable").value && this.siblingField("frequency").value === "Monthly" && !this.isSet) {
                return "required";
            }
        },
        autoform: {
            options: function () {
                return getDaysArr().map(function (entry) {
                    return {label: entry, value: entry};
                });
            },
            firstOption: 'Pick a Day!',
            class: 'monthlyDay'
        }
    },
    forever_enable: {
        type: Boolean,
        label: 'Repeats Forever or for Unknown Time',
        autoform: {
            checked: false,
            class: "forever_enable"
        }
    },
    lifetime_date: {
        type: Date,
        optional: true,
        label: "Ending Date *",
        custom: function() {
            if (this.field('week_enable').value) {
                var enabled = this.siblingField("forever_enable").value;
                if (!enabled) {
                    if (!this.isSet) {
                        return "required";
                    }
                }
            }
        },
        autoform: {
            type: 'pickadate',
            pickadateOptions: {
                format: 'd mmmm, yyyy',
                formatSubmit: 'yyyy-mm-dd'
            },
            class: "lifetime-date required-label-tag"
        }
    }
});

Events.attachSchema(new SimpleSchema({
    organiser: {
        type: Object,
        autoform: {
            omit: true
        }
    },
    'organiser._id': {
        type: String,
        autoform: {
            type: 'hidden'
        }
    },
    'organiser.name': {
        type: String,
        autoform: {
            type: 'hidden'
        }
    },
    category: {
        type: Object
    },
    'category._id': {
        type: String,
        //optional: true,
        autoform: {
          hidden: true,
          label: false,
          firstOption: 'Choose Category',
          class: 'category-select-id'
        }
    },
    'category.name': {
        type: String,
        autoform: {
            type: 'hidden'
        },
        optional: true,
        autoValue: function() {
            var categoryId = this.field('category._id').value;
            if (!categoryId) return this.value;     //don't change the value if can't find _id
            return Categories.findOne(categoryId).name;
        }
    },
    'category.color': {
        type: String,
        autoform: {
            type: 'hidden'
        },
        optional: true,
        autoValue: function() {
            var categoryId = this.field('category._id').value;
            if (!categoryId) return this.value;     //don't change the value if can't find _id
            return Categories.findOne(categoryId).color;
        }
    },
    'category.approved': {
      type: Boolean,
      autoform: {
        type: 'hidden'
      },
      optional: true,
      autoValue: function() {
        var categoryId = this.field('category._id').value;
        if (!categoryId) {
          return false;
        }
        return Categories.findOne(categoryId).approved;
      }
    },
    name: {
        type: String,
        label: 'Name',
        max: 100,
        autoform: {
            id: "event-name"
        }
    },
    address: {
        type: String,
        label: 'Address or postcode',
        max: 100,
        autoform: {
            //add attributes to the form element
            afFieldInput: {
                //SEE DOCS: https://github.com/sergeyt/meteor-typeahead
                'class': "typeahead",
                'data-source': "geocodeDataSource",
                'data-min-length': "3",
                'data-autoselect': "true",
                'data-highlight': "true",
                'data-select': "selectedHandler"
            }
        },
        //@TODO could be nice if we could validate ONLY this field on blur, this could save API usage
        custom: _.debounce(function() {
            if (Meteor.isClient && this.isSet) {
                Meteor.call("getCoords", this.value, function (error, result) {
                    if (typeof result == 'undefined' || result.length == 0) {
                        Events.simpleSchema().namedContext("events-form").addInvalidKeys([{
                            name: "address",
                            type: "notFound"
                        }]);
                    }
                });
            }
        },600)
    },
    coordinates: {
        type: Object,
        autoform: {
            //type: "hidden"
        },
        optional: true,
        custom: function() {
            var invalidKeys = Events.simpleSchema().namedContext("events-form").invalidKeys().
                map(function(key){
                    return key.name
                });
            var addressKey = 'address';
            var isAddressValid = !_.contains(invalidKeys,addressKey);
            if (isAddressValid) {
                if (!this.isSet) return "required";
            }
        }
    },
    'coordinates.lat': {
        type: Number,
        decimal: true,
        autoform: {
            //disabled: true
            type: "hidden",
            label: false
        }
    },
    'coordinates.lng': {
        type: Number,
        decimal: true,
        autoform: {
            //disabled: true
            type: "hidden",
            label: false
        }
    },
    meetingPoint: {
        type: String,
        label: 'How to Find',
        max: 100
    },
    findHints: {
        type: String,
        label: 'How to find us?',
        max: 250,
        optional: true
    },
    dateEvent: {
        type: Date,
        label: 'Starting Date *',
        autoform: {
            type: 'pickadate',
            pickadateOptions: {
                format: 'd mmmm, yyyy',
                formatSubmit: 'yyyy-mm-dd'
            },
            class: 'required-label-tag'
        }
    },
    time: {
        type: String,
        label: 'Starting Time *',
        optional: true,
        custom: function() {
            return lifetimeBasicValidation.call(this);
        },
        autoform: {
          defaultValue: "Pick a Time!",
          class: "required-label-tag selection-trigger-time"
        },
    },
    time_end: {
        type: String,
        label: 'Closing Time *',
        optional: true,
        custom: function() {
            return lifetimeBasicValidation.call(this);
        },
        autoform: {
          defaultValue: "Pick a Time!",
          class: "required-label-tag selection-trigger-time"
        }
    },
    //optional links to social sites where the event is promoted
    'links.$.url': {
        type: String,
        label: 'Link',
        max: 200,
        regEx: SimpleSchema.RegEx.Url
    },
    overview: {
      type: String,
      label: 'Overview',
      max: 150,
      autoform: {
          type: "textarea",
          class: "overview-word-limit"
      }
  },
    description: {
        type: String,
        label: 'Description',
        max: 400,
        autoform: {
            type: "textarea",
            class: "description-word-limit"
        }
    },
    dateCreated: {
        type: Date,
        label: 'Date published',
        autoform: {
            omit: true
        }
    },
    reported: {
      type: Object,
      optional: true,
      autoform: {
          type: 'hidden'
      }
    },
    'reported.number': {
        type: Number,
        decimal: true,
        autoform: {
            type: 'hidden'
        }
    },
    'reported.status': {
        type: Boolean,
        autoform: {
          type: 'hidden'
        }
    },
    'reported.admin_overwrite': {
        type: Boolean,
        autoform: {
            type: 'hidden'
        }
    },
    'reported.users': {
      type: [String],
      autoform: {
        type: 'hidden'
      }
    },
    week_enable: {
        label: 'More than one day?',
        type: Boolean,
        defaultValue: false,
        autoform: {
            class: 'week_enable_check'
        }
    },
    repetition: {
        type: Repetition
    },
    week: {
        type: Week,
        optional: true
    },
    time_equal: {
        type: Boolean,
        defaultValue: false,
        optional: true,
        label: "Set Times Equal",
        autoform: {
            class: 'times-equal'
        }
    },
    engagement: {
      type: Object,
      optional: true
    },
    'engagement.limit': {
      type: Number,
      autoform: {
        min: '0'
      }
    },
    'engagement.attendees': {
      type: [String],
      optional: true,
      autoform: {
        type: 'hidden'
      }
    }
}));
SimpleSchema.messages({
    "required category._id": "Please select a category",
    "required coordinates": "Please provide an address",
    "notFound address": "Address not found",
    "offline address": "Address not available, are you offline?",
    "required repetition.frequency": "Please select an option"
});

function mergeDateTime(date, time) {
    if (date === undefined || time === undefined) {
      return;
    }
    var hour = time.split(':')[0];
    var minutes = time.split(':')[1];
    date.setHours(hour);
    date.setMinutes(minutes);
    return date
}

function getDaysArr() {
    var result = [];
    for (var i = 0; i <= 31; i++) {
        result.push(i);
    }
    return result;
}

// Helper functions for validation
function lifetimeBasicValidation() {
    if ((!this.field('week_enable').value || this.field('time_equal').value) && !this.isSet) {
        return "required";
    }
}

function weekDayValidation() {
    if (this.siblingField("enable").value && !this.isSet) {
        if (this.field('time_equal').value === false) {
            return "required";
        }
    }
}
<commit_msg>change limit label to attendee limit<commit_after>Events = new Mongo.Collection('events');

Events.before.insert(function(userId, doc) {
    doc.dateCreated = new Date();

    if (userId) { //checks if request comes from frontend
        var user = Meteor.user();
        doc.organiser = {
            _id: userId,
            name: user.profile.name
        }
    }
});

Events.before.update(function(userId, doc, fieldNames, modifier) {
  // Check is the update comes from reporting the event or updating attendence
  if (userId && modifier['$set']['engagement'] === undefined && modifier['$set']['reported'] === undefined) {
    // Check for week enable checkbox
    if (doc['week_enable'] === true && modifier['$set']['week_enable'] !== false || modifier['$set']['week_enable'] === true) {
      if ((doc['repetition']['forever_enable'] === true && modifier['$set']['repetition.forever_enable'] !== false) || modifier['$set']['repetition.forever_enable'] === true) {

        // Removes the end date so that the event query returns the correct events.

        if (modifier['$unset']['repetition.lifetime_date'] !== undefined) {
          delete modifier['$unset']['repetition.lifetime_date'];
        }

        modifier['$set']['repetition.lifetime_date'] = '';
      }
    } else {

      // Removes both to make sure that the event query returns the correct events

      if (modifier['$unset']['repetition.lifetime_date'] !== undefined) {
        delete modifier['$unset']['repetition.lifetime_date'];
      }

      modifier['$set']['repetition.lifetime_date'] = '';

      if ( modifier['$unset']['repetition.forever_enable'] !== undefined) {
        delete modifier['$unset']['repetition.forever_enable'];
      }

      modifier['$set']['repetition.forever_enable'] = false;
    }
  }
});

WeekDay = new SimpleSchema({
    enable: {
        type: Boolean,
        defaultValue: false,
        autoform: {
            class: 'day-enable'
        }
    },
    time: {
        type: String,
        label: 'Opening Time *',
        optional: true,
        custom: function() {
            return weekDayValidation.call(this);
        },
        autoform: {
          defaultValue: "Pick a Time!",
          class: "required-label-tag selection-trigger-time"
        }
    },
    time_end: {
        type: String,
        label: 'Closing Time *',
        optional: true,
        custom: function() {
            return weekDayValidation.call(this);
        },
        autoform: {
          defaultValue: "Pick a Time!",
          class: "required-label-tag selection-trigger-time"
        }
    }
});

Week = new SimpleSchema({
    sunday: {
        type: WeekDay
    },
    monday: {
        type: WeekDay
    },
    tuesday: {
        type: WeekDay
    },
    wednesday: {
        type: WeekDay
    },
    thursday: {
        type: WeekDay
    },
    friday: {
        type: WeekDay
    },
    saturday: {
        type: WeekDay
    }
});

Repetition = new SimpleSchema({
    enable: {
        label: 'Recurring?',
        type: Boolean,
        defaultValue: false,
        autoform: {
            class: 'repeating_enable_check'
        }
    },
    frequency: {
        label: 'Frequency',
        type: String,
        optional: true,
        custom: function() {
            if (this.siblingField("enable").value && !this.isSet) {
                return "required";
            }
        },
        autoform: {
            type: 'select-radio',
            label: false,
            options: function () {
                return ["Weekly", "Biweekly", "Monthly"].map(function (entry) {
                    return {label: entry, value: entry};
                });
            },
            class: 'frequency'
        }
    },
    monthlyDays: {
        'label': 'Day',
        type: Number,
        optional: true,
        custom: function() {
            if (this.siblingField("enable").value && this.siblingField("frequency").value === "Monthly" && !this.isSet) {
                return "required";
            }
        },
        autoform: {
            options: function () {
                return getDaysArr().map(function (entry) {
                    return {label: entry, value: entry};
                });
            },
            firstOption: 'Pick a Day!',
            class: 'monthlyDay'
        }
    },
    forever_enable: {
        type: Boolean,
        label: 'Repeats Forever or for Unknown Time',
        autoform: {
            checked: false,
            class: "forever_enable"
        }
    },
    lifetime_date: {
        type: Date,
        optional: true,
        label: "Ending Date *",
        custom: function() {
            if (this.field('week_enable').value) {
                var enabled = this.siblingField("forever_enable").value;
                if (!enabled) {
                    if (!this.isSet) {
                        return "required";
                    }
                }
            }
        },
        autoform: {
            type: 'pickadate',
            pickadateOptions: {
                format: 'd mmmm, yyyy',
                formatSubmit: 'yyyy-mm-dd'
            },
            class: "lifetime-date required-label-tag"
        }
    }
});

Events.attachSchema(new SimpleSchema({
    organiser: {
        type: Object,
        autoform: {
            omit: true
        }
    },
    'organiser._id': {
        type: String,
        autoform: {
            type: 'hidden'
        }
    },
    'organiser.name': {
        type: String,
        autoform: {
            type: 'hidden'
        }
    },
    category: {
        type: Object
    },
    'category._id': {
        type: String,
        //optional: true,
        autoform: {
          hidden: true,
          label: false,
          firstOption: 'Choose Category',
          class: 'category-select-id'
        }
    },
    'category.name': {
        type: String,
        autoform: {
            type: 'hidden'
        },
        optional: true,
        autoValue: function() {
            var categoryId = this.field('category._id').value;
            if (!categoryId) return this.value;     //don't change the value if can't find _id
            return Categories.findOne(categoryId).name;
        }
    },
    'category.color': {
        type: String,
        autoform: {
            type: 'hidden'
        },
        optional: true,
        autoValue: function() {
            var categoryId = this.field('category._id').value;
            if (!categoryId) return this.value;     //don't change the value if can't find _id
            return Categories.findOne(categoryId).color;
        }
    },
    'category.approved': {
      type: Boolean,
      autoform: {
        type: 'hidden'
      },
      optional: true,
      autoValue: function() {
        var categoryId = this.field('category._id').value;
        if (!categoryId) {
          return false;
        }
        return Categories.findOne(categoryId).approved;
      }
    },
    name: {
        type: String,
        label: 'Name',
        max: 100,
        autoform: {
            id: "event-name"
        }
    },
    address: {
        type: String,
        label: 'Address or postcode',
        max: 100,
        autoform: {
            //add attributes to the form element
            afFieldInput: {
                //SEE DOCS: https://github.com/sergeyt/meteor-typeahead
                'class': "typeahead",
                'data-source': "geocodeDataSource",
                'data-min-length': "3",
                'data-autoselect': "true",
                'data-highlight': "true",
                'data-select': "selectedHandler"
            }
        },
        //@TODO could be nice if we could validate ONLY this field on blur, this could save API usage
        custom: _.debounce(function() {
            if (Meteor.isClient && this.isSet) {
                Meteor.call("getCoords", this.value, function (error, result) {
                    if (typeof result == 'undefined' || result.length == 0) {
                        Events.simpleSchema().namedContext("events-form").addInvalidKeys([{
                            name: "address",
                            type: "notFound"
                        }]);
                    }
                });
            }
        },600)
    },
    coordinates: {
        type: Object,
        autoform: {
            //type: "hidden"
        },
        optional: true,
        custom: function() {
            var invalidKeys = Events.simpleSchema().namedContext("events-form").invalidKeys().
                map(function(key){
                    return key.name
                });
            var addressKey = 'address';
            var isAddressValid = !_.contains(invalidKeys,addressKey);
            if (isAddressValid) {
                if (!this.isSet) return "required";
            }
        }
    },
    'coordinates.lat': {
        type: Number,
        decimal: true,
        autoform: {
            //disabled: true
            type: "hidden",
            label: false
        }
    },
    'coordinates.lng': {
        type: Number,
        decimal: true,
        autoform: {
            //disabled: true
            type: "hidden",
            label: false
        }
    },
    meetingPoint: {
        type: String,
        label: 'How to Find',
        max: 100
    },
    findHints: {
        type: String,
        label: 'How to find us?',
        max: 250,
        optional: true
    },
    dateEvent: {
        type: Date,
        label: 'Starting Date *',
        autoform: {
            type: 'pickadate',
            pickadateOptions: {
                format: 'd mmmm, yyyy',
                formatSubmit: 'yyyy-mm-dd'
            },
            class: 'required-label-tag'
        }
    },
    time: {
        type: String,
        label: 'Starting Time *',
        optional: true,
        custom: function() {
            return lifetimeBasicValidation.call(this);
        },
        autoform: {
          defaultValue: "Pick a Time!",
          class: "required-label-tag selection-trigger-time"
        },
    },
    time_end: {
        type: String,
        label: 'Closing Time *',
        optional: true,
        custom: function() {
            return lifetimeBasicValidation.call(this);
        },
        autoform: {
          defaultValue: "Pick a Time!",
          class: "required-label-tag selection-trigger-time"
        }
    },
    //optional links to social sites where the event is promoted
    'links.$.url': {
        type: String,
        label: 'Link',
        max: 200,
        regEx: SimpleSchema.RegEx.Url
    },
    overview: {
      type: String,
      label: 'Overview',
      max: 150,
      autoform: {
          type: "textarea",
          class: "overview-word-limit"
      }
  },
    description: {
        type: String,
        label: 'Description',
        max: 400,
        autoform: {
            type: "textarea",
            class: "description-word-limit"
        }
    },
    dateCreated: {
        type: Date,
        label: 'Date published',
        autoform: {
            omit: true
        }
    },
    reported: {
      type: Object,
      optional: true,
      autoform: {
          type: 'hidden'
      }
    },
    'reported.number': {
        type: Number,
        decimal: true,
        autoform: {
            type: 'hidden'
        }
    },
    'reported.status': {
        type: Boolean,
        autoform: {
          type: 'hidden'
        }
    },
    'reported.admin_overwrite': {
        type: Boolean,
        autoform: {
            type: 'hidden'
        }
    },
    'reported.users': {
      type: [String],
      autoform: {
        type: 'hidden'
      }
    },
    week_enable: {
        label: 'More than one day?',
        type: Boolean,
        defaultValue: false,
        autoform: {
            class: 'week_enable_check'
        }
    },
    repetition: {
        type: Repetition
    },
    week: {
        type: Week,
        optional: true
    },
    time_equal: {
        type: Boolean,
        defaultValue: false,
        optional: true,
        label: "Set Times Equal",
        autoform: {
            class: 'times-equal'
        }
    },
    engagement: {
      type: Object,
      optional: true
    },
    'engagement.limit': {
      type: Number,
      label: 'Attendee Limit',
      autoform: {
        min: '0'
      }
    },
    'engagement.attendees': {
      type: [String],
      optional: true,
      autoform: {
        type: 'hidden'
      }
    }
}));
SimpleSchema.messages({
    "required category._id": "Please select a category",
    "required coordinates": "Please provide an address",
    "notFound address": "Address not found",
    "offline address": "Address not available, are you offline?",
    "required repetition.frequency": "Please select an option"
});

function mergeDateTime(date, time) {
    if (date === undefined || time === undefined) {
      return;
    }
    var hour = time.split(':')[0];
    var minutes = time.split(':')[1];
    date.setHours(hour);
    date.setMinutes(minutes);
    return date
}

function getDaysArr() {
    var result = [];
    for (var i = 0; i <= 31; i++) {
        result.push(i);
    }
    return result;
}

// Helper functions for validation
function lifetimeBasicValidation() {
    if ((!this.field('week_enable').value || this.field('time_equal').value) && !this.isSet) {
        return "required";
    }
}

function weekDayValidation() {
    if (this.siblingField("enable").value && !this.isSet) {
        if (this.field('time_equal').value === false) {
            return "required";
        }
    }
}
<|endoftext|>


<commit_before>compareVersions = function (v1, v2) { // return true if v2 is newer than v1
  var v1Array = v1.split('.');
  var v2Array = v2.split('.');
  // go through each segment of v2 and stop if we find one that's higher
  // than the equivalent segment of v1; else return false
  return v2Array.some( function (value, index) {
    return value > v1Array[index];
  });
  return false;
}

Meteor.startup(function () {
  if(Meteor.user() && isAdmin(Meteor.user())){
    var url = 'http://version.telescopeapp.org/';
    HTTP.get(url, {
      params: {
        currentVersion: telescopeVersion,
        siteTitle: getSetting('title'),
        siteUrl: getSiteUrl()
      }
    }, function (error, result) {
      if(result){
        // console.log(result);
        var currentVersion = telescopeVersion;
        var newVersion = result.content;
        var message = "";
        if (compareVersions(currentVersion, newVersion)){
          Session.set('updateVersion', newVersion);
        }
      }
    });
  }
});

heroModules.push({
  template: 'updateBanner'
});<commit_msg>set updateVersion to null on startup<commit_after>compareVersions = function (v1, v2) { // return true if v2 is newer than v1
  var v1Array = v1.split('.');
  var v2Array = v2.split('.');
  // go through each segment of v2 and stop if we find one that's higher
  // than the equivalent segment of v1; else return false
  return v2Array.some( function (value, index) {
    return value > v1Array[index];
  });
  return false;
}

Meteor.startup(function () {
  Session.set('updateVersion', null);

  if(Meteor.user() && isAdmin(Meteor.user())){
    var url = 'http://version.telescopeapp.org/';
    HTTP.get(url, {
      params: {
        currentVersion: telescopeVersion,
        siteTitle: getSetting('title'),
        siteUrl: getSiteUrl()
      }
    }, function (error, result) {
      if(result){
        // console.log(result);
        var currentVersion = telescopeVersion;
        var newVersion = result.content;
        var message = "";
        if (compareVersions(currentVersion, newVersion)){
          Session.set('updateVersion', newVersion);
        }
      }
    });
  }
});

heroModules.push({
  template: 'updateBanner'
});<|endoftext|>


<commit_before>var httplib = require('http');
var pgplib = require('pg-promise');
var scrub = require('pg-format');

var common = require('../common');
var expect = common.expect;
var Promise = common.Promise;

var handleError = require('../common').handleError;

var couch2pg = require('../../index');

// prebuild the query string with table and column references
var pgcol = process.env.POSTGRESQL_COLUMN;
var pgtab = process.env.POSTGRESQL_TABLE;
var queryStr = scrub('SELECT %I FROM %I WHERE %I->>\'_id\' = %%L AND %I->>\'_rev\' = %%L;', pgcol, pgtab, pgcol, pgcol);

describe('Integration', function() {

  before(function (done) {
    couch2pg().then(function () {
      done();
    }, function (err) {
      done(err);
    });
  });

  it('moves all documents to postgres', function(done) {
    // connect to postgres
    var pgp = pgplib({ 'promiseLib': Promise });
    var db = pgp(process.env.POSTGRESQL_URL);

    // fetch all documents out of couch
    var buffer = '';
    var incoming = httplib.request(process.env.COUCHDB_URL);
    incoming.on('response', function (res) {
      res.setEncoding('utf8');
      res.on('data', function(chunk) {
        buffer = buffer + new Buffer(chunk);
      });
      res.on('end', function() {
        // document download completed
        var data = JSON.parse(buffer);
        // setup a single connection for a series of thenable queries
        var sco;
        var queries = db.connect()
          .then(function(cnxn) {
            sco = cnxn;
          });
        // iterate over all documents
        data.rows.forEach(function (row) {

          // confirm each doc is in postgres
          var uuid = row.id;
          var rev = row.value.rev;
          var thisQuery = scrub(queryStr, uuid, rev);
          // iterative step: order queries with then
          queries = queries.then(function () {
            return sco.query(thisQuery);
          }, handleError)
            .then(function(result) {
              if (result[0] === undefined) {
                throw Error('cannot find result for query: ' + thisQuery);
              }
              var obj = result[0][pgcol];
              return expect(obj).deep.equals(row.doc);
            }, handleError);
        });
        // mark completion when the last promise has returned
        queries.then(function () {
            done();
          })
          .catch(function (err) {
            done(err);
          })
          .finally(function () {
            if (sco) {
              // close the database connection
              sco.done();
            }
          });
      });
    });
    incoming.end();
  });

});
<commit_msg>avoid _design docs for Travis integration testing<commit_after>var httplib = require('http');
var pgplib = require('pg-promise');
var scrub = require('pg-format');

var common = require('../common');
var expect = common.expect;
var Promise = common.Promise;

var handleError = require('../common').handleError;

var couch2pg = require('../../index');

// prebuild the query string with table and column references
var pgcol = process.env.POSTGRESQL_COLUMN;
var pgtab = process.env.POSTGRESQL_TABLE;
var queryStr = scrub('SELECT %I FROM %I WHERE %I->>\'_id\' = %%L AND %I->>\'_rev\' = %%L;', pgcol, pgtab, pgcol, pgcol);

describe('Integration', function() {

  before(function (done) {
    couch2pg().then(function () {
      done();
    }, function (err) {
      done(err);
    });
  });

  it('moves all documents to postgres', function(done) {
    // connect to postgres
    var pgp = pgplib({ 'promiseLib': Promise });
    var db = pgp(process.env.POSTGRESQL_URL);

    // fetch all documents out of couch
    var buffer = '';
    var incoming = httplib.request(process.env.COUCHDB_URL);
    incoming.on('response', function (res) {
      res.setEncoding('utf8');
      res.on('data', function(chunk) {
        buffer = buffer + new Buffer(chunk);
      });
      res.on('end', function() {
        // document download completed
        var data = JSON.parse(buffer);
        // setup a single connection for a series of thenable queries
        var sco;
        var queries = db.connect()
          .then(function(cnxn) {
            sco = cnxn;
          });
        // iterate over all documents
        data.rows.forEach(function (row) {

          // confirm each doc is in postgres
          var uuid = row.id;
          var rev = row.value.rev;
          var thisQuery = scrub(queryStr, uuid, rev);
          // skip design docs
          if (uuid.slice(0,7) === '_design') { return; }
          // iterative step: order queries with then
          queries = queries.then(function () {
            return sco.query(thisQuery);
          }, handleError)
            .then(function(result) {
              if (result[0] === undefined) {
                throw Error('cannot find result for query: ' + thisQuery);
              }
              var obj = result[0][pgcol];
              return expect(obj).deep.equals(row.doc);
            }, handleError);
        });
        // mark completion when the last promise has returned
        queries.then(function () {
            done();
          })
          .catch(function (err) {
            done(err);
          })
          .finally(function () {
            if (sco) {
              // close the database connection
              sco.done();
            }
          });
      });
    });
    incoming.end();
  });

});
<|endoftext|>


<commit_before>
// Regexp pattern for extract translations
// Some tools:
//  - https://regexper.com/
//  - https://regex101.com/
//  - http://www.freeformatter.com/javascript-escape.html
exports.pattern = function(gettext) {
  // If custom pattern provided, enforce word boundary to avoid some false positives.
  // e.g. someString.split('.') would extract '.' if custom pattern is 't'
  const patternName = typeof gettext !== 'string' ? 'context.t' : `\\b(?=\\w)${gettext}`;

  return new RegExp(
    `(?:${patternName}(?:(?:(?:\\(\\s*?\\"(.+?[^\\\\])(?:\\"))|(?:\\(\\s*?\\'(.+?[^\\\\])(?:\\')))|(?:(?:\\(\\s*?\\[\\s*?\\'(.+?[^\\\\])\\'\\s*?\\,\\s*?\\'(.+?[^\\\\])\\')|(?:\\(\\s*?\\[\\s*?\\"(.+?[^\\\\])\\"\\s*?\\,\\s*?\\"(.+?[^\\\\])\\")))(?:.*?\\}\\s*?\\,\\s*?(?:(?:\\'(.+?[^\\\\])\\')|(?:\\s*?\\"(.+?[^\\\\])\\")))?)`,
    'g'
  );
};

// Extract all occurences of content
exports.getAllMatches = function(pattern, content) {
  var found = [];
  var m = null;

  while ((m = pattern.exec(content)) !== null) {
    if (m.index === pattern.lastIndex) {
        pattern.lastIndex++;
    }
    found.push({
      text: m[1] || m[2] || m[3] || m[5],
      comment: (m[7] || m[8]) || null,
      plural: (m[4] || m[6]) || null
    })
  }

  return found;
}

// Grouping by text
exports.groupByText = function(filesMatches) {
  let group = {}

  for (let file in filesMatches) {
    const matches = filesMatches[file]

    for (let i = 0; i < matches.length; i++) {
      const trans = matches[i]

      if (group[trans.text] === undefined) {
        group[trans.text] = { files: [file], trans: trans }
      } else {
        if (group[trans.text].files.indexOf(file) === -1) {
          group[trans.text].files.push(file)
        }
      }
    }
  }

  return group
}

// Build pot file content
exports.potFileContent = function(texts) {
  let content = ''

  for (var obj in texts) {

    const files = texts[obj].files
    const trans = texts[obj].trans

    if (trans.comment) {
      content += `#. ${trans.comment}\n`
    }

    files.map((file) => {
      content += `#: ${file}\n`
    })

    // We must check if text is plural or not.
    if (trans.plural) {
      content += `msgid "${trans.text}"\nmsgid_plural "${trans.plural}"\nmsgstr[0] ""\nmsgstr[1] ""\n\n`
    } else {
      content += `msgid "${trans.text}"\nmsgstr ""\n\n`
    }

  }

  return content
}
<commit_msg>write to consume multiple comments<commit_after>
// Regexp pattern for extract translations
// Some tools:
//  - https://regexper.com/
//  - https://regex101.com/
//  - http://www.freeformatter.com/javascript-escape.html
exports.pattern = function(gettext) {
  // If custom pattern provided, enforce word boundary to avoid some false positives.
  // e.g. someString.split('.') would extract '.' if custom pattern is 't'
  const patternName = typeof gettext !== 'string' ? 'context.t' : `\\b(?=\\w)${gettext}`;

  return new RegExp(
    `(?:${patternName}(?:(?:(?:\\(\\s*?\\"(.+?[^\\\\])(?:\\"))|(?:\\(\\s*?\\'(.+?[^\\\\])(?:\\')))|(?:(?:\\(\\s*?\\[\\s*?\\'(.+?[^\\\\])\\'\\s*?\\,\\s*?\\'(.+?[^\\\\])\\')|(?:\\(\\s*?\\[\\s*?\\"(.+?[^\\\\])\\"\\s*?\\,\\s*?\\"(.+?[^\\\\])\\")))(?:.*?\\}\\s*?\\,\\s*?(?:(?:\\'(.+?[^\\\\])\\')|(?:\\s*?\\"(.+?[^\\\\])\\")))?)`,
    'g'
  );
};

// Extract all occurences of content
exports.getAllMatches = function(pattern, content) {
  var found = [];
  var m = null;

  while ((m = pattern.exec(content)) !== null) {
    if (m.index === pattern.lastIndex) {
        pattern.lastIndex++;
    }
    found.push({
      text: m[1] || m[2] || m[3] || m[5],
      comment: (m[7] || m[8]) || null,
      plural: (m[4] || m[6]) || null
    })
  }

  return found;
}

// Grouping by text
exports.groupByText = function(filesMatches) {
  let group = {}

  for (let file in filesMatches) {
    const matches = filesMatches[file]

    for (let i = 0; i < matches.length; i++) {
      const trans = matches[i]

      if (group[trans.text] === undefined) {
        group[trans.text] = { files: [file], trans: trans, comments: [trans.comment] }
      } else {
        if (group[trans.text].files.indexOf(file) === -1) {
          group[trans.text].files.push(file)
        }
        if (group[trans.text].comments.indexOf(trans.comment) === -1) {
          group[trans.text].comments.push(trans.comment)
        }
      }
    }
  }

  return group
}

// Build pot file content
exports.potFileContent = function(texts) {
  let content = ''

  for (var obj in texts) {

    const files = texts[obj].files
    const trans = texts[obj].trans
    const comments = texts[obj].comments

    comments.filter(comment => comment).map((comment) => {
      content += `#. ${comment}\n`
    })

    files.map((file) => {
      content += `#: ${file}\n`
    })

    // We must check if text is plural or not.
    if (trans.plural) {
      content += `msgid "${trans.text}"\nmsgid_plural "${trans.plural}"\nmsgstr[0] ""\nmsgstr[1] ""\n\n`
    } else {
      content += `msgid "${trans.text}"\nmsgstr ""\n\n`
    }

  }

  return content
}
<|endoftext|>


<commit_before>Groups = new Mongo.Collection('groups');

var GroupsSchema = new SimpleSchema({
  name:{
    type:String
});

// Add i18n tags
GroupsSchema.i18n("groups");

Groups.attachSchema(GroupsSchema);

Groups.helpers({
  'homes': function () {
    // Get group ID
    var groupId = this._id;

    // Get all homes assigned to group
    var homes = Homes.find({'groupId': groupId}).fetch();

    return homes;
  }
});

Groups.allow({
  insert: function () {
    return true;
  }
});
<commit_msg>Fix syntax error<commit_after>Groups = new Mongo.Collection('groups');

var GroupsSchema = new SimpleSchema({
  name: {
    type: String
  }
});

// Add i18n tags
GroupsSchema.i18n("groups");

Groups.attachSchema(GroupsSchema);

Groups.helpers({
  'homes': function () {
    // Get group ID
    var groupId = this._id;

    // Get all homes assigned to group
    var homes = Homes.find({'groupId': groupId}).fetch();

    return homes;
  }
});

Groups.allow({
  insert: function () {
    return true;
  }
});
<|endoftext|>


<commit_before>import { inject as service } from '@ember/service';
import Component from '@ember/component';
import layout from '../templates/components/cs-version-control';
import { task } from 'ember-concurrency';
import { modelType } from '@cardstack/rendering/helpers/cs-model-type';
import { defaultBranch } from '@cardstack/plugin-utils/environment';
import { computed } from "@ember/object";
import { or } from '@ember/object/computed';

export default Component.extend({
  layout,
  tagName: '',
  opened: true,
  animationRules,
  "on-error": function() {},
  resourceMetadata: service(),
  store: service(),
  router: service(),
  data: service('cardstack-data'),
  tools: service('cardstack-tools'),

  modelMeta: computed('model', function() {
    return this.get('resourceMetadata').read(this.get('model'));
  }),

  modelType: computed('model', function() {
    return modelType(this.get('model'));
  }),

  onMaster: computed('modelMeta.branch', function() {
    let branch = this.get('modelMeta').branch;
    return branch == null || branch === defaultBranch;
  }),

  upstreamMeta: computed('upstreamModel', function() {
    let upstream = this.get('upstreamModel');
    if (upstream) {
      return this.get('resourceMetadata').read(upstream);
    }
  }),

  fetchUpstreamModel: task(function * () {
    this.set('upstreamModel', null);
    if (this.get('onMaster')) {
      // Nothing to do, we're already on the default branch, so there
      // is no model more upstream than ours.
      return;
    }
    let model = this.get('model');
    let type = modelType(model);
    let id = model.get('id');
    if (id == null) {
      // Nothing to do, we don't have an id yet. It's vanishingly
      // unlikely that we're about to collide with something on
      // upstream anyway.
      return;
    }
    try {
      let upstreamModel = yield this.get('store').findRecord('cardstack-generic', `master/${type}/${id}`);
      this.set('upstreamModel', upstreamModel);
    } catch (err) {
      if (err.isAdapterError && err.errors && err.errors.length > 0 && err.errors[0].code === 404) {
        // There's no upstream model, that's OK.
        return;
      }
      throw err;
    }
  }).observes('modelMeta.branch', 'model.id').on('init'),

  // this describes the state of our model relative to its branch. So
  // "saved" here means it has been saved to its branch, etc.
  modificationState: computed('model.isNew', 'anythingDirty', function() {
    if (this.get('model.isNew')) {
      return "new";
    } else  if (this.get('anythingDirty')) {
      return "changed";
    } else {
      return "saved";
    }
  }),

  // this describes the state of our model relative to its value on
  // the default branch.
  upstreamState: computed('upstreamMeta.hash', 'modelMeta.hash', 'onMaster', 'fetchUpstreamModel.isRunning', function() {
    if (this.get('onMaster')) {
      return 'self';
    }

    if (this.get('fetchUpstreamModel.isRunning')) {
      return 'pending';
    }

    let upstreamMeta = this.get('upstreamMeta');
    if (!upstreamMeta) {
      return 'created';
    }

    let meta = this.get('modelMeta');
    if (meta.hash === upstreamMeta.hash) {
      return 'same';
    } else {
      return 'different';
    }

  }),

  title: computed('modificationState', 'upstreamState', function() {
    switch(this.get('modificationState')) {
    case 'new':
      return 'Drafted'
    case 'changed':
      return 'Changed';
    case 'saved':
      switch(this.get('upstreamState')) {
      case 'pending':
        return '...';
      case 'self':
        return 'Live';
      case 'created':
      case 'different':
      case 'same':
        return 'Preview';
      }
    }
  }),

  disabled: computed.equal('modificationState', 'saved'),

  currentState: computed('modificationState', 'upstreamState', function() {
    let modificationState = this.get('modificationState');
    let upstreamState = this.get('upstreamState');

    switch (modificationState) {
      case 'new':
        return 'draft'
      case 'changed':
        return 'edited';
      case 'saved':
        if (upstreamState === 'self') return 'published';
        else return 'saved';
      default:
        return;
    }
  }),

  // hasDirtyFields comes from the ember-data-relationship-tracker
  // addon, if it's available. It's fine if it's not since the value
  // will default to false, you just don't get relationship dirty tracking
  anythingDirty: or('model.{hasDirtyFields,hasDirtyOwned}'),

  anythingPending: or('model.isNew', 'anythingDirty'),

  update: task(function * () {
    let model = this.get('model');
    let errors = yield this.get('data').validate(model);
    if (Object.keys(errors).length > 0) {
      return this['on-error'](errors);
    }
    yield model.save();
  }).keepLatest(),

  cancel: task(function * () {
    this.get('tools').setEditing(false);

    if (this.get('anythingDirty')) {
      let model = this.get('model');

      model.rollbackAttributes();
      model.rollbackRelationships();

      if (model.dirtyTrackingRelationNames) {
        let relationNames = Object.keys(model.dirtyTrackingRelationNames);
        relationNames.forEach(relation => {
          let relationItems = model.get(relation);
          relationItems.forEach(item => {
            item.rollbackAttributes();
            item.rollbackRelationships();
          });
        });
      }
    }
  }),

  delete: task(function * () {
    yield this.get('model').destroyRecord();

    this.get('router').transitionTo('application');
  }),

  actions: {
    open() {
      this.set('opened', true);
    },
    close() {
      this.set('opened', false);
    }
  }
});

function animationRules() {
  this.transition(
    this.fromValue(false),
    this.toValue(true),
    this.use('to-down', { duration: 250 }),
    this.reverse('to-up', { duration: 250 })
  );
}
<commit_msg>Rollback attributes that are arrays<commit_after>import { inject as service } from '@ember/service';
import Component from '@ember/component';
import layout from '../templates/components/cs-version-control';
import { task } from 'ember-concurrency';
import { modelType } from '@cardstack/rendering/helpers/cs-model-type';
import { defaultBranch } from '@cardstack/plugin-utils/environment';
import { computed } from "@ember/object";
import { or } from '@ember/object/computed';

export default Component.extend({
  layout,
  tagName: '',
  opened: true,
  animationRules,
  "on-error": function() {},
  resourceMetadata: service(),
  store: service(),
  router: service(),
  data: service('cardstack-data'),
  tools: service('cardstack-tools'),

  modelMeta: computed('model', function() {
    return this.get('resourceMetadata').read(this.get('model'));
  }),

  modelType: computed('model', function() {
    return modelType(this.get('model'));
  }),

  onMaster: computed('modelMeta.branch', function() {
    let branch = this.get('modelMeta').branch;
    return branch == null || branch === defaultBranch;
  }),

  upstreamMeta: computed('upstreamModel', function() {
    let upstream = this.get('upstreamModel');
    if (upstream) {
      return this.get('resourceMetadata').read(upstream);
    }
  }),

  fetchUpstreamModel: task(function * () {
    this.set('upstreamModel', null);
    if (this.get('onMaster')) {
      // Nothing to do, we're already on the default branch, so there
      // is no model more upstream than ours.
      return;
    }
    let model = this.get('model');
    let type = modelType(model);
    let id = model.get('id');
    if (id == null) {
      // Nothing to do, we don't have an id yet. It's vanishingly
      // unlikely that we're about to collide with something on
      // upstream anyway.
      return;
    }
    try {
      let upstreamModel = yield this.get('store').findRecord('cardstack-generic', `master/${type}/${id}`);
      this.set('upstreamModel', upstreamModel);
    } catch (err) {
      if (err.isAdapterError && err.errors && err.errors.length > 0 && err.errors[0].code === 404) {
        // There's no upstream model, that's OK.
        return;
      }
      throw err;
    }
  }).observes('modelMeta.branch', 'model.id').on('init'),

  // this describes the state of our model relative to its branch. So
  // "saved" here means it has been saved to its branch, etc.
  modificationState: computed('model.isNew', 'anythingDirty', function() {
    if (this.get('model.isNew')) {
      return "new";
    } else  if (this.get('anythingDirty')) {
      return "changed";
    } else {
      return "saved";
    }
  }),

  // this describes the state of our model relative to its value on
  // the default branch.
  upstreamState: computed('upstreamMeta.hash', 'modelMeta.hash', 'onMaster', 'fetchUpstreamModel.isRunning', function() {
    if (this.get('onMaster')) {
      return 'self';
    }

    if (this.get('fetchUpstreamModel.isRunning')) {
      return 'pending';
    }

    let upstreamMeta = this.get('upstreamMeta');
    if (!upstreamMeta) {
      return 'created';
    }

    let meta = this.get('modelMeta');
    if (meta.hash === upstreamMeta.hash) {
      return 'same';
    } else {
      return 'different';
    }

  }),

  title: computed('modificationState', 'upstreamState', function() {
    switch(this.get('modificationState')) {
    case 'new':
      return 'Drafted'
    case 'changed':
      return 'Changed';
    case 'saved':
      switch(this.get('upstreamState')) {
      case 'pending':
        return '...';
      case 'self':
        return 'Live';
      case 'created':
      case 'different':
      case 'same':
        return 'Preview';
      }
    }
  }),

  disabled: computed.equal('modificationState', 'saved'),

  currentState: computed('modificationState', 'upstreamState', function() {
    let modificationState = this.get('modificationState');
    let upstreamState = this.get('upstreamState');

    switch (modificationState) {
      case 'new':
        return 'draft'
      case 'changed':
        return 'edited';
      case 'saved':
        if (upstreamState === 'self') return 'published';
        else return 'saved';
      default:
        return;
    }
  }),

  // hasDirtyFields comes from the ember-data-relationship-tracker
  // addon, if it's available. It's fine if it's not since the value
  // will default to false, you just don't get relationship dirty tracking
  anythingDirty: or('model.{hasDirtyFields,hasDirtyOwned}'),

  anythingPending: or('model.isNew', 'anythingDirty'),

  update: task(function * () {
    let model = this.get('model');
    let errors = yield this.get('data').validate(model);
    if (Object.keys(errors).length > 0) {
      return this['on-error'](errors);
    }
    yield model.save();
  }).keepLatest(),

  cancel: task(function * () {
    this.get('tools').setEditing(false);

    if (this.get('anythingDirty')) {
      let model = this.get('model');

      model.rollbackAttributes();
      model.rollbackRelationships();
      model.reload(); // this is to rollback attributes that are arrays

      if (model.dirtyTrackingRelationNames) {
        let relationNames = Object.keys(model.dirtyTrackingRelationNames);
        relationNames.forEach(relation => {
          let relationItems = model.get(relation);
          relationItems.forEach(item => {
            item.rollbackAttributes();
            item.rollbackRelationships();
          });
        });
      }
    }
  }),

  delete: task(function * () {
    yield this.get('model').destroyRecord();

    this.get('router').transitionTo('application');
  }),

  actions: {
    open() {
      this.set('opened', true);
    },
    close() {
      this.set('opened', false);
    }
  }
});

function animationRules() {
  this.transition(
    this.fromValue(false),
    this.toValue(true),
    this.use('to-down', { duration: 250 }),
    this.reverse('to-up', { duration: 250 })
  );
}
<|endoftext|>


<commit_before>$(function(){
  function PopupCenter(url, title, w, h) {
    // Fixes dual-screen position
    var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left;
    var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top;

    var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    var left = ((width / 2) - (w / 2)) + dualScreenLeft;
    var top = ((height / 2) - (h / 2)) + dualScreenTop;
    var newWindow = window.open(url, title, 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);

    // Puts focus on the newWindow
    if (window.focus) {
        newWindow.focus();
    }
  }

  var showModal = function() {
    $('.modal-wrapper').fadeIn();
    $('body').addClass('modal-open');
  };

  var hideModal = function() {
    $('.modal-wrapper').fadeOut();
    $('body').removeClass('modal-open');
  };

  var showTwitterPopup = function() {
    PopupCenter('twitter.html', 'twitter', 600, 500);
  };

  // toggle large audience checkbox
  $('input[name=volunteer]').click(function(e){
    var isChecked =  $(this).is(':checked');
    var $div = $('.action-comment');

    if (isChecked) {
      $div.show(100, function(){
        $div.find('input').focus();
      })
    }
    else {
      $div.slideUp(100);
    }
  });

  // submit form
  $('form').submit(function(e){
    e.preventDefault();

    var $form = $(this);
    var params = $form.serialize();
    console.log(params)
    $('.form-error').hide();
    $form.find('input').attr('disabled', 'disabled');

    var $button = $form.find('button')
    var buttonText = $button.text()
    $button.text('Saving...');

    $.post($form.attr('action'), params, function(response) {
      if (response.data) {
        showModal();
      }
      else {
        $('.form-error').show();
      }

      $form.find('input').removeAttr('disabled');
      $button.text(buttonText);
    });
  });

  // close modal
  $('.modal .close').click(function(e) {
    e.preventDefault();
    hideModal();
  });

  // twitter tool modals
  $('.twitter-modal').click(function(e){
    e.preventDefault();
    showTwitterPopup();
  });
  var loc = window.location.href;
  if (loc.indexOf('org=dp') != -1) {
    document.getElementById('fftf_disclosure').style.display = 'none';
    document.getElementById('fftf_form').style.display = 'none';
    document.getElementById('dp_disclosure').style.display = 'block';
    document.getElementById('dp_form').style.display = 'block';
    }
});<commit_msg>update app.js<commit_after>$(function(){
  function PopupCenter(url, title, w, h) {
    // Fixes dual-screen position
    var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left;
    var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top;

    var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    var left = ((width / 2) - (w / 2)) + dualScreenLeft;
    var top = ((height / 2) - (h / 2)) + dualScreenTop;
    var newWindow = window.open(url, title, 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);

    // Puts focus on the newWindow
    if (window.focus) {
        newWindow.focus();
    }
  }

  var showModal = function() {
    $('.modal-wrapper').fadeIn();
    $('body').addClass('modal-open');
  };

  var hideModal = function() {
    $('.modal-wrapper').fadeOut();
    $('body').removeClass('modal-open');
  };

  var showTwitterPopup = function() {
    PopupCenter('twitter.html', 'twitter', 600, 500);
  };

  // toggle large audience checkbox
  $('input[name=volunteer]').click(function(e){
    var isChecked =  $(this).is(':checked');
    var $div = $('.action-comment');

    if (isChecked) {
      $div.show(100, function(){
        $div.find('input').focus();
      })
    }
    else {
      $div.slideUp(100);
    }
  });

  // submit form
  $('form').submit(function(e){
    e.preventDefault();

    var $form = $(this);
    var params = $form.serialize();

    $('.form-error').hide();
    $form.find('input').attr('disabled', 'disabled');

    var $button = $form.find('button')
    var buttonText = $button.text()
    $button.text('Saving...');

    $.post($form.attr('action'), params, function(response) {
      if (response.data) {
        showModal();
      }
      else {
        $('.form-error').show();
      }

      $form.find('input').removeAttr('disabled');
      $button.text(buttonText);
    });
  });

  // close modal
  $('.modal .close').click(function(e) {
    e.preventDefault();
    hideModal();
  });

  // twitter tool modals
  $('.twitter-modal').click(function(e){
    e.preventDefault();
    showTwitterPopup();
  });
  var loc = window.location.href;
  if (loc.indexOf('org=dp') != -1) {
    document.getElementById('fftf_disclosure').style.display = 'none';
    document.getElementById('fftf_form').style.display = 'none';
    document.getElementById('dp_disclosure').style.display = 'block';
    document.getElementById('dp_form').style.display = 'block';
    }
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var convertFile = require('../src/icu-converter').convertFile;
var writer = require('../src/icu-converter').getWriter;

var program = require('commander');
var fs = require('fs');

program
  .version('0.0.1')
  .usage('[options] <file...>')
  .option('-f --format <format>', 'Select which format to use')
  .option('-e --encoding <encoding>', 'Specify the encoding of the resource bundle (defaults to utf-8)')
  .option('-o --output-dir <dir>', 'Directory to output converted files')
  .parse(process.argv)

program.args.forEach(function(fn) {
  console.log("Processing: " + fn);

  var jsObj = convertFile(fn, {encoding: program.encoding});
  var formatWriter = writer(program.format);

  formatWriter(jsObj, fn, program.outputDir);
});

<commit_msg>Handles the file extension instead of the writer Updated the version number<commit_after>#!/usr/bin/env node

var convertFile = require('../src/icu-converter').convertFile;
var writer = require('../src/icu-converter').getWriter;

var program = require('commander');
var fs = require('fs');
var path = require('path');

program
  .version('0.1.0-dev')
  .usage('[options] <file...>')
  .option('-f --format <format>', 'Select which format to use')
  .option('-e --encoding <encoding>', 'Specify the encoding of the resource bundle (defaults to utf-8)')
  .option('-o --output-dir <dir>', 'Directory to output converted files')
  .parse(process.argv)

program.args.forEach(function(fn) {
  console.log("Processing: " + fn);

  var jsObj = convertFile(fn, {encoding: program.encoding});
  var formatWriter = writer(program.format);

  var outputDir = program.outputDir;
  var fileExt = path.extname(fn);

  var outputFn = path.basename(fn).replace('.' + fileExt) + '.' + program.format
  var outputFile = outputDir + '/' + outputFn;
  console.log("Writing: " + outputFile);
  formatWriter(jsObj, outputFile);
});

<|endoftext|>


<commit_before>/*jshint node: true, -W106 */
'use strict';

/*
* Name : routesSpec.js
* Module : UnitTest
* Location : /test/presentationTier
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-19   Samuele Zanella    Initial code
* =========================================================
*/

var Routes = require('../../lib/presentationTier/routes.js');

var assert = require('assert');
var Express = require('express');
//var request = require('superagent');
var request = require('supertest');
//var http = require('http');

var app = new Express();

describe('Routes', function() {
    it('returns null when there are no params', function() {
        assert.strictEqual((new Routes()).hasOwnProperty('_app'), false);
    });

    it('returns null when there is a non-valid app in params', function() {
        assert.strictEqual((new Routes('wrong', '/namespace')).hasOwnProperty('_app'), false);
    });

    it('returns null when there is a non-valid namepace in params', function() {
        assert.strictEqual((new Routes(app, 123)).hasOwnProperty('_app'), false);
    });

    it('set param values to properties', function() {
        var routes1 = new Routes(app, '/namespace');
        //assert.strictEqual(routes1._app, );
        assert.strictEqual(routes1._norrisNamespace, '/namespace');
    });

    describe('#addRoutingPath', function(done) {
        var routes2 = new Routes(app, '/namespace');
        it('returns false if passed an invalid namespace', function() {
            assert.strictEqual(routes2.addRoutingPath(123, 'page'), false);
        });
        it('returns false if passed an invalid filename', function() {
            assert.strictEqual(routes2.addRoutingPath('/page', 123), false);
        });
        it('returns true if passed valid parameters', function() {
            assert.strictEqual(routes2.addRoutingPath('/page', 'page'), true);
        });
        it('behaves correctly if passed valid parameters', function(done) {
            var app2 = new Express();
            var routes3 = new Routes(app2, '/norris');
            routes3.addRoutingPath('/page', 'page');
            var server = app2.listen(3000);

            request(app2).get('/page').expect(200, done);

        });
    });
});<commit_msg>try to have 100% of coverage<commit_after>/*jshint node: true, -W106 */
'use strict';

/*
* Name : routesSpec.js
* Module : UnitTest
* Location : /test/presentationTier
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-19   Samuele Zanella    Initial code
* =========================================================
*/

var Routes = require('../../lib/presentationTier/routes.js');

var assert = require('assert');
var Express = require('express');
//var request = require('superagent');
var request = require('supertest');
//var http = require('http');

var app = new Express();

describe('Routes', function() {
    it('returns null when there are no params', function() {
        assert.strictEqual((new Routes()).hasOwnProperty('_app'), false);
    });

    it('returns null when there is a non-valid app in params', function() {
        assert.strictEqual((new Routes('wrong', '/namespace')).hasOwnProperty('_app'), false);
    });

    it('returns null when there is a non-valid namepace in params', function() {
        assert.strictEqual((new Routes(app, 123)).hasOwnProperty('_app'), false);
    });

    it('set param values to properties', function() {
        var routes1 = new Routes(app, '/namespace');
        //assert.strictEqual(routes1._app, );
        assert.strictEqual(routes1._norrisNamespace, '/namespace');
    });

    describe('#addRoutingPath', function(done) {
        var routes2 = new Routes(app, '/namespace');
        it('returns false if passed an invalid namespace', function() {
            assert.strictEqual(routes2.addRoutingPath(123, 'page'), false);
        });
        it('returns false if passed an invalid filename', function() {
            assert.strictEqual(routes2.addRoutingPath('/page', 123), false);
        });
        it('returns true if passed valid parameters', function() {
            assert.strictEqual(routes2.addRoutingPath('/page', 'page'), true);
        });
        it('behaves correctly if passed valid parameters', function(done) {
            var app2 = new Express();
            var routes3 = new Routes(app2, '/norris');
            routes3.addRoutingPath('/page', 'page');
            var server = app2.listen(3000);

            request(app2).get('/page/').expect(200, done);

        });
    });
});<|endoftext|>


<commit_before>/**
 * Throttle the network capabilities of the browser. This can help to
 * emulate certain scenarios where a user looses the internet connection
 * and your app needs to address that.
 *
 * <example>
    :throttle.js
    it('should throttle the network', () => {
        // via static string
        browser.throttle('Regular 3G')

        // via custom values
        browser.throttle({
            'offline': false,
            'downloadThroughput': 200 * 1024 / 8,
            'uploadThroughput': 200 * 1024 / 8,
            'latency': 20
        })
    });
 * </example>
 *
 * @alias browser.throttle
 * @param {ThrottleOptions} params  parameters for throttling
 * @type utility
 *
 */
import { getBrowserObject } from '../../utils'

const NETWORK_PRESETS = {
    'offline': {
        offline: true,
        downloadThroughput: 0,
        uploadThroughput: 0,
        latency: 1
    },
    'GPRS': {
        offline: false,
        downloadThroughput: 50 * 1024 / 8,
        uploadThroughput: 20 * 1024 / 8,
        latency: 500
    },
    'Regular2G': {
        offline: false,
        downloadThroughput: 250 * 1024 / 8,
        uploadThroughput: 50 * 1024 / 8,
        latency: 300
    },
    'Good2G': {
        offline: false,
        downloadThroughput: 450 * 1024 / 8,
        uploadThroughput: 150 * 1024 / 8,
        latency: 150
    },
    'Regular3G': {
        offline: false,
        downloadThroughput: 750 * 1024 / 8,
        uploadThroughput: 250 * 1024 / 8,
        latency: 100
    },
    'Good3G': {
        offline: false,
        downloadThroughput: 1.5 * 1024 * 1024 / 8,
        uploadThroughput: 750 * 1024 / 8,
        latency: 40
    },
    'Regular4G': {
        offline: false,
        downloadThroughput: 4 * 1024 * 1024 / 8,
        uploadThroughput: 3 * 1024 * 1024 / 8,
        latency: 20
    },
    'DSL': {
        offline: false,
        downloadThroughput: 2 * 1024 * 1024 / 8,
        uploadThroughput: 1 * 1024 * 1024 / 8,
        latency: 5
    },
    'WiFi': {
        offline: false,
        downloadThroughput: 30 * 1024 * 1024 / 8,
        uploadThroughput: 15 * 1024 * 1024 / 8,
        latency: 2
    },
    'online': {
        offline: false,
        latency: 0,
        downloadThroughput: -1,
        uploadThroughput: -1
    }
}
const NETWORK_PRESET_TYPES = Object.keys(NETWORK_PRESETS)

export default async function throttle (params) {
    if (
        /**
         * check string parameter
         */
        (typeof params !== 'string' || !NETWORK_PRESET_TYPES.includes(params)) &&
        /**
         * check object parameter
         */
        (typeof params !== 'object')
    ) {
        throw new Error(`Invalid parameter for "throttle". Expected it to be typeof object or one of the following values: ${NETWORK_PRESET_TYPES.join(', ')} but found "${params}"`)
    }

    /**
     * use WebDriver extension if connected with cloud service
     */
    if (this.isSauce) {
        const browser = getBrowserObject(this)
        await browser.throttleNetwork(params)
        return null
    }

    // Connect to Chrome DevTools
    await this.getPuppeteer()
    const pages = await this.puppeteer.pages()
    const client = await pages[0].target().createCDPSession()

    // Set throttling property
    await client.send(
        'Network.emulateNetworkConditions',
        typeof params === 'string'
            ? NETWORK_PRESETS[params]
            : params
    )

    return null
}
<commit_msg>Update browser.throttle documentation (#5638)<commit_after>/**
 * Throttle the network capabilities of the browser. This can help to
 * emulate certain scenarios where a user loses their internet connection
 * and your app needs to address that.
 *
 * There are many presets available with default configurations for ease of use.
 * They are `offline`, `GPRS`, `Regular2G`, `Good2G`, `Regular3G`, `Good3G`,
 * `Regular4G`, `DSL`, `WiFi`, `online`.
 *
 * You can see the values for these presets [in the source code](https://github.com/webdriverio/webdriverio/blob/6824e4eb118a8d20685f12f4bc42f13fd56f8a25/packages/webdriverio/src/commands/browser/throttle.js#L29).
 *
 * <example>
    :throttle.js
    it('should throttle the network', () => {
        // via static string preset
        browser.throttle('Regular 3G')

        // via custom values
        browser.throttle({
            'offline': false,
            'downloadThroughput': 200 * 1024 / 8,
            'uploadThroughput': 200 * 1024 / 8,
            'latency': 20
        })
    });
 * </example>
 *
 * @alias browser.throttle
 * @param {ThrottleOptions} params  parameters for throttling
 * @param {Boolean}        params.offline              True to emulate internet disconnection.
 * @param {Number}         params.latency              Minimum latency from request sent to response headers received (ms).
 * @param {Number}         params.downloadThroughput   Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.
 * @param {Number}         params.uploadThroughput     Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.
 * @type utility
 *
 */
import { getBrowserObject } from '../../utils'

const NETWORK_PRESETS = {
    'offline': {
        offline: true,
        downloadThroughput: 0,
        uploadThroughput: 0,
        latency: 1
    },
    'GPRS': {
        offline: false,
        downloadThroughput: 50 * 1024 / 8,
        uploadThroughput: 20 * 1024 / 8,
        latency: 500
    },
    'Regular2G': {
        offline: false,
        downloadThroughput: 250 * 1024 / 8,
        uploadThroughput: 50 * 1024 / 8,
        latency: 300
    },
    'Good2G': {
        offline: false,
        downloadThroughput: 450 * 1024 / 8,
        uploadThroughput: 150 * 1024 / 8,
        latency: 150
    },
    'Regular3G': {
        offline: false,
        downloadThroughput: 750 * 1024 / 8,
        uploadThroughput: 250 * 1024 / 8,
        latency: 100
    },
    'Good3G': {
        offline: false,
        downloadThroughput: 1.5 * 1024 * 1024 / 8,
        uploadThroughput: 750 * 1024 / 8,
        latency: 40
    },
    'Regular4G': {
        offline: false,
        downloadThroughput: 4 * 1024 * 1024 / 8,
        uploadThroughput: 3 * 1024 * 1024 / 8,
        latency: 20
    },
    'DSL': {
        offline: false,
        downloadThroughput: 2 * 1024 * 1024 / 8,
        uploadThroughput: 1 * 1024 * 1024 / 8,
        latency: 5
    },
    'WiFi': {
        offline: false,
        downloadThroughput: 30 * 1024 * 1024 / 8,
        uploadThroughput: 15 * 1024 * 1024 / 8,
        latency: 2
    },
    'online': {
        offline: false,
        latency: 0,
        downloadThroughput: -1,
        uploadThroughput: -1
    }
}
const NETWORK_PRESET_TYPES = Object.keys(NETWORK_PRESETS)

export default async function throttle (params) {
    if (
        /**
         * check string parameter
         */
        (typeof params !== 'string' || !NETWORK_PRESET_TYPES.includes(params)) &&
        /**
         * check object parameter
         */
        (typeof params !== 'object')
    ) {
        throw new Error(`Invalid parameter for "throttle". Expected it to be typeof object or one of the following values: ${NETWORK_PRESET_TYPES.join(', ')} but found "${params}"`)
    }

    /**
     * use WebDriver extension if connected with cloud service
     */
    if (this.isSauce) {
        const browser = getBrowserObject(this)
        await browser.throttleNetwork(params)
        return null
    }

    // Connect to Chrome DevTools
    await this.getPuppeteer()
    const pages = await this.puppeteer.pages()
    const client = await pages[0].target().createCDPSession()

    // Set throttling property
    await client.send(
        'Network.emulateNetworkConditions',
        typeof params === 'string'
            ? NETWORK_PRESETS[params]
            : params
    )

    return null
}
<|endoftext|>


<commit_before>fdescribe('The atlas-scrollable-content directive', function () {
    var $compile,
        $rootScope;

    beforeEach(function () {
        angular.mock.module('atlas');

        angular.mock.inject(function (_$compile_, _$rootScope_) {
            $compile = _$compile_;
            $rootScope = _$rootScope_;
        });
    });

    function getDirective (visibility, pageName) {
        var directive,
            element,
            scope,
            i,
            paragraph;

        element = document.createElement('div');
        element.setAttribute('atlas-scrollable-content', '');
        element.setAttribute('visibility', 'visibility');
        element.setAttribute('page-name', pageName || '');
        element.setAttribute('style', 'height: 100px; overflow-y: scroll;');

        //Insert a lot of dummy content to enable scrolling
        for (i = 0; i < 100; i++) {
            paragraph = document.createElement('p');
            paragraph.innerText = 'I am a paragraph.';

            element.appendChild(paragraph);
        }

        scope = $rootScope.$new();
        scope.visibility = visibility;

        directive = $compile(element)(scope);
        scope.$apply();

        document.body.appendChild(element);

        return directive;
    }

    it('resets the scrollTop property whenever the active component changes', function () {
        var directive,
            visibility,
            pageName;

        visibility = {
            page: false,
            detail: true,
            searchResults: false,
            dataSelection: false
        };

        directive = getDirective(visibility, pageName);
        expect(directive[0].scrollTop).toBe(0);

        //Now scroll down
        directive[0].scrollTop = 100;

        //Show another component
        visibility.detail = false;
        visibility.page = true;
        pageName = 'home';
        $rootScope.$apply();

        //Make sure the scrollTop has been reset
        expect(directive[0].scrollTop).toBe(0);
    });
});<commit_msg>tg-1635 tests now succesful<commit_after>fdescribe('The atlas-scrollable-content directive', function () {
    var $compile,
        $rootScope;

    beforeEach(function () {
        angular.mock.module('atlas');

        angular.mock.inject(function (_$compile_, _$rootScope_) {
            $compile = _$compile_;
            $rootScope = _$rootScope_;
        });
    });

    function getDirective (visibility, pageName) {
        var directive,
            element,
            scope,
            i,
            paragraph;

        element = document.createElement('div');
        element.setAttribute('atlas-scrollable-content', '');
        element.setAttribute('visibility', 'visibility');
        element.setAttribute('page-name', pageName || '');
        element.setAttribute('style', 'height: 100px; overflow-y: scroll;');

        //Insert a lot of dummy content to enable scrolling
        for (i = 0; i < 100; i++) {
            paragraph = document.createElement('p');
            paragraph.innerText = 'I am a paragraph.';

            element.appendChild(paragraph);
        }

        scope = $rootScope.$new();
        scope.visibility = visibility;

        directive = $compile(element)(scope);
        scope.$apply();

        document.body.appendChild(element);

        return directive;
    }

    it('resets the scrollTop property whenever the active component changes', function () {
        var directive,
            scope,
            visibility,
            pageName;

        visibility = {
            page: false,
            detail: true,
            searchResults: false,
            dataSelection: false
        };

        directive = getDirective(visibility, pageName);
        expect(directive[0].scrollTop).toBe(0);

        //Now scroll down
        directive[0].scrollTop = 100;

        //Show another component
        scope = directive.isolateScope();
        scope.visibility.detail = false;
        scope.visibility.page = true;
        scope.pageName = 'home';
        scope.$apply();

        //Make sure the scrollTop has been reset
        expect(directive[0].scrollTop).toBe(0);
    });
});<|endoftext|>


<commit_before>import 'babel-polyfill';
import React from 'react';
import App from './containers/App';
import Navbar from './components/Navbar';
import ProjectMenu from './components/ProjectMenu';
import SubjectSelect  from './components/SubjectSelect';
import SubjectView  from './components/SubjectView';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute, Link, browserHistory } from 'react-router';
import { render } from 'react-dom';
import configureStore from './store/configureStore';
import injectTapEventPlugin from 'react-tap-event-plugin';

injectTapEventPlugin();

const store = configureStore(window.__INITIAL_STATE__);

// Very manually constraining this to the root path until we establish proper
// routing and views. This allows us to bounce out of the single page app paradigm
// and into existing ehb-datasource url paths
if (window.location.pathname == '/') {
  render(
    <Provider store={store}>
      <Router history={browserHistory}>
        <Route path='/' component={App}>
          <IndexRoute component={ProjectMenu} />
          <Route path="dataentry/protocol/:id" component={SubjectSelect}/>
          <Route
            path="dataentry/protocol/:prot_id/subject/:sub_id(/:edit)"
            component={SubjectView}
          />
        </Route>
      </Router>
    </Provider>,
    document.getElementById('react')
  );
} else {
  render(
    <Provider store={store}>
      <Navbar />
    </Provider>,
  document.getElementById('react'))
}
<commit_msg>eslint embark index<commit_after>import 'babel-polyfill';
import React from 'react';
import App from './containers/App';
import Navbar from './components/Navbar';
import ProjectMenu from './components/ProjectMenu';
import SubjectSelect from './components/SubjectSelect';
import SubjectView from './components/SubjectView';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import { render } from 'react-dom';
import configureStore from './store/configureStore';
import injectTapEventPlugin from 'react-tap-event-plugin';

injectTapEventPlugin();

/* eslint-disable no-underscore-dangle*/
const store = configureStore(window.__INITIAL_STATE__);

// Very manually constraining this to the root path until we establish proper
// routing and views. This allows us to bounce out of the single page app paradigm
// and into existing ehb-datasource url paths
if (window.location.pathname === '/') {
  render(
    <Provider store={store}>
      <Router history={browserHistory}>
        <Route path="/" component={App}>
          <IndexRoute component={ProjectMenu} />
          <Route path="dataentry/protocol/:id" component={SubjectSelect} />
          <Route
            path="dataentry/protocol/:prot_id/subject/:sub_id(/:edit)"
            component={SubjectView}
          />
        </Route>
      </Router>
    </Provider>,
    document.getElementById('react')
  );
} else {
  render(
    <Provider store={store}>
      <Navbar />
    </Provider>,
    document.getElementById('react'));
}
<|endoftext|>