<commit_before>/**
 * @module timed
 * @submodule timed-services
 * @public
 */
import Ember            from 'ember'
import Service          from 'ember-service'
import service          from 'ember-service/inject'
import moment           from 'moment'
import formatDuration   from 'timed/utils/format-duration'
import getOwner         from 'ember-owner/get'
import { scheduleOnce } from 'ember-runloop'

import computed, {
  observes
} from 'ember-computed-decorators'

import {
  camelize,
  capitalize
} from 'ember-string'

import {
  task,
  timeout
} from 'ember-concurrency'

const { testing } = Ember

/**
 * Tracking service
 *
 * This contains some methods, the application needs on multiple routes
 *
 * @class TrackingService
 * @extends Ember.Service
 * @public
 */
export default Service.extend({
  /**
   * The store service
   *
   * @property {Ember.Store} store
   * @public
   */
  store: service('store'),

  /**
   * The notify service
   *
   * @property {EmberNotify.NotifyService} notify
   * @public
   */
  notify: service('notify'),

  /**
   * Init hook, get the current activity
   *
   * @method init
   * @public
   */
  async init() {
    this._super()

    let actives = await this.get('store').query('activity', {
      include: 'blocks,task,task.project,task.project.customer',
      active: true
    })

    this.set('activity', actives.getWithDefault('firstObject', null))

    this.get('_computeTitle').perform()
  },

  /**
   * The application
   *
   * @property {Ember.Application} application
   * @public
   */
  @computed
  application() {
    return getOwner(this).lookup('application:main')
  },

  /**
   * The default application title
   *
   * @property {String} title
   * @public
   */
  @computed('application.name')
  title(name) {
    return capitalize(camelize(name || 'Timed'))
  },

  /**
   * Trigger a reload of the title because the activity has changed
   *
   * @method _triggerTitle
   * @private
   */
  @observes('activity.active')
  _triggerTitle() {
    if (this.get('activity.active')) {
      this.get('_computeTitle').perform()
    }
    else {
      this.setTitle(this.get('title'))
    }
  },

  /**
   * Set the doctitle
   *
   * @method setTitle
   * @param {String} title The title to set
   * @public
   */
  setTitle(title) {
    scheduleOnce('afterRender', this, (t) => {
      document.title = t
    }, title)
  },

  /**
   * Set the title of the application to show the current tracking time and
   * task
   *
   * @method _computeTitle
   * @private
   */
  _computeTitle: task(function* () {
    while (this.get('activity.active')) {
      let elapsed  = this.get('activity.duration') || moment.duration()
      let duration = moment.duration(moment().diff(this.get('activity.activeBlock.from')))

      let full = moment.duration(elapsed).add(duration)

      let task = ''

      if (this.get('activity.task.content')) {
        let c = this.get('activity.task.project.customer.name')
        let p = this.get('activity.task.project.name')
        let t = this.get('activity.task.name')

        task = `${c} > ${p} > ${t}`
      }
      else {
        task = 'Unknown Task'
      }

      this.setTitle(`${formatDuration(full)} (${task})`)

      if (testing) {
        return
      }

      yield timeout(1000)
    }
  }),

  /**
   * Filter all customers
   *
   * @property {EmberConcurrency.Task} filterCustomers
   * @public
   */
  filterCustomers: task(function* () {
    yield timeout(500)

    return yield this.get('store').query('customer', {})
  }).restartable(),

  /**
   * Filter all projects by customer
   *
   * @property {EmberConcurrency.Task} filterProjects
   * @public
   */
  filterProjects: task(function* (customer) {
    if (!customer) {
      throw new Error('No customer selected')
    }

    yield timeout(500)

    return yield this.get('store').query('project', { customer })
  }).restartable(),

  /**
   * Filter all tasks by project
   *
   * @property {EmberConcurrency.Task} filterTask
   * @public
   */
  filterTasks: task(function* (project) {
    if (!project) {
      throw new Error('No project selected')
    }

    yield timeout(500)

    return yield this.get('store').query('task', { project })
  }).restartable(),

  /**
   * The current activity
   *
   * @property {Activity} currentActivity
   * @public
   */
  _activity: null,

  /**
   * The currenty activity or create a new one if none is set
   *
   * @property {Activity} activity
   * @public
   */
  @computed
  activity: {
    get() {
      return this.get('_activity')
    },
    set(key, value) {
      let newActivity = value || this.get('store').createRecord('activity')

      this.set('_activity', newActivity)

      return newActivity
    }
  },

  /**
   * Start the activity
   *
   * @method startActivity
   * @public
   */
  startActivity: task(function* () {
    let activity = this.get('activity')

    if (activity.get('active')) {
      return
    }

    try {
      if (activity.get('isNew')) {
        yield activity.save()
      }

      let block = this.get('store').createRecord('activity-block', { activity })

      yield block.save()

      this.get('notify').success('Activity was started')
    }
    catch(e) {
      /* istanbul ignore next */
      this.get('notify').error('Error while starting the activity')
    }
  }).drop(),

  /**
   * Stop the activity
   *
   * @method stopActivity
   * @public
   */
  stopActivity: task(function* () {
    let activity = this.get('activity')

    if (!activity.get('active')) {
      return
    }

    try {
      let block = yield activity.get('activeBlock')

      if (block) {
        block.set('to', moment())

        yield block.save()
      }

      this.set('activity', null)

      this.get('notify').success('Activity was stopped')
    }
    catch(e) {
      /* istanbul ignore next */
      this.get('notify').error('Error while stopping the activity')
    }
  }).drop()
})
<commit_msg>Set task to 'Unknown Task' per default to save an else statement<commit_after>/**
 * @module timed
 * @submodule timed-services
 * @public
 */
import Ember            from 'ember'
import Service          from 'ember-service'
import service          from 'ember-service/inject'
import moment           from 'moment'
import formatDuration   from 'timed/utils/format-duration'
import getOwner         from 'ember-owner/get'
import { scheduleOnce } from 'ember-runloop'

import computed, {
  observes
} from 'ember-computed-decorators'

import {
  camelize,
  capitalize
} from 'ember-string'

import {
  task,
  timeout
} from 'ember-concurrency'

const { testing } = Ember

/**
 * Tracking service
 *
 * This contains some methods, the application needs on multiple routes
 *
 * @class TrackingService
 * @extends Ember.Service
 * @public
 */
export default Service.extend({
  /**
   * The store service
   *
   * @property {Ember.Store} store
   * @public
   */
  store: service('store'),

  /**
   * The notify service
   *
   * @property {EmberNotify.NotifyService} notify
   * @public
   */
  notify: service('notify'),

  /**
   * Init hook, get the current activity
   *
   * @method init
   * @public
   */
  async init() {
    this._super()

    let actives = await this.get('store').query('activity', {
      include: 'blocks,task,task.project,task.project.customer',
      active: true
    })

    this.set('activity', actives.getWithDefault('firstObject', null))

    this.get('_computeTitle').perform()
  },

  /**
   * The application
   *
   * @property {Ember.Application} application
   * @public
   */
  @computed
  application() {
    return getOwner(this).lookup('application:main')
  },

  /**
   * The default application title
   *
   * @property {String} title
   * @public
   */
  @computed('application.name')
  title(name) {
    return capitalize(camelize(name || 'Timed'))
  },

  /**
   * Trigger a reload of the title because the activity has changed
   *
   * @method _triggerTitle
   * @private
   */
  @observes('activity.active')
  _triggerTitle() {
    if (this.get('activity.active')) {
      this.get('_computeTitle').perform()
    }
    else {
      this.setTitle(this.get('title'))
    }
  },

  /**
   * Set the doctitle
   *
   * @method setTitle
   * @param {String} title The title to set
   * @public
   */
  setTitle(title) {
    scheduleOnce('afterRender', this, (t) => {
      document.title = t
    }, title)
  },

  /**
   * Set the title of the application to show the current tracking time and
   * task
   *
   * @method _computeTitle
   * @private
   */
  _computeTitle: task(function* () {
    while (this.get('activity.active')) {
      let elapsed  = this.get('activity.duration') || moment.duration()
      let duration = moment.duration(moment().diff(this.get('activity.activeBlock.from')))

      let full = moment.duration(elapsed).add(duration)

      let task = 'Unknown Task'

      if (this.get('activity.task.content')) {
        let c = this.get('activity.task.project.customer.name')
        let p = this.get('activity.task.project.name')
        let t = this.get('activity.task.name')

        task = `${c} > ${p} > ${t}`
      }

      this.setTitle(`${formatDuration(full)} (${task})`)

      if (testing) {
        return
      }

      yield timeout(1000)
    }
  }),

  /**
   * Filter all customers
   *
   * @property {EmberConcurrency.Task} filterCustomers
   * @public
   */
  filterCustomers: task(function* () {
    yield timeout(500)

    return yield this.get('store').query('customer', {})
  }).restartable(),

  /**
   * Filter all projects by customer
   *
   * @property {EmberConcurrency.Task} filterProjects
   * @public
   */
  filterProjects: task(function* (customer) {
    if (!customer) {
      throw new Error('No customer selected')
    }

    yield timeout(500)

    return yield this.get('store').query('project', { customer })
  }).restartable(),

  /**
   * Filter all tasks by project
   *
   * @property {EmberConcurrency.Task} filterTask
   * @public
   */
  filterTasks: task(function* (project) {
    if (!project) {
      throw new Error('No project selected')
    }

    yield timeout(500)

    return yield this.get('store').query('task', { project })
  }).restartable(),

  /**
   * The current activity
   *
   * @property {Activity} currentActivity
   * @public
   */
  _activity: null,

  /**
   * The currenty activity or create a new one if none is set
   *
   * @property {Activity} activity
   * @public
   */
  @computed
  activity: {
    get() {
      return this.get('_activity')
    },
    set(key, value) {
      let newActivity = value || this.get('store').createRecord('activity')

      this.set('_activity', newActivity)

      return newActivity
    }
  },

  /**
   * Start the activity
   *
   * @method startActivity
   * @public
   */
  startActivity: task(function* () {
    let activity = this.get('activity')

    if (activity.get('active')) {
      return
    }

    try {
      if (activity.get('isNew')) {
        yield activity.save()
      }

      let block = this.get('store').createRecord('activity-block', { activity })

      yield block.save()

      this.get('notify').success('Activity was started')
    }
    catch(e) {
      /* istanbul ignore next */
      this.get('notify').error('Error while starting the activity')
    }
  }).drop(),

  /**
   * Stop the activity
   *
   * @method stopActivity
   * @public
   */
  stopActivity: task(function* () {
    let activity = this.get('activity')

    if (!activity.get('active')) {
      return
    }

    try {
      let block = yield activity.get('activeBlock')

      if (block) {
        block.set('to', moment())

        yield block.save()
      }

      this.set('activity', null)

      this.get('notify').success('Activity was stopped')
    }
    catch(e) {
      /* istanbul ignore next */
      this.get('notify').error('Error while stopping the activity')
    }
  }).drop()
})
<|endoftext|>


<commit_before>import { parse } from 'papaparse'
import {
    allPass, compose, filter, find, findLast, flatten, forEach,
    fromPairs, identity, join, map, complement, drop,
    takeWhile, times, sortBy, test, without, zip,
} from 'ramda'

const clean = compose(filter(identity), flatten)

const dataRegexp = test(/^(\d{4}|Year)/)

function isData (row) {
    return !!find(dataRegexp, row)
}

function getRows (csv) {
    const parsed = parse(csv, {
        dynamicTyping: false,
        header: false,
    })

    return parsed.data
}

function splitHeaders (rows) {
    const header = takeWhile(complement(isData), rows)
    const content = takeWhile(isData, drop(header.length, rows))
    const footer = drop(header.length + content.length, rows)

    return {
        content,
        header: clean(header),
        footer: clean(footer),
    }
}

function transposeObj (rows, columns) {
    const data = fromPairs(zip(columns, times(() => { return {} }, columns.length)))

    forEach((row) => {
        forEach((column) => {
            data[column][parseInt(row.Year)] = row[column]
        }, columns)
    }, rows)

    return data
}

export function cleanup (rawData) {
    const { header, content, footer } = splitHeaders(getRows(rawData))
    const text = join('\n', map(join('\t'), content))

    // Reparse data rows with dynamic typing
    const reparsed = parse(text, {
        header: true,
        dynamicTyping: true,
    })
    const excludedSeries = [
        'Year',
        'Imports',
        'Exports',
        'Stocks',
        'Unit value ($/t)',
        'Unit value (98$/t)',
    ] // TODO Move filtering elsewhere
    const series = without(excludedSeries, reparsed.meta.fields)

    if (reparsed.errors.length > 0) {
        console.error('Errors while parsing raw data:', reparsed.errors)
    }

    const columns = transposeObj(reparsed.data, series)

    return Object.assign(reparsed, { header, footer, series, columns })
}

export function productionSeries (series) {
    const production = test(/^(World production|World mine production)/)
    const estimated = test(/estimated/)
    return findLast(
        allPass([production, complement(estimated)]),
        sortBy(identity, series)
    )
}
<commit_msg>Also exclude interpolated series on productionSeries<commit_after>import { parse } from 'papaparse'
import {
    allPass, compose, filter, find, findLast, flatten, forEach,
    fromPairs, identity, join, map, complement, drop,
    takeWhile, times, sortBy, test, without, zip,
} from 'ramda'

const clean = compose(filter(identity), flatten)

const dataRegexp = test(/^(\d{4}|Year)/)

function isData (row) {
    return !!find(dataRegexp, row)
}

function getRows (csv) {
    const parsed = parse(csv, {
        dynamicTyping: false,
        header: false,
    })

    return parsed.data
}

function splitHeaders (rows) {
    const header = takeWhile(complement(isData), rows)
    const content = takeWhile(isData, drop(header.length, rows))
    const footer = drop(header.length + content.length, rows)

    return {
        content,
        header: clean(header),
        footer: clean(footer),
    }
}

function transposeObj (rows, columns) {
    const data = fromPairs(zip(columns, times(() => { return {} }, columns.length)))

    forEach((row) => {
        forEach((column) => {
            data[column][parseInt(row.Year)] = row[column]
        }, columns)
    }, rows)

    return data
}

export function cleanup (rawData) {
    const { header, content, footer } = splitHeaders(getRows(rawData))
    const text = join('\n', map(join('\t'), content))

    // Reparse data rows with dynamic typing
    const reparsed = parse(text, {
        header: true,
        dynamicTyping: true,
    })
    const excludedSeries = [
        'Year',
        'Imports',
        'Exports',
        'Stocks',
        'Unit value ($/t)',
        'Unit value (98$/t)',
    ] // TODO Move filtering elsewhere
    const series = without(excludedSeries, reparsed.meta.fields)

    if (reparsed.errors.length > 0) {
        console.error('Errors while parsing raw data:', reparsed.errors)
    }

    const columns = transposeObj(reparsed.data, series)

    return Object.assign(reparsed, { header, footer, series, columns })
}

export function productionSeries (series) {
    const production = test(/^(World production|World mine production)/)
    const estimated = test(/\((estimated|interpolated)\)$/)
    const selected = findLast(
        allPass([production, complement(estimated)]),
        sortBy(identity, series)
    )

    return selected
}
<|endoftext|>


<commit_before>import { h, Component } from 'preact/preact';
import CoreButton		from 'com/core-button/button';
import SVGIcon 			from 'com/svg-icon/icon';
import NavLink 			from 'com/nav-link/link';

export default class ContentPost extends Component {
	render(props,state) {
		props.title = (props.post && props.post.title) ? props.post.title : props.title;
		props.user = props.user ? props.user : {};

		var hasTwitter = props.user.twitter ?  (<SVGIcon baseline small>twitter</SVGIcon>/{props.user.twitter}) : ;
		var hasTeam = props.user.team ?  of {props.user.team} <SVGIcon>users</SVGIcon> : ;

		// Build URL //
		// TODO: append trailing '/' to base if missing
		var url = props.slug+'/';
		// TODO: if single post mode, prefix with '../'

//		function parseNames( str ) {
//			// Dummy: Use Global Object //
//			var users = {
//				'pov': {
//					name:'PoV',
//					slug:'pov',
//					avatar:'/other/logo/mike/Chicken64.png',
//					twitter:'mikekasprzak',
//				}
//			};
//
//			return str.replace(/@([A-Za-z][A-Za-z0-9-]*)/g,function(original,p1,offset,s) {
//				//console.log(match,p1,offset);
//				var name = p1.toLowerCase();
//				if ( users[name] ) {
//					return ""+users[name].name+"";
//				}
//				else {
//					return original;
//				}
//			});
//
//			// TODO: attach the Navigation link code to the  tag above //
//		}

		var parsedBody = marked.parse(props.body);
		var dangerParsedBody = { __html:parsedBody };

		var avatar = props.user.avatar ? "//"+STATIC_DOMAIN+props.user.avatar : "";

		return (

<NavLink href={url}>{props.title}</NavLink>

						Posted {props.relative_time} ago
						on {props.short_date},
						by <NavLink href={'/u/'+props.user.slug+'/'} class="-author">{props.user.name}</NavLink>
						{hasTwitter}
						{hasTeam}

<SVGIcon>arrow-up</SVGIcon>

<SVGIcon>wedge-left</SVGIcon>

<SVGIcon>wedge-right</SVGIcon>

<SVGIcon>heart-check</SVGIcon>

0

<SVGIcon>wedge-right</SVGIcon>

<SVGIcon>bubble-empty</SVGIcon>

0

<SVGIcon>cog</SVGIcon>

		);
	}
	// body: unmagin-top, unmargin-bottom. replace with selector
//
<SVGIcon>wedge-right</SVGIcon>

	componentDidMount() {
	}
	componentWillUnmount() {
	}
}
<commit_msg>nice, now showing @name when you hover over an @name (i.e. title)<commit_after>import { h, Component } from 'preact/preact';
import CoreButton		from 'com/core-button/button';
import SVGIcon 			from 'com/svg-icon/icon';
import NavLink 			from 'com/nav-link/link';

export default class ContentPost extends Component {
	render(props,state) {
		props.title = (props.post && props.post.title) ? props.post.title : props.title;
		props.user = props.user ? props.user : {};

		var hasTwitter = props.user.twitter ?  (<SVGIcon baseline small>twitter</SVGIcon>/{props.user.twitter}) : ;
		var hasTeam = props.user.team ?  of {props.user.team} <SVGIcon>users</SVGIcon> : ;

		// Build URL //
		// TODO: append trailing '/' to base if missing
		var url = props.slug+'/';
		// TODO: if single post mode, prefix with '../'

//		function parseNames( str ) {
//			// Dummy: Use Global Object //
//			var users = {
//				'pov': {
//					name:'PoV',
//					slug:'pov',
//					avatar:'/other/logo/mike/Chicken64.png',
//					twitter:'mikekasprzak',
//				}
//			};
//
//			return str.replace(/@([A-Za-z][A-Za-z0-9-]*)/g,function(original,p1,offset,s) {
//				//console.log(match,p1,offset);
//				var name = p1.toLowerCase();
//				if ( users[name] ) {
//					return ""+users[name].name+"";
//				}
//				else {
//					return original;
//				}
//			});
//
//			// TODO: attach the Navigation link code to the  tag above //
//		}

		var parsedBody = marked.parse(props.body);
		var dangerParsedBody = { __html:parsedBody };

		var avatar = props.user.avatar ? "//"+STATIC_DOMAIN+props.user.avatar : "";

		return (

<NavLink href={url}>{props.title}</NavLink>

						Posted {props.relative_time} ago
						on {props.short_date},
						by <NavLink href={'/u/'+props.user.slug+'/'} class="-author" title={'@'+props.user.slug}>{props.user.name}</NavLink>
						{hasTwitter}
						{hasTeam}

<SVGIcon>arrow-up</SVGIcon>

<SVGIcon>wedge-left</SVGIcon>

<SVGIcon>wedge-right</SVGIcon>

<SVGIcon>heart-check</SVGIcon>

0

<SVGIcon>wedge-right</SVGIcon>

<SVGIcon>bubble-empty</SVGIcon>

0

<SVGIcon>cog</SVGIcon>

		);
	}
	// body: unmagin-top, unmargin-bottom. replace with selector
//
<SVGIcon>wedge-right</SVGIcon>

	componentDidMount() {
	}
	componentWillUnmount() {
	}
}
<|endoftext|>


<commit_before>/*global moment:false*/

(function(){
	var banner = $('#nodeunit-banner');
	var tests = $('#nodeunit-tests');
	var headerRow = $("#header-row");

	var start = moment();
	var passed = 0;
	var failed = 0;
	var total = 0;
	var currentTestModule;
	var currentModuleEl;

	function updateTest(_passed, _failed) {
		passed += _passed;
		failed += _failed;
		updateTotals(passed, failed);
	}

	function updateTotals(_passed, _failed) {
		if (_failed) {
			banner.addClass('has-failed');
		}
		banner.html('' + _passed + ' tests passed
' +
                        '' + _failed + ' failed');
	}

	(function() {
		var queryArgs = {}, query = window.location.search, pieces, i, key_val,
			filtered, suite, test;
		if (!query) { return; }
		if (query[query.length - 1] === '/') {
			query = query.slice(0, query.length - 1);
		}
		pieces = query.slice(1).split('&');
		for (i = 0; i < pieces.length; ++i) {
			key_val = pieces[i].split('=');
			queryArgs[decodeURIComponent(key_val[0])] = decodeURIComponent(key_val[1]);
		}
		if (queryArgs.suite !== undefined) {
			filtered = {};
			for (suite in exports) {
				if (suite.match(queryArgs.suite)) {
					filtered[suite] = exports[suite];
				}
			}
			exports = filtered;
		}
		if (queryArgs.test !== undefined) {
			for (suite in exports) {
				filtered = {};
				for (test in exports[suite]) {
					if (test === 'setUp' || test === 'tearDown' || test.match(queryArgs.test)) {
						filtered[test] = exports[suite][test];
					}
				}
				exports[suite] = filtered;
			}
		}
	}());

        QUnit.moduleStart(function (module) {
            var name = module.name;
            currentTestModule = name;
            currentModuleEl = $('
').addClass('tests-module');
            currentModuleEl.append('
' + name + '
');
            tests.append(currentModuleEl);
        });

        var assertions;
        var failedAssertions = []
        QUnit.testStart(function (test) {
            assertions = [];
        });

        QUnit.log(function (assertion) {
            assertions.push(assertion);
        });

        QUnit.testDone(function (test) {
            var name = test.name;
            var testEl = $('
').addClass('tests-test'),
                    testHtml = '',
                    assertUl = $('
').addClass('tests-asserts'),
                    assertLi,
                    assertHtml = '',
                    assert;

            total++;

            // each test
            testHtml += '
' + name + ' ';
            if (test.failed > 0) {
                    testEl.addClass('has-failed is-open');
                    testHtml += test.passed + ' passed : ';
                    testHtml += test.failed + ' failed
';
            } else {
                    testHtml += 'all ' + test.passed + ' passed
';
            }
            testEl.html(testHtml);

            // each assert
            for (var i = 0; i < assertions.length; i++) {
                    assert = assertions[i];
                    assert.uid = total + '.' + (i + 1);
                    assertLi = $('
').addClass('tests-assert');
                    assertHtml = '' + assert.uid + ' ';
                    assertHtml += (assert.message || 'no message');
                    if (assert.result === false) {
                            assertHtml += ' (' + assert.expected + ' ' + '===' + ' ' + assert.actual + ')';
                            assertHtml += '
' + (assert.source || assert.message) + '
';
                            assertLi.addClass('has-failed');
                            failedAssertions.push(assert);
                    }
                    assertLi.html(assertHtml);
                    assertUl.append(assertLi);
            }

            testEl.append(assertUl);
            currentModuleEl.append(testEl);
            updateTest(test.passed, test.failed);
        });

        QUnit.done(function () {
            var duration = moment().diff(start),
                    failures = failedAssertions.length,
                    assert, i,
                    reportHTML = '',
                    header,
                    expression,
                    submitUrl = "https://github.com/moment/moment/issues/new",
                    searchUrl = "https://github.com/moment/moment/search",
                    titleText = "" + failures + " test" + (failures !== 1 ? "s" : "") + " failed. ",
                    bodyText = [
                            "### Client info",
                            '```',
                            "Date String   : " + (new Date()).toString(),
                            "Locale String : " + (new Date()).toLocaleString(),
                            "Offset        : " + (new Date(1000)).getTimezoneOffset(),
                            "User Agent    : " + navigator.userAgent,
                            '```'
                    ];

            for (i = 0; i < failedAssertions.length; ++i) {
                    assert = failedAssertions[i];

                    header = assert.module + ':' + assert.name + ' (' + assert.uid + ') ';
                    titleText += header;

                    bodyText.push('');
                    bodyText.push('====');
                    bodyText.push('');
                    bodyText.push('### ' + header);
                    bodyText.push('');
                    bodyText.push(assert.message);
                    bodyText.push('');
                    bodyText.push('```javascript');
                    bodyText.push('// Expected ' + assert.expected);
                    bodyText.push('// Actual   ' + assert.actual);

                    expression = typeof assert.actual === 'string' ?
                        '"' + assert.actual.replace('"', '\\"') + '"' : assert.actual;
                    expression += ' ' + '===' + ' ';
                    expression += typeof assert.expected === 'string' ?
                        '"' + assert.expected.replace('"', '\\"') + '"' : assert.expected;

                    bodyText.push(expression);
                    bodyText.push('```');
            }

            bodyText = bodyText.join('\n');

            submitUrl += '?title=' + encodeURIComponent(titleText);
            submitUrl += '&body=' + encodeURIComponent(bodyText);

            searchUrl += '?type=Issues&q=' + encodeURIComponent(titleText);

            if (failures) {
                    reportHTML += '
Uh oh, looks like some tests failed.
';
                    reportHTML += "
It's hard to catch bugs across all browsers and timezones. If you have a minute, please report the failing test.
";
                    reportHTML += "STEP 1: Search for an existing failure report";
                    reportHTML += "
If it doesn't look like this failure has already been reported, proceed to step 2.
";
                    reportHTML += "STEP 2: Submit a failure report";
                    reportHTML += '
Issue title
';
                    reportHTML += '
' + titleText + '
';
                    reportHTML += '
Issue description
';
                    reportHTML += '
' + bodyText.replace(/\n/g, '
') + '
';
            } else {
                    reportHTML += "
Awesome, all the unit tests passed!
";
            }

            $('#report-wrapper').html('
' + reportHTML + '
');

            // updateTotals(assertions.passes(), failures);
	});

        // fire tests after callbacks are registered
        QUnit.start();

	tests.on('click', '.tests-test', function(){
		$(this).toggleClass('is-open');
	});
})();
<commit_msg>slight fixes to test outputs (#328)<commit_after>/*global moment:false*/

(function(){
	var banner = $('#nodeunit-banner');
	var tests = $('#nodeunit-tests');
	var headerRow = $("#header-row");

	var start = moment();
	var passed = 0;
	var failed = 0;
	var total = 0;
	var currentTestModule;
	var currentModuleEl;

	function updateTest(_passed, _failed) {
		passed += _passed;
		failed += _failed;
		updateTotals(passed, failed);
	}

	function updateTotals(_passed, _failed) {
		if (_failed) {
			banner.addClass('has-failed');
		}
		banner.html('' + _passed + ' tests passed
' +
                        '' + _failed + ' failed');
	}

	(function() {
		var queryArgs = {}, query = window.location.search, pieces, i, key_val,
			filtered, suite, test;
		if (!query) { return; }
		if (query[query.length - 1] === '/') {
			query = query.slice(0, query.length - 1);
		}
		pieces = query.slice(1).split('&');
		for (i = 0; i < pieces.length; ++i) {
			key_val = pieces[i].split('=');
			queryArgs[decodeURIComponent(key_val[0])] = decodeURIComponent(key_val[1]);
		}
		if (queryArgs.suite !== undefined) {
			filtered = {};
			for (suite in exports) {
				if (suite.match(queryArgs.suite)) {
					filtered[suite] = exports[suite];
				}
			}
			exports = filtered;
		}
		if (queryArgs.test !== undefined) {
			for (suite in exports) {
				filtered = {};
				for (test in exports[suite]) {
					if (test === 'setUp' || test === 'tearDown' || test.match(queryArgs.test)) {
						filtered[test] = exports[suite][test];
					}
				}
				exports[suite] = filtered;
			}
		}
	}());

        QUnit.moduleStart(function (module) {
            var name = module.name;
            currentTestModule = name;
            currentModuleEl = $('
').addClass('tests-module');
            currentModuleEl.append('
' + name + '
');
            tests.append(currentModuleEl);
        });

        var assertions;
        var failedAssertions = []
        QUnit.testStart(function (test) {
            assertions = [];
        });

        QUnit.log(function (assertion) {
            assertions.push(assertion);
        });

        QUnit.testDone(function (test) {
            var name = test.name;
            var testEl = $('
').addClass('tests-test'),
                    testHtml = '',
                    assertUl = $('
').addClass('tests-asserts'),
                    assertLi,
                    assertHtml = '',
                    assert;

            total++;

            // each test
            testHtml += '
' + name + ' ';
            if (test.failed > 0) {
                    testEl.addClass('has-failed is-open');
                    testHtml += test.passed + ' passed : ';
                    testHtml += test.failed + ' failed
';
            } else {
                    testHtml += 'all ' + test.passed + ' passed
';
            }
            testEl.html(testHtml);

            // each assert
            for (var i = 0; i < assertions.length; i++) {
                    assert = assertions[i];
                    assert.uid = total + '.' + (i + 1);
                    assertLi = $('
').addClass('tests-assert');
                    assertHtml = '' + assert.uid + ' ';
                    assertHtml += (assert.message || 'no message');
                    if (assert.result === false) {
                            assertHtml += ' (' + assert.expected + ' ' + '===' + ' ' + assert.actual + ')';
                            assertHtml += '
' + (assert.source || assert.message) + '
';
                            assertLi.addClass('has-failed');
                            failedAssertions.push(assert);
                    }
                    assertLi.html(assertHtml);
                    assertUl.append(assertLi);
            }

            testEl.append(assertUl);
            currentModuleEl.append(testEl);
            updateTest(test.passed, test.failed);
        });

        QUnit.done(function () {
            var duration = moment().diff(start),
                    failures = failedAssertions.length,
                    assert, i,
                    reportHTML = '',
                    header,
                    expression,
                    submitUrl = "https://github.com/moment/moment/issues/new",
                    searchUrl = "https://github.com/moment/moment/search",
                    titleText = "" + failures + " test" + (failures !== 1 ? "s" : "") + " failed. ",
                    bodyText = [
                        "### Client info",
                        '```',
                        "Date String   : " + (new Date()).toString(),
                        "Locale String : " + (new Date()).toLocaleString(),
                        "Offset        : " + (new Date()).getTimezoneOffset(),
                        "User Agent    : " + navigator.userAgent,
                        "Moment Version: " + moment.version,
                        '```'
                    ];

            for (i = 0; i < failedAssertions.length; ++i) {
                    assert = failedAssertions[i];

                    header = assert.module + ':' + assert.name + ' (' + assert.uid + ') ';
                    titleText += header;

                    bodyText.push('');
                    bodyText.push('====');
                    bodyText.push('');
                    bodyText.push('### ' + header);
                    bodyText.push('');
                    bodyText.push(assert.message);
                    bodyText.push('');
                    bodyText.push('```javascript');
                    bodyText.push('// Expected ' + assert.expected);
                    bodyText.push('// Actual   ' + assert.actual);

                    expression = typeof assert.actual === 'string' ?
                        '"' + assert.actual.replace('"', '\\"') + '"' : assert.actual;
                    expression += ' ' + '===' + ' ';
                    expression += typeof assert.expected === 'string' ?
                        '"' + assert.expected.replace('"', '\\"') + '"' : assert.expected;

                    bodyText.push(expression);
                    bodyText.push('```');
            }

            bodyText = bodyText.join('\n');

            submitUrl += '?title=' + encodeURIComponent(titleText);
            submitUrl += '&body=' + encodeURIComponent(bodyText);

            searchUrl += '?type=Issues&q=' + encodeURIComponent(titleText);

            if (failures) {
                    reportHTML += '
Uh oh, looks like some tests failed.
';
                    reportHTML += "
It's hard to catch bugs across all browsers and timezones. If you have a minute, please report the failing test.
";
                    reportHTML += "STEP 1: Search for an existing failure report";
                    reportHTML += "
If it doesn't look like this failure has already been reported, proceed to step 2.
";
                    reportHTML += "STEP 2: Submit a failure report";
                    reportHTML += '
Issue title
';
                    reportHTML += '
' + titleText + '
';
                    reportHTML += '
Issue description
';
                    reportHTML += '
' + bodyText.replace(/\n/g, '
') + '
';
            } else {
                    reportHTML += "
Awesome, all the unit tests passed!
";
            }

            $('#report-wrapper').html('
' + reportHTML + '
');

            // updateTotals(assertions.passes(), failures);
	});

        // fire tests after callbacks are registered
        QUnit.start();

	tests.on('click', '.tests-test', function(){
		$(this).toggleClass('is-open');
	});
})();
<|endoftext|>


<commit_before>var gtl = {init: false, scale: 100, mouse: null, mousestart: null, scrolled: false, smoothscroll: false};

var timelineInit = function() {
  gtl.x = d3.scale.linear()
    .range([0, gtl.scale]);
  gtl.w = d3.scale.linear()
    .range([0, gtl.scale])
    .domain([0, 24]);
  gtl.y = d3.scale.linear();

  gtl.main = d3.select(".timeline-visualization")
    .attr("style", "height:" + screen.height + "px;");

  gtl.timeline = gtl.main.append("div").attr("id", "timeline");
  gtl.rules = gtl.timeline.append("div").attr("id", "tlrules");
  gtl.body = gtl.timeline.append("div").attr("id", "tlbody");

  $('#done').click(function() {
    $('input[name="item-done"]').click();
  });
  $('input[name="item-done"]').click(function(e) {
    e.preventDefault();
    var $this = $(this);
    if (user) {
      if ($this.attr('checked')) {
        $this.attr('checked', false);
        $('#done').removeClass('done');
      } else {
        $this.attr('checked', true);
        $('#done').addClass('done');
      }
    }
    $this.blur();
  }).attr('checked', false);

  var formItem = $('#item form');
  formItem.find('.btn-delete').click(function() {
    handlers.deleteItem(formItem.data('js-data'));
  });
  formItem.find('.btn-list').click(function() {
    var item = formItem.data('js-data');
    if (item.user) {
      handlers.changeURL('/user/' + item.user._id);
    } else if (item.list) {
      handlers.changeURL('/list/' + item.list._id);
    }
  });

  var formList = $('#list form');
  formList.find('.btn-delete').click(function() {
    handlers.deleteList(formList.data('js-data'));
  });

  $('#editlist').click(function(e) {
    e.preventDefault();
    handlers.changeURL('/list/' + handlers.currentList + '/edit');
  });

  $('.subscribe').click(function(e) {
    e.preventDefault();
    var $this = $(this);
    if ($this.attr('subbed')) {
      $this.removeAttr('subbed');
    } else $this.attr('subbed', 'subbed');
    handlers.subscribe(!!$this.attr('subbed'));
  });

  $('#list #adduser').click(function(e) {
    e.preventDefault();
    var form = $('#list form');
    var email = form.find('#email').val();
    var permission = form.find('#members-head .permission').val();
    var list = form.data('js-data');
    for (var i = 0; i < list.members.length; i++) {
      if (list.members[i].user.email.toLowerCase() === email.toLowerCase()) {
        alert("This user is already added to the list.");
        return;
      }
    }
    makeRequest('POST', '/email.json', {email: email}, function(data) {
      list.members.push({permission: permission, user: data});
      handlers.populateListMembers(list);
    });
  });

  gtl.init = true;
  setInterval(timeUpdate, 1000);
};

function timeUpdate() {
  gtl.rules.selectAll(".now")
    .transition().duration(750).ease("linear")
    .style("left", gtl.x(moment().diff(gtl.starttime) / 3600000) + "px");

  gtl.body.selectAll(".white")
    .transition().duration(750).ease("linear")
    .style("width", function(d) { return Math.max(0, gtl.w(-d.rstart + moment().diff(gtl.starttime) / 3600000) - 1) + "px"; });

  gtl.body.selectAll(".item-back")
    .attr("rend", function(d) { return d.rend - moment().diff(gtl.starttime) / 3600000; });

  gtl.body.selectAll(".item")
    .attr("rend", function(d) { return d.rend - moment().diff(gtl.starttime) / 3600000; });
}

function barsEnter(bars) {
  var wrap = bars.append("div").attr("class", "rule-wrap");

  wrap.append("div")
    .attr("class", "rule")
    .style("left", function(d) { return gtl.x(d * 24 - Math.floor(-gtl.gstart / 24) * 24 + 24 - moment().hours()) + "px"; });

  wrap.append("div")
    .attr("class", "rule-text")
    .style("left", function(d) { return (gtl.x(d * 24 - Math.floor(-gtl.gstart / 24) * 24 + 24 - moment().hours()) - (gtl.scale / 2)) + "px"; })
    .style("width", function() { return gtl.scale + "px"; })
    .html(function(d) { var tmp = moment().add('days', d - Math.floor(-gtl.gstart / 24) + 1); return tmp.format("ddd") + "
" + tmp.format("MMM D"); });

  gtl.rules.selectAll(".now")
    .data(d3.range(1))
    .enter().append("div")
    .attr("class", "now")
    .style("left", gtl.x(0) + "px");
}

function barsUpdate(bars) {
  bars.select(".rule")
    .transition().duration(750).ease("linear")
    .style("left", function(d) { return gtl.x(d * 24 - Math.floor(-gtl.gstart / 24) * 24 + 24 - moment().hours()) + "px"; });

  bars.select(".rule-text")
    .html(function(d) { var tmp = moment().add('days', d - Math.floor(-gtl.gstart / 24) + 1); return tmp.format("ddd") + "
" + tmp.format("MMM D"); })
    .transition().duration(750).ease("linear")
    .style("left", function(d) { return (gtl.x(d * 24 - Math.floor(-gtl.gstart / 24) * 24 + 24 - moment().hours()) - (gtl.scale / 2)) + "px"; })
    .style("width", function() { return gtl.scale + "px"; });

  gtl.rules.selectAll(".now")
    .transition().duration(750).ease("linear")
    .style("left", gtl.x(0) + "px");

  gtl.body.selectAll(".white")
    .transition().duration(750).ease("linear")
    .style("width", function(d) { return Math.max(0, gtl.w(-d.rstart) - 1) + "px"; });
}

function barsExit(bars) {
  bars.transition().duration(750).remove();
}

function getListName(d) {
  if (d.user) {
    return d.user._id == handlers.currentUser ? '' : d.user.name;
  } else if (d.list) {
    return d.list._id == handlers.currentList ? '' : d.list.name;
  } else return '';
}

function itemsEnter(items) {
  var wrap = items.append("div")
    .attr("class", "item-wrap");

  wrap.append("div")
    .attr("class", "item-back")
    .attr("done", function(d) { return d.done; })
    .attr("rend", function(d) { return d.rend; })
    .attr("notify", function(d) { return (d.rend / (d.rend - d.rstart)) <= 0.2; })
    .style("left", function(d) { return gtl.x(d.rstart) + "px"; })
    .style("top", function(d) { return (gtl.y(d.row) + 45) + "px"; })
    .append("div")
    .attr("class", "white")
    .style("width", function(d) { return Math.max(0, gtl.w(-d.rstart) - 1) + "px"; });

  var front = wrap.append("div")
    .attr("class", "item")
    .attr("done", function(d) { return d.done; })
    .attr("rend", function(d) { return d.rend; })
    .attr("notify", function(d) { return (d.rend / (d.rend - d.rstart)) <= 0.2; })
    .style("left", function(d) { return gtl.x(d.rstart) + "px"; })
    .style("top", function(d) { return (gtl.y(d.row) + 45) + "px"; });

  front.append("div")
    .attr("class", "info title")
    .attr("title", function(d) { return d.name; })
    .text(function(d) { return d.name; });

  front.append("div")
    .attr("class", "info desc")
    .attr("title", function(d) { return d.desc; })
    .text(function(d) { return d.desc; });

  front.append("div")
    .attr("class", "info from")
    .attr("title", getListName)
    .text(getListName);

  front.append("div")
    .attr("class", "info due")
    .attr("title", function(d) { return moment().add('hours', d.rend).calendar(); })
    .text(function(d) { return moment().add('hours', d.rend).calendar(); });

  front.on("click", function(d) {
    if (gtl.mousestart && Math.abs(d3.event.screenX - gtl.mousestart[0]) < 2) {
      handlers.changeURL('/item/' + d._id);
    }
  });
}

function itemsUpdate(items) {
  items.select(".item-back")
    .style("top", function(d) { return (gtl.y(d.row) + 45) + "px"; })
    .attr("done", function(d) { return d.done; })
    .attr("rend", function(d) { return d.rend; })
    .attr("notify", function(d) { return (d.rend / (d.rend - d.rstart)) <= 0.2; })
    .transition().duration(750)
    .style("left", function(d) { return gtl.x(d.rstart) + "px"; })
    .style("width", function(d) { return gtl.w(d.rend - d.rstart) + "px"; })
    .select(".white")
    .style("width", function(d) { return Math.max(0, gtl.w(-d.rstart) - 1) + "px"; });

  var front = items.select(".item")
    .style("top", function(d) { return (gtl.y(d.row) + 45) + "px"; })
    .attr("done", function(d) { return d.done; })
    .attr("rend", function(d) { return d.rend; })
    .attr("notify", function(d) { return (d.rend / (d.rend - d.rstart)) <= 0.2; })
    .transition().duration(750)
    .style("left", function(d) { return gtl.x(d.rstart) + "px"; })
    .style("width", function(d) { return gtl.w(d.rend - d.rstart) + "px"; });

  front.select(".title")
    .attr("title", function(d) { return d.name; })
    .text(function(d) { return d.name; });

  front.select(".desc")
    .attr("title", function(d) { return d.desc; })
    .text(function(d) { return d.desc; });

  front.select(".from")
    .attr("title", getListName)
    .text(getListName);

  front.select(".due")
    .attr("title", function(d) { return moment().add('hours', d.rend).calendar(); })
    .text(function(d) { return moment().add('hours', d.rend).calendar(); });
}

function itemsExit(items) {
  items.transition().duration(750).style("opacity", 0).remove();
}

var timelineUpdate = function(data) {
  if (!gtl.init) timelineInit();
  if (!data) {
    showError();
    return;
  }
  var currentDate = moment();
  gtl.starttime = currentDate;

  for (var i = 0; i < data.length; ++i) {
    data[i].rstart = moment(data[i].start).diff(currentDate) / 3600000;
    data[i].rend = moment(data[i].end).diff(currentDate) / 3600000;
  }
  gtl.gstart = Math.min(0, d3.min(data, function(d) { return d.rstart; }));
  gtl.gend = Math.max(0, d3.max(data, function(d) { return d.rend; }));
  if (isNaN(gtl.gstart)) gtl.gstart = 0;
  if (isNaN(gtl.gend)) gtl.gend = 0;
  gtl.gstart -= (screen.width / gtl.scale * 24);
  gtl.gend += (screen.width / gtl.scale * 24);

  var height = data.length * 70;
  gtl.main.attr("style", "height:" + (height + 50) + "px;");
  gtl.y.range([0, height]);

  gtl.x.domain([gtl.gstart, gtl.gstart + 24]);
  gtl.y.domain([0, data.length]);

  var bars = gtl.rules.selectAll(".rule-wrap")
    .data(d3.range(Math.floor((gtl.gend - gtl.gstart) / 24)));

  barsEnter(bars.enter());
  barsUpdate(bars);
  barsExit(bars.exit());

  var sorted = data.sort(function(a, b) {
    if (a.done == b.done) {
      var endc = a.rend  0 || b.rstart > 0) { // Sort items that haven't started yet by start date
        return a.rstart  bpercent ? 1 : (apercent == bpercent ? 0 : -1);
      }
    } else if (a.done) { // Completed items go underneith all other items
      return 1;
    } else return -1;
  });

  var rowend = [];
  var rows = 0;
  for (var i = 0; i < sorted.length; i++) { // Compress rows of items into available space
    (function() {
      for (var r = 0; r < rows; r++) {
        if (rowend[r] <= sorted[i].rstart) {
          rowend[r] = sorted[i].rend;
          sorted[i].row = r;
          return;
        }
      }
      sorted[i].row = rows;
      rowend[rows++] = sorted[i].rend;
    })();
  }

  var items = gtl.body.selectAll(".item-wrap")
    .data(sorted, function(d) { return d._id; });

  itemsEnter(items.enter());
  itemsUpdate(items);
  itemsExit(items.exit());

  if (!gtl.mouse && !gtl.scrolled) {
    $(window).scrollLeft(gtl.x(0) - $(window).width() / 2);
    gtl.scrolled = true;
  }
  if (gtl.smoothscroll) {
    $('body,html').animate({
      scrollLeft: gtl.x(0) - $(window).width() / 2
    }, 755, 'linear');
    gtl.smoothscroll = false;
  }
};
<commit_msg>Fixed compression for items sorted in reverse order. Fixed page height being higher than needed.<commit_after>var gtl = {init: false, scale: 100, mouse: null, mousestart: null, scrolled: false, smoothscroll: false};

var timelineInit = function() {
  gtl.x = d3.scale.linear()
    .range([0, gtl.scale]);
  gtl.w = d3.scale.linear()
    .range([0, gtl.scale])
    .domain([0, 24]);
  gtl.y = d3.scale.linear();

  gtl.main = d3.select(".timeline-visualization")
    .attr("style", "height:" + screen.height + "px;");

  gtl.timeline = gtl.main.append("div").attr("id", "timeline");
  gtl.rules = gtl.timeline.append("div").attr("id", "tlrules");
  gtl.body = gtl.timeline.append("div").attr("id", "tlbody");

  $('#done').click(function() {
    $('input[name="item-done"]').click();
  });
  $('input[name="item-done"]').click(function(e) {
    e.preventDefault();
    var $this = $(this);
    if (user) {
      if ($this.attr('checked')) {
        $this.attr('checked', false);
        $('#done').removeClass('done');
      } else {
        $this.attr('checked', true);
        $('#done').addClass('done');
      }
    }
    $this.blur();
  }).attr('checked', false);

  var formItem = $('#item form');
  formItem.find('.btn-delete').click(function() {
    handlers.deleteItem(formItem.data('js-data'));
  });
  formItem.find('.btn-list').click(function() {
    var item = formItem.data('js-data');
    if (item.user) {
      handlers.changeURL('/user/' + item.user._id);
    } else if (item.list) {
      handlers.changeURL('/list/' + item.list._id);
    }
  });

  var formList = $('#list form');
  formList.find('.btn-delete').click(function() {
    handlers.deleteList(formList.data('js-data'));
  });

  $('#editlist').click(function(e) {
    e.preventDefault();
    handlers.changeURL('/list/' + handlers.currentList + '/edit');
  });

  $('.subscribe').click(function(e) {
    e.preventDefault();
    var $this = $(this);
    if ($this.attr('subbed')) {
      $this.removeAttr('subbed');
    } else $this.attr('subbed', 'subbed');
    handlers.subscribe(!!$this.attr('subbed'));
  });

  $('#list #adduser').click(function(e) {
    e.preventDefault();
    var form = $('#list form');
    var email = form.find('#email').val();
    var permission = form.find('#members-head .permission').val();
    var list = form.data('js-data');
    for (var i = 0; i < list.members.length; i++) {
      if (list.members[i].user.email.toLowerCase() === email.toLowerCase()) {
        alert("This user is already added to the list.");
        return;
      }
    }
    makeRequest('POST', '/email.json', {email: email}, function(data) {
      list.members.push({permission: permission, user: data});
      handlers.populateListMembers(list);
    });
  });

  gtl.init = true;
  setInterval(timeUpdate, 1000);
};

function timeUpdate() {
  gtl.rules.selectAll(".now")
    .transition().duration(750).ease("linear")
    .style("left", gtl.x(moment().diff(gtl.starttime) / 3600000) + "px");

  gtl.body.selectAll(".white")
    .transition().duration(750).ease("linear")
    .style("width", function(d) { return Math.max(0, gtl.w(-d.rstart + moment().diff(gtl.starttime) / 3600000) - 1) + "px"; });

  gtl.body.selectAll(".item-back")
    .attr("rend", function(d) { return d.rend - moment().diff(gtl.starttime) / 3600000; });

  gtl.body.selectAll(".item")
    .attr("rend", function(d) { return d.rend - moment().diff(gtl.starttime) / 3600000; });
}

function barsEnter(bars) {
  var wrap = bars.append("div").attr("class", "rule-wrap");

  wrap.append("div")
    .attr("class", "rule")
    .style("left", function(d) { return gtl.x(d * 24 - Math.floor(-gtl.gstart / 24) * 24 + 24 - moment().hours()) + "px"; });

  wrap.append("div")
    .attr("class", "rule-text")
    .style("left", function(d) { return (gtl.x(d * 24 - Math.floor(-gtl.gstart / 24) * 24 + 24 - moment().hours()) - (gtl.scale / 2)) + "px"; })
    .style("width", function() { return gtl.scale + "px"; })
    .html(function(d) { var tmp = moment().add('days', d - Math.floor(-gtl.gstart / 24) + 1); return tmp.format("ddd") + "
" + tmp.format("MMM D"); });

  gtl.rules.selectAll(".now")
    .data(d3.range(1))
    .enter().append("div")
    .attr("class", "now")
    .style("left", gtl.x(0) + "px");
}

function barsUpdate(bars) {
  bars.select(".rule")
    .transition().duration(750).ease("linear")
    .style("left", function(d) { return gtl.x(d * 24 - Math.floor(-gtl.gstart / 24) * 24 + 24 - moment().hours()) + "px"; });

  bars.select(".rule-text")
    .html(function(d) { var tmp = moment().add('days', d - Math.floor(-gtl.gstart / 24) + 1); return tmp.format("ddd") + "
" + tmp.format("MMM D"); })
    .transition().duration(750).ease("linear")
    .style("left", function(d) { return (gtl.x(d * 24 - Math.floor(-gtl.gstart / 24) * 24 + 24 - moment().hours()) - (gtl.scale / 2)) + "px"; })
    .style("width", function() { return gtl.scale + "px"; });

  gtl.rules.selectAll(".now")
    .transition().duration(750).ease("linear")
    .style("left", gtl.x(0) + "px");

  gtl.body.selectAll(".white")
    .transition().duration(750).ease("linear")
    .style("width", function(d) { return Math.max(0, gtl.w(-d.rstart) - 1) + "px"; });
}

function barsExit(bars) {
  bars.transition().duration(750).remove();
}

function getListName(d) {
  if (d.user) {
    return d.user._id == handlers.currentUser ? '' : d.user.name;
  } else if (d.list) {
    return d.list._id == handlers.currentList ? '' : d.list.name;
  } else return '';
}

function itemsEnter(items) {
  var wrap = items.append("div")
    .attr("class", "item-wrap");

  wrap.append("div")
    .attr("class", "item-back")
    .attr("done", function(d) { return d.done; })
    .attr("rend", function(d) { return d.rend; })
    .attr("notify", function(d) { return (d.rend / (d.rend - d.rstart)) <= 0.2; })
    .style("left", function(d) { return gtl.x(d.rstart) + "px"; })
    .style("top", function(d) { return (gtl.y(d.row) + 45) + "px"; })
    .append("div")
    .attr("class", "white")
    .style("width", function(d) { return Math.max(0, gtl.w(-d.rstart) - 1) + "px"; });

  var front = wrap.append("div")
    .attr("class", "item")
    .attr("done", function(d) { return d.done; })
    .attr("rend", function(d) { return d.rend; })
    .attr("notify", function(d) { return (d.rend / (d.rend - d.rstart)) <= 0.2; })
    .style("left", function(d) { return gtl.x(d.rstart) + "px"; })
    .style("top", function(d) { return (gtl.y(d.row) + 45) + "px"; });

  front.append("div")
    .attr("class", "info title")
    .attr("title", function(d) { return d.name; })
    .text(function(d) { return d.name; });

  front.append("div")
    .attr("class", "info desc")
    .attr("title", function(d) { return d.desc; })
    .text(function(d) { return d.desc; });

  front.append("div")
    .attr("class", "info from")
    .attr("title", getListName)
    .text(getListName);

  front.append("div")
    .attr("class", "info due")
    .attr("title", function(d) { return moment().add('hours', d.rend).calendar(); })
    .text(function(d) { return moment().add('hours', d.rend).calendar(); });

  front.on("click", function(d) {
    if (gtl.mousestart && Math.abs(d3.event.screenX - gtl.mousestart[0]) < 2) {
      handlers.changeURL('/item/' + d._id);
    }
  });
}

function itemsUpdate(items) {
  items.select(".item-back")
    .style("top", function(d) { return (gtl.y(d.row) + 45) + "px"; })
    .attr("done", function(d) { return d.done; })
    .attr("rend", function(d) { return d.rend; })
    .attr("notify", function(d) { return (d.rend / (d.rend - d.rstart)) <= 0.2; })
    .transition().duration(750)
    .style("left", function(d) { return gtl.x(d.rstart) + "px"; })
    .style("width", function(d) { return gtl.w(d.rend - d.rstart) + "px"; })
    .select(".white")
    .style("width", function(d) { return Math.max(0, gtl.w(-d.rstart) - 1) + "px"; });

  var front = items.select(".item")
    .style("top", function(d) { return (gtl.y(d.row) + 45) + "px"; })
    .attr("done", function(d) { return d.done; })
    .attr("rend", function(d) { return d.rend; })
    .attr("notify", function(d) { return (d.rend / (d.rend - d.rstart)) <= 0.2; })
    .transition().duration(750)
    .style("left", function(d) { return gtl.x(d.rstart) + "px"; })
    .style("width", function(d) { return gtl.w(d.rend - d.rstart) + "px"; });

  front.select(".title")
    .attr("title", function(d) { return d.name; })
    .text(function(d) { return d.name; });

  front.select(".desc")
    .attr("title", function(d) { return d.desc; })
    .text(function(d) { return d.desc; });

  front.select(".from")
    .attr("title", getListName)
    .text(getListName);

  front.select(".due")
    .attr("title", function(d) { return moment().add('hours', d.rend).calendar(); })
    .text(function(d) { return moment().add('hours', d.rend).calendar(); });
}

function itemsExit(items) {
  items.transition().duration(750).style("opacity", 0).remove();
}

var timelineUpdate = function(data) {
  if (!gtl.init) timelineInit();
  if (!data) {
    showError();
    return;
  }
  var currentDate = moment();
  gtl.starttime = currentDate;

  for (var i = 0; i < data.length; ++i) {
    data[i].rstart = moment(data[i].start).diff(currentDate) / 3600000;
    data[i].rend = moment(data[i].end).diff(currentDate) / 3600000;
  }
  gtl.gstart = Math.min(0, d3.min(data, function(d) { return d.rstart; }));
  gtl.gend = Math.max(0, d3.max(data, function(d) { return d.rend; }));
  if (isNaN(gtl.gstart)) gtl.gstart = 0;
  if (isNaN(gtl.gend)) gtl.gend = 0;
  gtl.gstart -= (screen.width / gtl.scale * 24);
  gtl.gend += (screen.width / gtl.scale * 24);

  var sorted = data.sort(function(a, b) {
    if (a.done == b.done) {
      var endc = a.rend  0 || b.rstart > 0) { // Sort items that haven't started yet by start date
        return a.rstart  bpercent ? 1 : (apercent == bpercent ? 0 : -1);
      }
    } else if (a.done) { // Completed items go underneith all other items
      return 1;
    } else return -1;
  });

  var rowend = [];
  var rowstart = [];
  var rows = 0;
  for (var i = 0; i < sorted.length; i++) { // Compress rows of items into available space
    (function() {
      for (var r = 0; r < rows; r++) {
        if (rowend[r] <= sorted[i].rstart) {
          rowend[r] = sorted[i].rend;
          sorted[i].row = r;
          return;
        } else if (rowstart[r] >= sorted[i].rend) {
          rowstart[r] = sorted[i].rstart;
          sorted[i].row = r;
          return;
        }
      }
      sorted[i].row = rows;
      rowstart[rows] = sorted[i].rstart;
      rowend[rows++] = sorted[i].rend;
    })();
  }

  var height = rows * 70;
  gtl.main.attr("style", "height:" + (height + 50) + "px;");
  gtl.y.range([0, height]);

  gtl.x.domain([gtl.gstart, gtl.gstart + 24]);
  gtl.y.domain([0, rows]);

  var bars = gtl.rules.selectAll(".rule-wrap")
    .data(d3.range(Math.floor((gtl.gend - gtl.gstart) / 24)));

  barsEnter(bars.enter());
  barsUpdate(bars);
  barsExit(bars.exit());

  var items = gtl.body.selectAll(".item-wrap")
    .data(sorted, function(d) { return d._id; });

  itemsEnter(items.enter());
  itemsUpdate(items);
  itemsExit(items.exit());

  if (!gtl.mouse && !gtl.scrolled) {
    $(window).scrollLeft(gtl.x(0) - $(window).width() / 2);
    gtl.scrolled = true;
  }
  if (gtl.smoothscroll) {
    $('body,html').animate({
      scrollLeft: gtl.x(0) - $(window).width() / 2
    }, 755, 'linear');
    gtl.smoothscroll = false;
  }
};
<|endoftext|>


<commit_before>const { Command, Store, Stopwatch } = require('klasa');

module.exports = class extends Command {

	constructor(...args) {
		super(...args, {
			aliases: ['r'],
			permissionLevel: 10,
			guarded: true,
			description: (message) => message.language.get('COMMAND_RELOAD_DESCRIPTION'),
			usage: '<Store:store|Piece:piece|everything:default>'
		});
	}

	async run(message, [piece]) {
		if (piece === 'everything') return this.everything(message);
		if (piece instanceof Store) {
			const timer = new Stopwatch();
			await piece.loadAll();
			await piece.init();
			if (this.client.shard) {
				await this.client.shard.broadcastEval(`
					if (this.shard.id !== ${this.client.shard.id}) this.${piece.name}.loadAll().then(() => this.${piece.name}.loadAll());
				`);
			}
			return message.sendLocale('COMMAND_RELOAD_ALL', [piece, timer.stop()]);
		}

		try {
			const itm = await piece.reload();
			const timer = new Stopwatch();
			if (this.client.shard) {
				await this.client.shard.broadcastEval(`
					if (this.shard.id !== ${this.client.shard.id}) this.${piece.store}.get('${piece.name}').reload();
				`);
			}
			return message.sendLocale('COMMAND_RELOAD', [itm.type, itm.name, timer.stop]);
		} catch (err) {
			piece.store.set(piece);
			return message.sendMessage(`❌ ${err}`);
		}
	}

	async everything(message) {
		const timer = new Stopwatch();
		await Promise.all(this.client.pieceStores.map(async (store) => {
			await store.loadAll();
			await store.init();
		}));
		if (this.client.shard) {
			await this.client.shard.broadcastEval(`
				if (this.shard.id !== ${this.client.shard.id}) this.client.pieceStores.map(async (store) => {
					await store.loadAll();
					await store.init();
				});
			`);
		}
		return message.sendLocale('COMMAND_RELOAD_EVERYTHING', [timer.stop()]);
	}

};
<commit_msg>Update reload.js (#375)<commit_after>const { Command, Store, Stopwatch } = require('klasa');

module.exports = class extends Command {

	constructor(...args) {
		super(...args, {
			aliases: ['r'],
			permissionLevel: 10,
			guarded: true,
			description: (message) => message.language.get('COMMAND_RELOAD_DESCRIPTION'),
			usage: '<Store:store|Piece:piece|everything:default>'
		});
	}

	async run(message, [piece]) {
		if (piece === 'everything') return this.everything(message);
		if (piece instanceof Store) {
			const timer = new Stopwatch();
			await piece.loadAll();
			await piece.init();
			if (this.client.shard) {
				await this.client.shard.broadcastEval(`
					if (this.shard.id !== ${this.client.shard.id}) this.${piece.name}.loadAll().then(() => this.${piece.name}.loadAll());
				`);
			}
			return message.sendLocale('COMMAND_RELOAD_ALL', [piece, timer.stop()]);
		}

		try {
			const itm = await piece.reload();
			const timer = new Stopwatch();
			if (this.client.shard) {
				await this.client.shard.broadcastEval(`
					if (this.shard.id !== ${this.client.shard.id}) this.${piece.store}.get('${piece.name}').reload();
				`);
			}
			return message.sendLocale('COMMAND_RELOAD', [itm.type, itm.name, timer.stop()]);
		} catch (err) {
			piece.store.set(piece);
			return message.sendMessage(`❌ ${err}`);
		}
	}

	async everything(message) {
		const timer = new Stopwatch();
		await Promise.all(this.client.pieceStores.map(async (store) => {
			await store.loadAll();
			await store.init();
		}));
		if (this.client.shard) {
			await this.client.shard.broadcastEval(`
				if (this.shard.id !== ${this.client.shard.id}) this.client.pieceStores.map(async (store) => {
					await store.loadAll();
					await store.init();
				});
			`);
		}
		return message.sendLocale('COMMAND_RELOAD_EVERYTHING', [timer.stop()]);
	}

};
<|endoftext|>


<commit_before>const { remote, shell } = require('electron')

const links = document.querySelectorAll('a')
const licenses_elem = document.getElementById('licenses')

function onLinkClick(event) {
    //All links should have their href='#', so open the actual page in an external browser, and disable any scrolling, etc the window would do
    shell.openExternal(event.target._href)
    event.preventDefault()
}
function onLicenseClick() {
    this.lastChild.style.maxHeight = ''
    //event.target.lastChild.style.maxHeight = ''
}

//By default, links will open the page in the current window. This shouldn't happen, so each link needs to be changed
for (let i = 0; i < links.length; i++) {
    links[i]._href = links[i].href
    links[i].href = '#'

    if (links[i].innerText === '') {
        links[i].innerText = '(' + links[i]._href + ')'
    }

    links[i].addEventListener('click', onLinkClick)
}

//Replace all elements with special ids with the relevant version information
{
    if (app_version) {
        app_version.textContent = remote.app.getVersion()
    }

    if (node_version) {
        node_version.textContent = process.versions.node
    }

    if (electron_version) {
        electron_version.textContent = process.versions.electron
    }

    if (chrome_version) {
        chrome_version.textContent = process.versions.chrome
    }
}

function addLicense(module) {
    let elem = document.createElement('div')
    let header = document.createElement('h2')
    let links = document.createElement('span')
    header.textContent = module.name || ''

    if (module.version) {
        header.textContent += ' (' + module.version + ')'
    }
    if (module.publisher) {
        header.textContent += ', ' + module.publisher
    }
    if (module.licenses) {
        header.textContent += ': ' + module.licenses
    }

    if (module.url) {
        let link = document.createElement('a')
        link._href = module.url
        link.href = '#'
        link.textContent = module.url

        link.addEventListener('click', onLinkClick)

        links.appendChild(link)
    }
    if (module.repository) {
        let link = document.createElement('a')
        link._href = module.repository
        link.href = '#'
        link.textContent = module.repository

        link.addEventListener('click', onLinkClick)

        links.appendChild(link)
    }

    elem.appendChild(header)

    if (links.childElementCount) {
        elem.appendChild(links)
    }

    if (module.licenseText) {
        elem.appendChild(document.createElement('pre'))
        elem.lastChild.textContent = module.licenseText
        elem.lastChild.style.maxHeight = '1.5em'

        elem.addEventListener('click', onLicenseClick)
    }

    licenses_elem.appendChild(elem)
}

addLicense({
    name: 'Inter UI',
    publisher: 'Rasmus Andersson',
    url: 'https://rsms.me/inter/',
    repository: 'https://github.com/rsms/inter/',
    licenses: 'SIL OPEN FONT LICENSE',

    licenseText: `Copyright (c) 2017 The Inter UI Project Authors (me@rsms.me)

    This Font Software is licensed under the SIL Open Font License, Version 1.1.
    This license is copied below, and is also available with a FAQ at:
    http://scripts.sil.org/OFL

    -----------------------------------------------------------
    SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
    -----------------------------------------------------------

    PREAMBLE
    The goals of the Open Font License (OFL) are to stimulate worldwide
    development of collaborative font projects, to support the font creation
    efforts of academic and linguistic communities, and to provide a free and
    open framework in which fonts may be shared and improved in partnership
    with others.

    The OFL allows the licensed fonts to be used, studied, modified and
    redistributed freely as long as they are not sold by themselves. The
    fonts, including any derivative works, can be bundled, embedded,
    redistributed and/or sold with any software provided that any reserved
    names are not used by derivative works. The fonts and derivatives,
    however, cannot be released under any other type of license. The
    requirement for fonts to remain under this license does not apply
    to any document created using the fonts or their derivatives.

    DEFINITIONS
    "Font Software" refers to the set of files released by the Copyright
    Holder(s) under this license and clearly marked as such. This may
    include source files, build scripts and documentation.

    "Reserved Font Name" refers to any names specified as such after the
    copyright statement(s).

    "Original Version" refers to the collection of Font Software components as
    distributed by the Copyright Holder(s).

    "Modified Version" refers to any derivative made by adding to, deleting,
    or substituting -- in part or in whole -- any of the components of the
    Original Version, by changing formats or by porting the Font Software to a
    new environment.

    "Author" refers to any designer, engineer, programmer, technical
    writer or other person who contributed to the Font Software.

    PERMISSION AND CONDITIONS
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of the Font Software, to use, study, copy, merge, embed, modify,
    redistribute, and sell modified and unmodified copies of the Font
    Software, subject to the following conditions:

    1) Neither the Font Software nor any of its individual components,
    in Original or Modified Versions, may be sold by itself.

    2) Original or Modified Versions of the Font Software may be bundled,
    redistributed and/or sold with any software, provided that each copy
    contains the above copyright notice and this license. These can be
    included either as stand-alone text files, human-readable headers or
    in the appropriate machine-readable metadata fields within text or
    binary files as long as those fields can be easily viewed by the user.

    3) No Modified Version of the Font Software may use the Reserved Font
    Name(s) unless explicit written permission is granted by the corresponding
    Copyright Holder. This restriction only applies to the primary font name as
    presented to the users.

    4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
    Software shall not be used to promote, endorse or advertise any
    Modified Version, except to acknowledge the contribution(s) of the
    Copyright Holder(s) and the Author(s) or with their explicit written
    permission.

    5) The Font Software, modified or unmodified, in part or in whole,
    must be distributed entirely under this license, and must not be
    distributed under any other license. The requirement for fonts to
    remain under this license does not apply to any document created
    using the Font Software.

    TERMINATION
    This license becomes null and void if any of the above conditions are
    not met.

    DISCLAIMER
    THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
    OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
    COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
    DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
    OTHER DEALINGS IN THE FONT SOFTWARE.`
})

require('fs').readFile(
    require('path').join(__dirname, '../', 'licenses.json'),
    'utf8',
    (error, data) => {
        if (error) {
            licenses_elem.innerText =
                'Unable to load licenses!\n' +
                (error.message || error.toString())

            return false
        }

        try {
            data = JSON.parse(data)

            if (Array.isArray(data)) {
                for (let i = 0; i < data.length; i++) {
                    addLicense(data[i])
                }
            } else {
                throw new Error('Data is not an Array!')
            }
        } catch (error) {
            licenses_elem.innerText =
                'Unable to parse licenses!\n' +
                (error.message || error.toString())
        }
    }
)

document.getElementById('close').addEventListener('click', () => {
    window.close()
})
<commit_msg>Updated Inter font copyright<commit_after>const { remote, shell } = require('electron')

const links = document.querySelectorAll('a')
const licenses_elem = document.getElementById('licenses')

function onLinkClick(event) {
    //All links should have their href='#', so open the actual page in an external browser, and disable any scrolling, etc the window would do
    shell.openExternal(event.target._href)
    event.preventDefault()
}
function onLicenseClick() {
    this.lastChild.style.maxHeight = ''
    //event.target.lastChild.style.maxHeight = ''
}

//By default, links will open the page in the current window. This shouldn't happen, so each link needs to be changed
for (let i = 0; i < links.length; i++) {
    links[i]._href = links[i].href
    links[i].href = '#'

    if (links[i].innerText === '') {
        links[i].innerText = '(' + links[i]._href + ')'
    }

    links[i].addEventListener('click', onLinkClick)
}

//Replace all elements with special ids with the relevant version information
{
    if (app_version) {
        app_version.textContent = remote.app.getVersion()
    }

    if (node_version) {
        node_version.textContent = process.versions.node
    }

    if (electron_version) {
        electron_version.textContent = process.versions.electron
    }

    if (chrome_version) {
        chrome_version.textContent = process.versions.chrome
    }
}

function addLicense(module) {
    let elem = document.createElement('div')
    let header = document.createElement('h2')
    let links = document.createElement('span')
    header.textContent = module.name || ''

    if (module.version) {
        header.textContent += ' (' + module.version + ')'
    }
    if (module.publisher) {
        header.textContent += ', ' + module.publisher
    }
    if (module.licenses) {
        header.textContent += ': ' + module.licenses
    }

    if (module.url) {
        let link = document.createElement('a')
        link._href = module.url
        link.href = '#'
        link.textContent = module.url

        link.addEventListener('click', onLinkClick)

        links.appendChild(link)
    }
    if (module.repository) {
        let link = document.createElement('a')
        link._href = module.repository
        link.href = '#'
        link.textContent = module.repository

        link.addEventListener('click', onLinkClick)

        links.appendChild(link)
    }

    elem.appendChild(header)

    if (links.childElementCount) {
        elem.appendChild(links)
    }

    if (module.licenseText) {
        elem.appendChild(document.createElement('pre'))
        elem.lastChild.textContent = module.licenseText
        elem.lastChild.style.maxHeight = '1.5em'

        elem.addEventListener('click', onLicenseClick)
    }

    licenses_elem.appendChild(elem)
}

addLicense({
    name: 'Inter UI',
    publisher: 'Rasmus Andersson',
    url: 'https://rsms.me/inter/',
    repository: 'https://github.com/rsms/inter/',
    licenses: 'SIL OPEN FONT LICENSE',

    licenseText: `Copyright (c) 2016-2018 The Inter Project Authors (me@rsms.me)

    This Font Software is licensed under the SIL Open Font License, Version 1.1.
    This license is copied below, and is also available with a FAQ at:
    http://scripts.sil.org/OFL

    -----------------------------------------------------------
    SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
    -----------------------------------------------------------

    PREAMBLE
    The goals of the Open Font License (OFL) are to stimulate worldwide
    development of collaborative font projects, to support the font creation
    efforts of academic and linguistic communities, and to provide a free and
    open framework in which fonts may be shared and improved in partnership
    with others.

    The OFL allows the licensed fonts to be used, studied, modified and
    redistributed freely as long as they are not sold by themselves. The
    fonts, including any derivative works, can be bundled, embedded,
    redistributed and/or sold with any software provided that any reserved
    names are not used by derivative works. The fonts and derivatives,
    however, cannot be released under any other type of license. The
    requirement for fonts to remain under this license does not apply
    to any document created using the fonts or their derivatives.

    DEFINITIONS
    "Font Software" refers to the set of files released by the Copyright
    Holder(s) under this license and clearly marked as such. This may
    include source files, build scripts and documentation.

    "Reserved Font Name" refers to any names specified as such after the
    copyright statement(s).

    "Original Version" refers to the collection of Font Software components as
    distributed by the Copyright Holder(s).

    "Modified Version" refers to any derivative made by adding to, deleting,
    or substituting -- in part or in whole -- any of the components of the
    Original Version, by changing formats or by porting the Font Software to a
    new environment.

    "Author" refers to any designer, engineer, programmer, technical
    writer or other person who contributed to the Font Software.

    PERMISSION AND CONDITIONS
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of the Font Software, to use, study, copy, merge, embed, modify,
    redistribute, and sell modified and unmodified copies of the Font
    Software, subject to the following conditions:

    1) Neither the Font Software nor any of its individual components,
    in Original or Modified Versions, may be sold by itself.

    2) Original or Modified Versions of the Font Software may be bundled,
    redistributed and/or sold with any software, provided that each copy
    contains the above copyright notice and this license. These can be
    included either as stand-alone text files, human-readable headers or
    in the appropriate machine-readable metadata fields within text or
    binary files as long as those fields can be easily viewed by the user.

    3) No Modified Version of the Font Software may use the Reserved Font
    Name(s) unless explicit written permission is granted by the corresponding
    Copyright Holder. This restriction only applies to the primary font name as
    presented to the users.

    4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
    Software shall not be used to promote, endorse or advertise any
    Modified Version, except to acknowledge the contribution(s) of the
    Copyright Holder(s) and the Author(s) or with their explicit written
    permission.

    5) The Font Software, modified or unmodified, in part or in whole,
    must be distributed entirely under this license, and must not be
    distributed under any other license. The requirement for fonts to
    remain under this license does not apply to any document created
    using the Font Software.

    TERMINATION
    This license becomes null and void if any of the above conditions are
    not met.

    DISCLAIMER
    THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
    OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
    COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
    DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
    OTHER DEALINGS IN THE FONT SOFTWARE.`
})

require('fs').readFile(
    require('path').join(__dirname, '../', 'licenses.json'),
    'utf8',
    (error, data) => {
        if (error) {
            licenses_elem.innerText =
                'Unable to load licenses!\n' +
                (error.message || error.toString())

            return false
        }

        try {
            data = JSON.parse(data)

            if (Array.isArray(data)) {
                for (let i = 0; i < data.length; i++) {
                    addLicense(data[i])
                }
            } else {
                throw new Error('Data is not an Array!')
            }
        } catch (error) {
            licenses_elem.innerText =
                'Unable to parse licenses!\n' +
                (error.message || error.toString())
        }
    }
)

document.getElementById('close').addEventListener('click', () => {
    window.close()
})
<|endoftext|>


<commit_before>var cc ={win:Ti.UI.currentWindow};
Ti.include('./application.js','./about_resources_data.js');
(function(){

	cc.win.orientationModes = [
		Ti.UI.PORTRAIT,
		Ti.UI.UPSIDE_PORTRAIT
	];

	Ti.API.info('currentCountry=' +  Ti.Locale.currentCountry);
	Ti.API.info('currentLanguage=' +  Ti.Locale.currentLanguage);
	Ti.API.info('currentLocale=' +  Ti.Locale.currentLocale);

	cc.getDataRow=function(itemR,itemCount){
		var row = Ti.UI.createTableViewRow({
			height:50,
			hasChild:true,
			className:'res_' + itemCount,  //Add unique to force new template
			ja_url:itemR.ref_ja_url,
			en_url:itemR.ref_en_url,
			isRowElement:true //hack for android touch event
		});

		if(itemR.hasHeader){
			row.header=itemR.header;
		}
		var resName = Ti.UI.createLabel({text:itemR.title,
											 color:'#000',
											 height:'auto',
											 left:5,
											 width:(Ti.Platform.displayCaps.platformWidth-20),
											 textAlign:'left',
											 font:{
												fontSize:14,fontWeight:'Bold'
											}
											});
		row.add(resName);

		return row;
	};

	cc.getTableData=function(){
		var tableData=[];
		var itemCount = cc.resourceData.length;
		for (var iLoop=0;iLoop<itemCount;iLoop++){
			tableData.push(cc.getDataRow(cc.resourceData[iLoop],iLoop));
		}
		return tableData;
	};
	cc.tableView = Ti.UI.createTableView({
		backgroundColor:'#fff',
		data:cc.getTableData()
	});
	cc.win.add(cc.tableView);

	cc.openLink=function(urlText){
		if (!Ti.Network.online){
		 	  noNetworkAlert();
		} else {
		   Ti.Platform.openURL(urlText);
		}
	};
})();

//-------------------------------
//	Events
//-------------------------------
cc.tableView.addEventListener('click', function(e){

	//If japan then try to load the japanese link first
	if(Ti.Locale.currentLanguage=='ja'){
		if(e.rowData.ja_url.length>0){
			cc.openLink(e.rowData.ja_url);
		}else{
			cc.openLink(e.rowData.en_url);
		}
	}else{
		//For everyone else try the english version first
		if(e.rowData.en_url.length>0){
			cc.openLink(e.rowData.en_url);
		}else{
			cc.openLink(e.rowData.ja_url);
		}
	}
});<commit_msg>added custom row headers.  Styled per Go & Kaz<commit_after>var cc ={win:Ti.UI.currentWindow};
Ti.include('./application.js','./about_resources_data.js');
(function(){

	cc.win.orientationModes = [
		Ti.UI.PORTRAIT,
		Ti.UI.UPSIDE_PORTRAIT
	];

	Ti.API.info('currentCountry=' +  Ti.Locale.currentCountry);
	Ti.API.info('currentLanguage=' +  Ti.Locale.currentLanguage);
	Ti.API.info('currentLocale=' +  Ti.Locale.currentLocale);

	cc.getDataRowHeader=function(itemR,itemCount){
		var row = Ti.UI.createTableViewRow({
			height:20,
			hasChild:false,
			className:'header_' + itemCount,  //Add unique to force new template
			allowClick:false,
			backgroundColor: '#666',
			isRowElement:true //hack for android touch event
		});

		var resName = Ti.UI.createLabel({text:itemR.header,
											 color:'#fff',
											 height:'auto',
											 left:5,
											 width:(Ti.Platform.displayCaps.platformWidth-20),
											 textAlign:'left',
											 font:{
												fontSize:16,fontWeight:'Bold'
											}
											});
		row.add(resName);

		return row;
	};
	cc.getDataRow=function(itemR,itemCount){
		var row = Ti.UI.createTableViewRow({
			height:50,
			hasChild:true,
			className:'res_' + itemCount,  //Add unique to force new template
			ja_url:itemR.ref_ja_url,
			en_url:itemR.ref_en_url,
			allowClick:true,
			isRowElement:true //hack for android touch event
		});

		var resName = Ti.UI.createLabel({text:itemR.title,
											 color:'#000',
											 height:'auto',
											 left:5,
											 width:(Ti.Platform.displayCaps.platformWidth-20),
											 textAlign:'left',
											 font:{
												fontSize:14,fontWeight:'Bold'
											}
											});
		row.add(resName);

		return row;
	};

	cc.getTableData=function(){
		var tableData=[];
		var itemCount = cc.resourceData.length;
		for (var iLoop=0;iLoop<itemCount;iLoop++){
			if(cc.resourceData[iLoop].hasHeader){
				tableData.push(cc.getDataRowHeader(cc.resourceData[iLoop],iLoop));
			}
			tableData.push(cc.getDataRow(cc.resourceData[iLoop],iLoop));
		}
		return tableData;
	};
	cc.tableView = Ti.UI.createTableView({
		backgroundColor:'#fff',
		data:cc.getTableData()
	});
	cc.win.add(cc.tableView);

	cc.openLink=function(urlText){
		if (!Ti.Network.online){
		 	  noNetworkAlert();
		} else {
		   Ti.Platform.openURL(urlText);
		}
	};
})();

//-------------------------------
//	Events
//-------------------------------
cc.tableView.addEventListener('click', function(e){
	//Stop them from clicking on headers
	if(!e.rowData.allowClick){
		return;
	}
	//If japan then try to load the japanese link first
	if(Ti.Locale.currentLanguage=='ja'){
		if(e.rowData.ja_url.length>0){
			cc.openLink(e.rowData.ja_url);
		}else{
			cc.openLink(e.rowData.en_url);
		}
	}else{
		//For everyone else try the english version first
		if(e.rowData.en_url.length>0){
			cc.openLink(e.rowData.en_url);
		}else{
			cc.openLink(e.rowData.ja_url);
		}
	}
});<|endoftext|>


<commit_before>/**
 * Created by Julian/Wolke on 07.11.2016.
 */
let Command = require('../../structures/command');
let moment = require('moment');
let winston = require('winston');
let _ = require('lodash');
let version = require('../../../package.json').version;
let erisVersion = require('../../../node_modules/eris/package.json').version;
class BotInfo extends Command {
    constructor({t, mod}) {
        super();
        this.cmd = 'bot';
        this.cat = 'misc';
        this.aliases = ['info', 'stats'];
        this.needGuild = false;
        this.t = t;
        this.accessLevel = 0;
        this.hub = mod.getMod('hub');
        this.v = mod.getMod('vm');
    }

    run(msg) {
        let user = rem.user;
        // let responseTimeout = setTimeout(() => {
        //
        // }, 10000);
        this.fetchData(msg).then(data => {
            // console.log(data);
            this.buildReply(msg, user, data);
        }).catch(data => {
            console.error(data);
            // console.error(data.badShards);
            let res = data.err === `Timeout!` ? `Timeout! Only ${Object.keys(data.shardData).length} Shards have responded! Missing Shards: ${Object.keys(data.badShards).join(', ')}` : 'kyaa >_<';
            msg.channel.createMessage(`:x: \`${res}\``);
        });
    }

    fetchData(msg) {
        return new Promise((resolve, reject) => {
            this.hub.on(`action_resolved_${msg.id}`, (data) => {
                if (data.err) reject(data);
                resolve(data);
            });
            this.hub.executeAction('bot_info', msg.id);
        });

    }

    buildReply(msg, user, data) {
        let reply = {
            embed: {
                author: {
                    name: `${user.username}`,
                    icon_url: user.avatarURL
                },
                fields: this.buildBotInfo(msg, data),
                color: 0x00ADFF
            }
        };
        msg.channel.createMessage(reply).then().catch(err => {
            // console.error(err);
        });
    }

    buildBotInfo(msg, data) {
        moment.locale(msg.lang[0]);
        let fields = [];
        let guilds = 0;
        let users = 0;
        let channels = 0;
        let voice = 0;
        let voice_playing = 0;
        let shard_users = rem.guilds.map(g => g.memberCount).reduce((a, b) => a + b);
        let shard_guilds = rem.guilds.size;
        let shard_channels = rem.guilds.map(g => g.channels.size).reduce((a, b) => a + b);
        let shard_voice = this.v.getVoiceConnections();
        let shard_voice_playing = this.v.getVoiceConnections(true);
        _.forIn(data.shards, (value, key) => {
            guilds += value.guilds;
            users += value.users;
            channels += value.channels;
            voice += value.voice;
            voice_playing += value.voice_active;
        });
        fields.push({
            name: this.t('bot-info.uptime', {lngs: msg.lang}),
            value: moment().to(rem.startTime),
            inline: true
        });
        fields.push({name: this.t('generic.version', {lngs: msg.lang}), value: version, inline: true});
        fields.push({name: this.t('bot-info.made', {lngs: msg.lang}), value: 'Wolke, Dean, Veld', inline: true});
        fields.push({name: this.t('bot-info.lib', {lngs: msg.lang}), value: `Eris ${erisVersion}`, inline: true});
        fields.push({name: this.t('bot-info.guilds', {lngs: msg.lang}), value: guilds, inline: true});
        fields.push({name: this.t('bot-info.users', {lngs: msg.lang}), value: users, inline: true});
        fields.push({name: this.t('bot-info.channels', {lngs: msg.lang}), value: channels, inline: true});
        fields.push({
            name: `${this.t('bot-info.voice_active', {lngs: msg.lang})}/${this.t('bot-info.voice', {lngs: msg.lang})}`,
            value: `${voice_playing}/${voice}`,
            inline: true
        });
        fields.push({
            name: `${this.t('bot-info.voice_active', {lngs: msg.lang})}/${this.t('bot-info.voice', {lngs: msg.lang})} (${this.t('bot-info.shard', {lngs: msg.lang})})`,
            value: `${shard_voice_playing}/${shard_voice}`,
            inline: true
        });
        fields.push({name: this.t('bot-info.guilds-s', {lngs: msg.lang}), value: shard_guilds, inline: true});
        fields.push({name: this.t('bot-info.users-s', {lngs: msg.lang}), value: shard_users, inline: true});
        fields.push({name: this.t('bot-info.channels-s', {lngs: msg.lang}), value: shard_channels, inline: true});
        fields.push({
            name: this.t('generic.donate', {lngs: msg.lang}),
            value: '[patreon.com/rem_bot](https://www.patreon.com/rem_bot)',
            inline: true
        });
        fields.push({
            name: this.t('generic.support', {lngs: msg.lang}),
            value: '[ram.moe/support](https://ram.moe/support)',
            inline: true
        });
        fields.push({
            name: this.t('generic.invite', {lngs: msg.lang}),
            value: '[ram.moe/invite](https://ram.moe/invite)',
            inline: true
        });
        fields.push({
            name: this.t('bot-info.shard', {lngs: msg.lang}),
            value: `${rem.options.firstShardID + 1}/${rem.options.maxShards}`,
            inline: true
        });
        fields.push({
            name: 'Twitter',
            value: '[twitter.com/Rem_Bot__](https://twitter.com/Rem_Bot__)',
            inline: true
        });
        fields.push({
            name: this.t('bot-info.top_donators', {lngs: msg.lang}),
            value: `\`Karen#3938\` \`100$/m\`\n\`ResurrectionHQ#3061\` \`50$/m\`\n\`Hulkerman#0140\` \`108€\``,
            inline: true
        });
        return fields;
    }
}
module.exports = BotInfo;<commit_msg>no longer needed<commit_after>/**
 * Created by Julian/Wolke on 07.11.2016.
 */
let Command = require('../../structures/command');
let moment = require('moment');
let winston = require('winston');
let _ = require('lodash');
let version = require('../../../package.json').version;
let erisVersion = require('../../../node_modules/eris/package.json').version;
class BotInfo extends Command {
    constructor({t, mod}) {
        super();
        this.cmd = 'bot';
        this.cat = 'misc';
        this.aliases = ['info', 'stats'];
        this.needGuild = false;
        this.t = t;
        this.accessLevel = 0;
        this.hub = mod.getMod('hub');
        this.v = mod.getMod('vm');
    }

    run(msg) {
        let user = rem.user;
        // let responseTimeout = setTimeout(() => {
        //
        // }, 10000);
        this.fetchData(msg).then(data => {
            // console.log(data);
            this.buildReply(msg, user, data);
        }).catch(data => {
            console.error(data);
            // console.error(data.badShards);
            let res = data.err === `Timeout!` ? `Timeout! Only ${Object.keys(data.shardData).length} Shards have responded! Missing Shards: ${Object.keys(data.badShards).join(', ')}` : 'kyaa >_<';
            msg.channel.createMessage(`:x: \`${res}\``);
        });
    }

    fetchData(msg) {
        return new Promise((resolve, reject) => {
            this.hub.on(`action_resolved_${msg.id}`, (data) => {
                if (data.err) reject(data);
                resolve(data);
            });
            this.hub.executeAction('bot_info', msg.id);
        });

    }

    buildReply(msg, user, data) {
        let reply = {
            embed: {
                author: {
                    name: `${user.username}`,
                    icon_url: user.avatarURL
                },
                fields: this.buildBotInfo(msg, data),
                color: 0x00ADFF
            }
        };
        msg.channel.createMessage(reply).then().catch(err => {
            // console.error(err);
        });
    }

    buildBotInfo(msg, data) {
        moment.locale(msg.lang[0]);
        let fields = [];
        let guilds = 0;
        let users = 0;
        let channels = 0;
        let voice = 0;
        let voice_playing = 0;
        let shard_users = rem.guilds.map(g => g.memberCount).reduce((a, b) => a + b);
        let shard_guilds = rem.guilds.size;
        let shard_channels = rem.guilds.map(g => g.channels.size).reduce((a, b) => a + b);
        let shard_voice = this.v.getVoiceConnections();
        let shard_voice_playing = this.v.getVoiceConnections(true);
        _.forIn(data.shards, (value, key) => {
            guilds += value.guilds;
            users += value.users;
            channels += value.channels;
            voice += value.voice;
            voice_playing += value.voice_active;
        });
        fields.push({
            name: this.t('bot-info.uptime', {lngs: msg.lang}),
            value: moment().to(rem.startTime),
            inline: true
        });
        fields.push({name: this.t('generic.version', {lngs: msg.lang}), value: version, inline: true});
        fields.push({name: this.t('bot-info.made', {lngs: msg.lang}), value: 'Wolke, Dean, Veld', inline: true});
        fields.push({name: this.t('bot-info.lib', {lngs: msg.lang}), value: `Eris ${erisVersion}`, inline: true});
        fields.push({name: this.t('bot-info.guilds', {lngs: msg.lang}), value: guilds, inline: true});
        fields.push({name: this.t('bot-info.users', {lngs: msg.lang}), value: users, inline: true});
        fields.push({name: this.t('bot-info.channels', {lngs: msg.lang}), value: channels, inline: true});
        fields.push({
            name: `${this.t('bot-info.voice_active', {lngs: msg.lang})}/${this.t('bot-info.voice', {lngs: msg.lang})}`,
            value: `${voice_playing}/${voice}`,
            inline: true
        });
        fields.push({
            name: `${this.t('bot-info.voice_active', {lngs: msg.lang})}/${this.t('bot-info.voice', {lngs: msg.lang})} (${this.t('bot-info.shard', {lngs: msg.lang})})`,
            value: `${shard_voice_playing}/${shard_voice}`,
            inline: true
        });
        fields.push({name: this.t('bot-info.guilds-s', {lngs: msg.lang}), value: shard_guilds, inline: true});
        fields.push({name: this.t('bot-info.users-s', {lngs: msg.lang}), value: shard_users, inline: true});
        fields.push({name: this.t('bot-info.channels-s', {lngs: msg.lang}), value: shard_channels, inline: true});
        fields.push({
            name: this.t('bot-info.shard', {lngs: msg.lang}),
            value: `${rem.options.firstShardID + 1}/${rem.options.maxShards}`,
            inline: true
        });
        return fields;
    }
}
module.exports = BotInfo;
<|endoftext|>