<commit_before>'use strict'

const db = require('../utils/database').getDatabase()
const BaseModel = require('./base-model')

class UserGroup extends BaseModel {
  sqlAll () {
    return `SELECT GrpID as id,
    ${this.schema.dataFieldsNames.join(', ')}
    FROM sPepTree
    WHERE Hide=False
    AND grpid IN
     (SELECT grpid
     FROM sPersonal
     WHERE hide=false
     GROUP BY grpid)
    ORDER BY name`
  }
}

const model = new UserGroup(db, 'user-group', {
  name: 'string'
})

module.exports = model
<commit_msg>add UserGroup sqlOne<commit_after>'use strict'

const db = require('../utils/database').getDatabase()
const BaseModel = require('./base-model')

class UserGroup extends BaseModel {
  sqlAll () {
    return `SELECT GrpID as id,
    ${this.schema.dataFieldsNames.join(', ')}
    FROM sPepTree
    WHERE Hide=False
    AND grpid IN
     (SELECT grpid
     FROM sPersonal
     WHERE hide=false
     GROUP BY grpid)
    ORDER BY name`
  }

  sqlOne (id) {
    return `SELECT GrpID as id,
      ${this.schema.dataFieldsNames.join(', ')}
      FROM sPepTree
      WHERE GrpID=${id}`
  }
}

const model = new UserGroup(db, 'user-group', {
  name: 'string'
})

module.exports = model
<|endoftext|>


<commit_before>/**
 * node-archiver
 *
 * Copyright (c) 2012-2014 Chris Talkington, contributors.
 * Licensed under the MIT license.
 * https://github.com/ctalkington/node-archiver/blob/master/LICENSE-MIT
 */

var engine = require('zip-stream');
var util = require('../../util');

var Zip = module.exports = function(options) {
  options = this.options = util.defaults(options, {
    comment: '',
    forceUTC: false,
    store: false
  });

  if (typeof options.zlib !== 'object') {
    options.zlib = {};
  }

  if (store) {
    options.zlib.level = 0;
  } else if (typeof options.level === 'number' && options.level >= 0) {
    options.zlib.level = options.level;
    delete options.level;
  } else if (typeof options.zlib.level !== 'number') {
    options.zlib.level = 1;
  }

  this.engine = new engine(options);
};

Zip.prototype.append = function(source, data, callback) {
  this.engine.entry(source, data, callback);
};

Zip.prototype.finalize = function() {
  this.engine.finalize();
};

Zip.prototype.pipe = function(dest, pipeOpts) {
  return this.engine.pipe(dest, pipeOpts);
};<commit_msg>zip: fix invalid var.<commit_after>/**
 * node-archiver
 *
 * Copyright (c) 2012-2014 Chris Talkington, contributors.
 * Licensed under the MIT license.
 * https://github.com/ctalkington/node-archiver/blob/master/LICENSE-MIT
 */

var engine = require('zip-stream');
var util = require('../../util');

var Zip = module.exports = function(options) {
  options = this.options = util.defaults(options, {
    comment: '',
    forceUTC: false,
    store: false
  });

  if (typeof options.zlib !== 'object') {
    options.zlib = {};
  }

  if (options.store) {
    options.zlib.level = 0;
  } else if (typeof options.level === 'number' && options.level >= 0) {
    options.zlib.level = options.level;
    delete options.level;
  } else if (typeof options.zlib.level !== 'number') {
    options.zlib.level = 1;
  }

  this.engine = new engine(options);
};

Zip.prototype.append = function(source, data, callback) {
  this.engine.entry(source, data, callback);
};

Zip.prototype.finalize = function() {
  this.engine.finalize();
};

Zip.prototype.pipe = function(dest, pipeOpts) {
  return this.engine.pipe(dest, pipeOpts);
};<|endoftext|>


<commit_before>const Cmd = require('./').Cmd;
const fetchMetadata = require('./').fetchMetadata;
const fs = require('fs-promise');
const path = require('path');
const Vulcan = require('vulcanize');
const Promise = require('bluebird');

const WWW_DIR = path.join(__dirname, '../www');

class DocCmd extends Cmd {
  constructor(args, opts) {
    super(args, opts);

    this.input = path.resolve(this.args[0] || '.');
    this.output = path.resolve(this.opts.o || '_docs');
    this.force = Boolean(this.opts.f);
  }

  *run() {
    if (yield fs.exists(this.output)) {
      if (!this.force) {
        throw new Error(`Output directory already exists`);
      }

      // yield fs.remove(this.output);
    } else {
      yield fs.mkdirp(this.output);
    }

    let metadata = yield fetchMetadata(this.input);

    yield fs.copy(WWW_DIR, this.output, {clobber: true});
    yield fs.copy(path.join(this.input, 'bower_components'), path.join(this.output, 'bower_components'), {clobber: true});
    yield fs.copy(path.join(this.input), path.join(this.output, 'bower_components', metadata.name), {
      clobber: true,
      filter: function(file) {
        if (file.indexOf('/bower_components') >= 0 ||
        file.indexOf('/node_modules') >= 0 ||
        file.indexOf('/.') >= 0) {
          return false;
        }

        return true;
      },
    });
    yield fs.writeFile(path.join(this.output, 'metadata.json'), JSON.stringify(metadata, null, 2));

    let args = {
      abspath: this.output,
      inlineScripts: true,
      inlineCss: true,
    };
    let target = 'index-unvulcanized.html';
    let vulcan = new Vulcan(args);
    let content = yield Promise.promisify(vulcan.process, { context: vulcan })(target);
    yield fs.writeFile(path.join(this.output, 'index.html'), content);

    yield fs.remove(path.join(this.output, target));
  }
}

module.exports = DocCmd;
<commit_msg>avoid dev dependency of xin-cli on bower, xin-cli will be acquire from running xin-cli code base<commit_after>const Cmd = require('./').Cmd;
const fetchMetadata = require('./').fetchMetadata;
const fs = require('fs-promise');
const path = require('path');
const Vulcan = require('vulcanize');
const Promise = require('bluebird');

const WWW_DIR = path.join(__dirname, '../www');

class DocCmd extends Cmd {
  constructor(args, opts) {
    super(args, opts);

    this.input = path.resolve(this.args[0] || '.');
    this.output = path.resolve(this.opts.o || '_docs');
    this.force = Boolean(this.opts.f);
  }

  *run() {
    if (yield fs.exists(this.output)) {
      if (!this.force) {
        throw new Error(`Output directory already exists`);
      }

      // yield fs.remove(this.output);
    } else {
      yield fs.mkdirp(this.output);
    }

    let metadata = yield fetchMetadata(this.input);

    yield fs.copy(WWW_DIR, this.output, {clobber: true});
    yield fs.copy(path.join(this.input, 'bower_components'), path.join(this.output, 'bower_components'), {clobber: true});

    // copy xin-cli from running xin-cli location
    yield fs.copy(path.join(__dirname, '..'), path.join(this.output, 'bower_components/xin-cli'), {
      clobber: true,
      filter: function(file) {
        if (file.indexOf('/bower_components') >= 0 ||
        file.indexOf('/node_modules') >= 0 ||
        file.indexOf('/.') >= 0) {
          return false;
        }

        return true;
      },
    });
    yield fs.copy(path.join(this.input), path.join(this.output, 'bower_components', metadata.name), {
      clobber: true,
      filter: function(file) {
        if (file.indexOf('/bower_components') >= 0 ||
        file.indexOf('/node_modules') >= 0 ||
        file.indexOf('/.') >= 0) {
          return false;
        }

        return true;
      },
    });
    yield fs.writeFile(path.join(this.output, 'metadata.json'), JSON.stringify(metadata, null, 2));

    let args = {
      abspath: this.output,
      inlineScripts: true,
      inlineCss: true,
    };
    let target = 'index-unvulcanized.html';
    let vulcan = new Vulcan(args);
    let content = yield Promise.promisify(vulcan.process, { context: vulcan })(target);
    yield fs.writeFile(path.join(this.output, 'index.html'), content);

    yield fs.remove(path.join(this.output, target));
  }
}

module.exports = DocCmd;
<|endoftext|>


<commit_before>import { EJSON } from 'meteor/ejson';

/**
 * @param client
 * @param collectionName {string}
 * @param channels {Array<Channel>}
 * @param data {Object}
 * @param namespacedId
 */
export default (client, collectionName, channels, data, namespacedId) => {
    const message = EJSON.stringify(data);

    if (channels.length) {
        channels.forEach(channelName => {
            client.publish(channelName, message);

            if (namespacedId) {
                client.publish(collectionName + '::' + namespacedId, message);
            }
        })
    }
};
<commit_msg>Fixed #91 - added a check for channel name<commit_after>import { EJSON } from 'meteor/ejson';

/**
 * @param client
 * @param collectionName {string}
 * @param channels {Array<Channel>}
 * @param data {Object}
 * @param namespacedId This is the id of the document, for direct processing.
 */
export default (client, collectionName, channels, data, namespacedId) => {
    const message = EJSON.stringify(data);

    if (channels.length) {
        channels.forEach(channelName => {
            if (channelName) {
                // sometimes it can be null, need to think about it
                client.publish(channelName, message);
            }

            if (namespacedId) {
                client.publish(collectionName + '::' + namespacedId, message);
            }
        })
    }
};
<|endoftext|>


<commit_before>(function() {
    var Agora = this.Agora,
        app = this.app;

    Agora.QuestionListView = Backbone.View.extend({
        tagName: "div",
        initialize: function() {
            _.bindAll(this);
            this.template = _.template($("#template-question_list_view").html());
            this.render();
            return this.$el;
        },

        render: function() {
            // render template
            this.$el.html(this.template(ajax_data));
            $("#question-list").append(this.$el);
            $("#question-list table tbody").each(function (index) {
                var randomize = $(this).data('randomize');
                if (randomize) {
                    $(this).shuffle();
                }
            });
        }
    });

    Agora.ElectionResultsView = Backbone.View.extend({
        tagName: "div",
        initialize: function() {
            _.bindAll(this);
            this.template = _.template($("#template-election_results_view").html());
            this.render();
            return this.$el;
        },

        render: function() {
            // render template
            this.$el.html(this.template(ajax_data));
            $("#election-results").append(this.$el);
            for (var i = 0; i < ajax_data.election.result.counts.length; i++) {
                var view = null;
                if (ajax_data.election.result.counts[i].tally_type == 'MEEK-STV') {
                    view = new Agora.MeekStvTallyView({
                        question: ajax_data.election.result.counts[i],
                        tally:ajax_data.extra_data.tally_log[i],
                        question_num: i,
                    });
                } else if (ajax_data.election.result.counts[i].tally_type == 'ONE_CHOICE') {
                    view = new Agora.OneChoiceTallyView({
                        question: ajax_data.election.result.counts[i],
                        tally: ajax_data.extra_data.tally_log[i],
                        question_num: i,
                    });
                }
                $("#election-results").append(view.render().el);
            }
        }
    });

    Agora.MeekStvTallyView = Backbone.View.extend({
        tagName: "div",

        id: function() {
            return "tally_question" + this.options.question_num;
        },

        initialize: function() {
            _.bindAll(this);
            this.template = _.template($("#template-question_meek_stv_tally").html());
            this.render();
            return this.$el;
        },

        render: function() {
            // render template
            this.$el.html(this.template(this.options));
            this.$el.find('tbody tr').sortElements(function (a, b) {
                var rate = function (i) {
                    return ($(i).find('.already_won').length
                        + $(i).find('.won').length
                        - $(i).find('.lost').length
                        - $(i).find('.already_lost').length);
                }
                return rate(a) < rate(b);
            });
            return this;
        },
    });

    Agora.OneChoiceTallyView = Backbone.View.extend({
        tagName: "div",

        id: function() {
            return "tally_question" + this.options.question_num;
        },

        className: "election-results",

        initialize: function() {
            _.bindAll(this);
            this.color = d3.scale.category10();
            this.template = _.template($("#template-question_one_choice_tally").html());
            this.render();
            return this.$el;
        },

        render: function() {
            // render template
            for (var i=0; i<this.options.question.answers.length; i++) {
                this.options.question.answers[i]['color'] = this.color(i);
            }
            this.$el.html(this.template(this.options));
            this.$el.find('li').sortElements(function (a, b) {
                var rate = function (i) {
                    return parseFloat($(i).data('value'));
                }
                return rate(a) < rate(b);
            });
            this.pieChart();
            return this;
        },

        pieChart: function() {
            var pienode = this.$el.find('.piechart')[0];
            Charts.arc(this.options.question.answers,
                       pienode,
                       function (d) { return d.total_count; },
                       function (d) { return d.value; },
                       this.color,
                       500, 250);
        }
    });

    Agora.ElectionView = Backbone.View.extend({
        el: "div.election",

        initialize: function() {
            _.bindAll(this);
            // Only initialize on correct section of page exists.
            if ($("#activity-list").length > 0) {
                this.activityListView = new Agora.ActivityListView();
            }

            this.questionListView = new Agora.QuestionListView();

            if (ajax_data.election.result_tallied_at_date) {
                this.electionResultsView = new Agora.ElectionResultsView();
            }
        }
    });

    Agora.ElectionDelegatesView = Agora.GenericListView.extend({
        el: "#user-list",
        templateEl: "#template-vote_list_item",
        templateVoteInfoEl: "#template-vote_info",
        sendingData: false,

        events: {
            'hover .user-result .row': 'hoverUser'
        },

        initialize: function() {
            Agora.GenericListView.prototype.initialize.apply(this);

            this.delegateView = null;
        },

        renderItem: function(model) {
            return this.template(model.toJSON());
        },

        hoverUser: function(e) {
            if (!this.templateVoteInfo) {
                this.templateVoteInfo = _.template($(this.templateVoteInfoEl).html());
            }
            var id = $(e.target).closest('.row').data('id');
            var model = {
                vote: this.collection.get(id).toJSON(),
                election: ajax_data.election,
                extra_data: ajax_data.extra_data
            };
            if (model.election.result_tallied_at_date) {
                model.num_delegated_votes = 0;
                model.rank_in_delegates = "-";
                if (model.vote.delegate_election_count) {
                    model.num_delegated_votes = model.vote.delegate_election_count.count;
                    var rank = model.vote.delegate_election_count.rank;
                    if (rank) {
                        model.rank_in_delegates = rank + "º";
                    }
                }
            }
            $("#vote_info").html(this.templateVoteInfo(model));
            $("#vote_info .delegate_vote").click(this.delegateVote);
        },

        delegateVote: function (e) {
            e.preventDefault();
            Agora.delegateVoteHandler(e, this);
        }
    });
}).call(this)
<commit_msg>fixing typo<commit_after>(function() {
    var Agora = this.Agora,
        app = this.app;

    Agora.QuestionListView = Backbone.View.extend({
        tagName: "div",
        initialize: function() {
            _.bindAll(this);
            this.template = _.template($("#template-question_list_view").html());
            this.render();
            return this.$el;
        },

        render: function() {
            // render template
            this.$el.html(this.template(ajax_data));
            $("#question-list").append(this.$el);
            $("#question-list table tbody").each(function (index) {
                var randomize = $(this).data('randomize');
                if (randomize) {
                    $(this).shuffle();
                }
            });
        }
    });

    Agora.ElectionResultsView = Backbone.View.extend({
        tagName: "div",
        initialize: function() {
            _.bindAll(this);
            this.template = _.template($("#template-election_results_view").html());
            this.render();
            return this.$el;
        },

        render: function() {
            // render template
            this.$el.html(this.template(ajax_data));
            $("#election-results").append(this.$el);
            for (var i = 0; i < ajax_data.election.result.counts.length; i++) {
                var view = null;
                if (ajax_data.election.result.counts[i].tally_type == 'MEEK-STV') {
                    view = new Agora.MeekStvTallyView({
                        question: ajax_data.election.result.counts[i],
                        tally:ajax_data.extra_data.tally_log[i],
                        question_num: i,
                    });
                } else if (ajax_data.election.result.counts[i].tally_type == 'ONE_CHOICE') {
                    view = new Agora.OneChoiceTallyView({
                        question: ajax_data.election.result.counts[i],
                        tally: ajax_data.extra_data.tally_log[i],
                        question_num: i,
                    });
                }
                $("#election-results").append(view.render().el);
            }
        }
    });

    Agora.MeekStvTallyView = Backbone.View.extend({
        tagName: "div",

        id: function() {
            return "tally_question" + this.options.question_num;
        },

        initialize: function() {
            _.bindAll(this);
            this.template = _.template($("#template-question_meek_stv_tally").html());
            this.render();
            return this.$el;
        },

        render: function() {
            // render template
            this.$el.html(this.template(this.options));
            this.$el.find('tbody tr').sortElements(function (a, b) {
                var rate = function (i) {
                    return ($(i).find('.already_won').length
                        + $(i).find('.won').length
                        - $(i).find('.lost').length
                        - $(i).find('.already_lost').length);
                }
                return rate(a) < rate(b);
            });
            return this;
        },
    });

    Agora.OneChoiceTallyView = Backbone.View.extend({
        tagName: "div",

        id: function() {
            return "tally_question" + this.options.question_num;
        },

        className: "election-results",

        initialize: function() {
            _.bindAll(this);
            this.color = d3.scale.category10();
            this.template = _.template($("#template-question_one_choice_tally").html());
            this.render();
            return this.$el;
        },

        render: function() {
            // render template
            for (var i=0; i<this.options.question.answers.length; i++) {
                this.options.question.answers[i]['color'] = this.color(i);
            }
            this.$el.html(this.template(this.options));
            this.$el.find('li').sortElements(function (a, b) {
                var rate = function (i) {
                    return parseFloat($(i).data('value'));
                }
                return rate(a) < rate(b);
            });
            this.pieChart();
            return this;
        },

        pieChart: function() {
            var pienode = this.$el.find('.piechart')[0];
            Charts.arc(this.options.question.answers,
                       pienode,
                       function (d) { return d.total_count; },
                       function (d) { return d.value; },
                       this.color,
                       500, 250);
        }
    });

    Agora.ElectionView = Backbone.View.extend({
        el: "div.election",

        initialize: function() {
            _.bindAll(this);
            // Only initialize on correct section of page exists.
            if ($("#activity-list").length > 0) {
                this.activityListView = new Agora.ActivityListView();
            }

            this.questionListView = new Agora.QuestionListView();

            if (ajax_data.election.result_tallied_at_date) {
                this.electionResultsView = new Agora.ElectionResultsView();
            }
        }
    });

    Agora.ElectionDelegatesView = Agora.GenericListView.extend({
        el: "#user-list",
        templateEl: "#template-vote_list_item",
        templateVoteInfoEl: "#template-vote_info",
        sendingData: false,

        events: {
            'hover .user-result .row': 'hoverUser'
        },

        initialize: function() {
            Agora.GenericListView.prototype.initialize.apply(this);

            this.delegateView = null;
        },

        renderItem: function(model) {
            return this.template(model.toJSON());
        },

        hoverUser: function(e) {
            if (!this.templateVoteInfoEl) {
                this.templateVoteInfo = _.template($(this.templateVoteInfoEl).html());
            }
            var id = $(e.target).closest('.row').data('id');
            var model = {
                vote: this.collection.get(id).toJSON(),
                election: ajax_data.election,
                extra_data: ajax_data.extra_data
            };
            if (model.election.result_tallied_at_date) {
                model.num_delegated_votes = 0;
                model.rank_in_delegates = "-";
                if (model.vote.delegate_election_count) {
                    model.num_delegated_votes = model.vote.delegate_election_count.count;
                    var rank = model.vote.delegate_election_count.rank;
                    if (rank) {
                        model.rank_in_delegates = rank + "º";
                    }
                }
            }
            $("#vote_info").html(this.templateVoteInfo(model));
            $("#vote_info .delegate_vote").click(this.delegateVote);
        },

        delegateVote: function (e) {
            e.preventDefault();
            Agora.delegateVoteHandler(e, this);
        }
    });
}).call(this)
<|endoftext|>


<commit_before>import loggerCreator from '../utils/logger'
//noinspection JSUnresolvedVariable
var moduleLogger = loggerCreator("player");

import {observable, action, computed} from "mobx";
import retries from "../utils/retries"
import assert from "../utils/assert"
import Playlist from './web/playlist'
import * as wrappedSoundManager from './web/wrapped_sound_manager'

class Player {

  MARK_PLAYED_AFTER_SECONDS = 20;

  @observable isPlaying = false;
  @observable currentPlaylist = null;
  @observable song = null;

  @observable loadingAction = null;
  @observable loadingError = null;

  constructor() {
    let logger = loggerCreator("constructor", moduleLogger);

    logger.info(`initializing soundmanager2`);
    wrappedSoundManager.setup();
  }

  _onPlayProgress(seconds) {
    if (this.song && this.song.markingAsPlayedPromise === null && seconds >= this.MARK_PLAYED_AFTER_SECONDS) {
      let logger = loggerCreator(this._onPlayProgress.name, moduleLogger);

      return this.song.markAsPlayed();
    }
  }

  async changePlaylist(playlistName) {
    let logger = loggerCreator("changePlaylist", moduleLogger);

    await this.stop();

    logger.info(`setting playlist to ${playlistName}`);
    this.currentPlaylist = new Playlist(playlistName);
  }

  @action pause() {
    let logger = loggerCreator("pause", moduleLogger);

    let promise = Promise.resolve();

    if (this.song) {
      promise = this.song.pauseSound();
    }

    this.isPlaying = false;

    return promise;
  }

  @action play() {
    let logger = loggerCreator("play", moduleLogger);

    assert(this.currentPlaylist, "unexpected: playlist isn't set");

    if (this.song) {
      this.song.playSound();
    } else {
      this.next()
    }

    this.isPlaying = true;
  }

  _preloadNextSong() {
    let logger = loggerCreator(this._preloadNextSong.name, moduleLogger);

    logger.info(`peeking next song`);
    return this.currentPlaylist.peekNextSong()
      .then((peekedSong) => {
        logger.info(`loading peeked song: ${peekedSong.toString()}`);
        return peekedSong.load();
      })
      .catch(err => {
        logger.warn(`failed to peek the next song: ${err.stack}`);
      })
  }

  async next() {
    let logger = loggerCreator(this.next.name, moduleLogger);

    // time since last player - toggle-pause.
    // if too long, stop and clear playlist

    let previousSong = this.song;
    this.song = null;

    assert(this.currentPlaylist, "invalid state");

    if (previousSong) {
      logger.info(`previous song: ${previousSong.toString()}`);

      logger.info(`previous song - pausing playing song`);
      previousSong.pauseSound();

      logger.info(`previous song - making sure was marked as played`);
      if (previousSong.markingAsPlayedPromise) {
        logger.info(`previous song - marking as played`);
        await previousSong.markAsPlayed();
      } else {
        logger.info(`previous song - no need to mark as played`);
      }
    }

    await retries.promiseRetry(async lastError => {
      this.loadingAction = `Loading next song...`;
      this.loadingError = lastError && lastError.toString();
      let nextSong = await this.currentPlaylist.nextSong();

      if(nextSong !== null) {
        logger.info(`got next song: ${nextSong.toString()}`);

        if (this.song !== nextSong || this.song === null) {
          this.song = nextSong;
          logger.info(`subscribing to song events`);
          this.song.subscribePlayProgress(this._onPlayProgress.bind(this));
          this.song.subscribeFinish(this.next.bind(this));
        }

        this.loadingAction = `${nextSong.artist} - ${nextSong.title}`;
        logger.info(`playing sound`);
        await this.song.playSound();
      } else {
        logger.info(`no next song returned - playlist is empty`);
        this.loadingError = "Playlist is empty - No additional songs found"
      }
    })

    await this._preloadNextSong();
  }

  @action stop() {
    let logger = loggerCreator("stop", moduleLogger);

    return this.pause().then(() => {
      logger.info(`setting song to null`);
      this.song = null;
    });
  }

  @computed get isLoading() {
    if (this.song && this.song.loadedSound) {
      return false;
    } else {
      return true;
    }
  }
}

export default new Player();<commit_msg>web - next works<commit_after>import loggerCreator from '../utils/logger'
//noinspection JSUnresolvedVariable
var moduleLogger = loggerCreator("player");

import {observable, action, computed} from "mobx";
import retries from "../utils/retries"
import assert from "../utils/assert"
import Playlist from './web/playlist'
import * as wrappedSoundManager from './web/wrapped_sound_manager'

class Player {

  MARK_PLAYED_AFTER_SECONDS = 20;

  @observable isPlaying = false;
  @observable currentPlaylist = null;
  @observable song = null;

  @observable loadingAction = null;
  @observable loadingError = null;

  constructor() {
    let logger = loggerCreator("constructor", moduleLogger);

    logger.info(`initializing soundmanager2`);
    wrappedSoundManager.setup();
  }

  _onPlayProgress(seconds) {
    if (this.song && this.song.markingAsPlayedPromise === null && seconds >= this.MARK_PLAYED_AFTER_SECONDS) {
      let logger = loggerCreator(this._onPlayProgress.name, moduleLogger);

      return this.song.markAsPlayed();
    }
  }

  async changePlaylist(playlistName) {
    let logger = loggerCreator("changePlaylist", moduleLogger);

    await this.stop();

    logger.info(`setting playlist to ${playlistName}`);
    this.currentPlaylist = new Playlist(playlistName);
  }

  @action pause() {
    let logger = loggerCreator("pause", moduleLogger);

    let promise = Promise.resolve();

    if (this.song) {
      promise = this.song.pauseSound();
    }

    this.isPlaying = false;

    return promise;
  }

  @action play() {
    let logger = loggerCreator("play", moduleLogger);

    assert(this.currentPlaylist, "unexpected: playlist isn't set");

    if (this.song) {
      this.song.playSound();
    } else {
      this.playNext()
    }

    this.isPlaying = true;
  }

  _preloadNextSong() {
    let logger = loggerCreator(this._preloadNextSong.name, moduleLogger);

    logger.info(`peeking next song`);
    return this.currentPlaylist.peekNextSong()
      .then((peekedSong) => {
        logger.info(`loading peeked song: ${peekedSong.toString()}`);
        return peekedSong.load();
      })
      .catch(err => {
        logger.warn(`failed to peek the next song: ${err.stack}`);
      })
  }

  async playNext() {
    let logger = loggerCreator(this.playNext.name, moduleLogger);

    // time since last player - toggle-pause.
    // if too long, stop and clear playlist

    let previousSong = this.song;
    this.song = null;

    assert(this.currentPlaylist, "invalid state");

    if (previousSong) {
      logger.info(`previous song: ${previousSong.toString()}`);

      logger.info(`previous song - pausing playing song`);
      previousSong.pauseSound();

      logger.info(`previous song - making sure was marked as played`);
      if (previousSong.markingAsPlayedPromise) {
        logger.info(`previous song - marking as played`);
        await previousSong.markAsPlayed();
      } else {
        logger.info(`previous song - no need to mark as played`);
      }
    }

    await retries.promiseRetry(async lastError => {
      this.loadingAction = `Loading next song...`;
      this.loadingError = lastError && lastError.toString();
      let nextSong = await this.currentPlaylist.nextSong();

      if(nextSong !== null) {
        logger.info(`got next song: ${nextSong.toString()}`);

        if (this.song !== nextSong || this.song === null) {
          this.song = nextSong;
          logger.info(`subscribing to song events`);
          this.song.subscribePlayProgress(this._onPlayProgress.bind(this));
          this.song.subscribeFinish(this.playNext.bind(this));
        }

        this.loadingAction = `${nextSong.artist} - ${nextSong.title}`;
        logger.info(`playing sound`);
        await this.song.playSound();
      } else {
        logger.info(`no next song returned - playlist is empty`);
        this.loadingError = "Playlist is empty - No additional songs found"
      }
    })

    await this._preloadNextSong();
  }

  @action stop() {
    let logger = loggerCreator("stop", moduleLogger);

    return this.pause().then(() => {
      logger.info(`setting song to null`);
      this.song = null;
    });
  }

  @computed get isLoading() {
    if (this.song && this.song.loadedSound) {
      return false;
    } else {
      return true;
    }
  }
}

export default new Player();<|endoftext|>


<commit_before>angular.module('ontrack.extension.oidc', [
    'ot.service.core',
    'ot.service.form'
])
    .config(function ($stateProvider) {
        $stateProvider.state('oidc-settings', {
            url: '/extension/oidc/oidc-settings',
            templateUrl: 'extension/oidc/oidc-settings.tpl.html',
            controller: 'OidcSettingsCtrl'
        });
    })
    .controller('OidcSettingsCtrl', function ($scope, $http, ot, otFormService, otAlertService) {
        const view = ot.view();
        view.title = "OIDC Providers";
        view.breadcrumbs = ot.homeBreadcrumbs();
        view.commands = [
            ot.viewCloseCommand('/home')
        ];

        let viewInitialized = false;

        $scope.loadingProviders = false;

        const loadProviders = () => {
            $scope.loadingProviders = true;
            ot.pageCall($http.get("extension/oidc/providers")).then((resources) => {
                $scope.resources = resources;
                if (!viewInitialized) {
                    viewInitialized = true;
                    view.commands.push({
                        condition: function () {
                            return $scope.resources._create;
                        },
                        id: 'createProvider',
                        name: "Create providre",
                        cls: 'ot-command-new',
                        action: $scope.createProvider
                    });
                }
            }).finally(() => {
                $scope.loadingProviders = false;
            });
        };

        loadProviders();

        $scope.createProvider = () => {
            otFormService.create($scope.resources._create, "Create provider").then(loadProviders);
        };

        $scope.deleteProvider = (provider) => {
              otAlertService.confirm({
                  title: "OIDC provider deletion",
                  message: `Do you want to delete the ${provider.name} provider? It won't be available for authentication any longer.`
              }).then(() => ot.pageCall($http.delete(provider._delete))).then(loadProviders);
        };
    })
;<commit_msg>#756 Deletion of a provider<commit_after>angular.module('ontrack.extension.oidc', [
    'ot.service.core',
    'ot.service.form'
])
    .config(function ($stateProvider) {
        $stateProvider.state('oidc-settings', {
            url: '/extension/oidc/oidc-settings',
            templateUrl: 'extension/oidc/oidc-settings.tpl.html',
            controller: 'OidcSettingsCtrl'
        });
    })
    .controller('OidcSettingsCtrl', function ($scope, $http, ot, otFormService, otAlertService) {
        const view = ot.view();
        view.title = "OIDC Providers";
        view.breadcrumbs = ot.homeBreadcrumbs();
        view.commands = [
            ot.viewCloseCommand('/home')
        ];

        let viewInitialized = false;

        $scope.loadingProviders = false;

        const loadProviders = () => {
            $scope.loadingProviders = true;
            ot.pageCall($http.get("extension/oidc/providers")).then((resources) => {
                $scope.resources = resources;
                if (!viewInitialized) {
                    viewInitialized = true;
                    view.commands.push({
                        condition: function () {
                            return $scope.resources._create;
                        },
                        id: 'createProvider',
                        name: "Create provider",
                        cls: 'ot-command-new',
                        action: $scope.createProvider
                    });
                }
            }).finally(() => {
                $scope.loadingProviders = false;
            });
        };

        loadProviders();

        $scope.createProvider = () => {
            otFormService.create($scope.resources._create, "Create provider").then(loadProviders);
        };

        $scope.deleteProvider = (provider) => {
              otAlertService.confirm({
                  title: "OIDC provider deletion",
                  message: `Do you want to delete the ${provider.name} provider? It won't be available for authentication any longer.`
              }).then(() => ot.pageCall($http.delete(provider._delete))).then(loadProviders);
        };
    })
;<|endoftext|>


<commit_before>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

"use strict";

/**
 * Collection of serialization methods for form items
 */
core.Module("core.bom.FormItem",
{
	/**
	 * {Boolean} Returns whether the form @item {Element} is successful (should be submitted to the server)
	 */
	isSuccessful: function(item)
	{
		if (jasy.Env.isSet("debug"))
		{
			core.Assert.isEqual(arguments.length, 1);
			core.dom.Node.assertIsNode(item);
		}

		if (!item.name || item.disabled) {
			return false;
		}

		switch (item.type)
		{
			case "button":
			case "reset":
				return false;

			case "radio":
			case "checkbox":
				return item.checked;

			case "image":
			case "submit":
				return item == (item.ownerDocument || item.document).activeElement;
		}

		return true;
	},

	/**
	 * {String} Returns the value of the given form @item {Element}.
	 */
	getValue : function(item)
	{
		if (jasy.Env.isSet("debug"))
		{
			core.Assert.isEqual(arguments.length, 1);
			core.dom.Node.assertIsNode(item);
		}

		return core.String.interpret(encodeURIComponent(item.value));
	},

	/**
	 * {String} Returns the serialized representation of the given form @item {Element}.
	 */
	serialize: function(item)
	{
		if (jasy.Env.isSet("debug"))
		{
			core.Assert.isEqual(arguments.length, 1);
			core.dom.Node.assertIsNode(item);
			core.Assert.isType(item.name, "String");
		}

		return item.name + "=" + this.getValue(item);
	}
});<commit_msg>Added support for multi select boxes<commit_after>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

"use strict";

/**
 * Collection of serialization methods for form items
 */
core.Module("core.bom.FormItem",
{
	/**
	 * {Boolean} Returns whether the form @item {Element} is successful (should be submitted to the server)
	 */
	isSuccessful: function(item)
	{
		if (jasy.Env.isSet("debug"))
		{
			core.Assert.isEqual(arguments.length, 1);
			core.dom.Node.assertIsNode(item);
		}

		if (!item.name || item.disabled) {
			return false;
		}

		switch (item.type)
		{
			case "button":
			case "reset":
				return false;

			case "radio":
			case "checkbox":
				return item.checked;

			case "image":
			case "submit":
				return item == (item.ownerDocument || item.document).activeElement;
		}

		return true;
	},

	/**
	 * {String} Returns the value of the given form @item {Element}.
	 */
	getValue : function(item)
	{
		if (jasy.Env.isSet("debug"))
		{
			core.Assert.isEqual(arguments.length, 1);
			core.dom.Node.assertIsNode(item);
		}

		if (item.tagName == "SELECT")
		{
			// Inspired by jQuery
			var index = item.selectedIndex;
			var options = item.options;
			var one = item.type === "select-one" || index < 0;
			var max = one ? index + 1 : options.length;
			var values = one ? null : [];
			var i = index < 0 ? max : one ? index : 0;

			for (; i<max; i++)
			{
				var option = options[i];

				// Ignore disabled options
				if (option.disabled) {
					continue;
				}

				// Ignore options which are in disabled optgroups
				var parent = option.parentNode;
				if (parent.disabled && parent.tagName == "OPTGROUP") {
					continue;
				}

				var value = option.value;

				if (one) {
					return value;
				} else {
					values.push(value);
				}
			}

			return values;
		}
		else
		{
			return core.String.interpret(item.value || item.text);
		}
	},

	/**
	 * {String} Returns the serialized representation of the given form @item {Element}.
	 */
	serialize: function(item)
	{
		if (jasy.Env.isSet("debug"))
		{
			core.Assert.isEqual(arguments.length, 1);
			core.dom.Node.assertIsNode(item);
			core.Assert.isType(item.name, "String");
		}

		var name = encodeURIComponent(item.name);
		var value = this.getValue(item);

		// Support for select boxes with multiple values
		if (value instanceof Array)
		{
			var result = [];
			for (var i=0, l=value.length; i<l; i++) {
				result.push(name + "=" + encodeURIComponent(value[i]));
			}

			return result.join("&");
		}

		// Or everything else
		else
		{
			return name + "=" + encodeURIComponent(value);
		}
	}
});<|endoftext|>


<commit_before>var sys = require('sys'),
    http = require('http'),
    fs = require('fs'),
    url = require('url'),
    events = require('events');

var DEFAULT_PORT = 8000;

function main(argv) {
  new HttpServer({
    'GET': createServlet(StaticServlet),
    'HEAD': createServlet(StaticServlet)
  }).start(Number(argv[2]) || DEFAULT_PORT);
}

function escapeHtml(value) {
  return value.toString().
    replace('<', '<').
    replace('>', '&gt').
    replace('"', '"');
}

function createServlet(Class) {
  var servlet = new Class();
  return servlet.handleRequest.bind(servlet);
}

/**
 * An Http server implementation that uses a map of methods to decide
 * action routing.
 *
 * @param {Object} Map of method => Handler function
 */
function HttpServer(handlers) {
  this.handlers = handlers;
  this.server = http.createServer(this.handleRequest_.bind(this));
}

HttpServer.prototype.start = function(port) {
  this.port = port;
  this.server.listen(port);
  sys.puts('Http Server running at http://127.0.0.1:' + port + '/');
};

HttpServer.prototype.parseUrl_ = function(urlString) {
  var parsed = url.parse(urlString);
  parsed.pathname = url.resolve('/', parsed.pathname);
  return url.parse(url.format(parsed), true);
};

HttpServer.prototype.handleRequest_ = function(req, res) {
  var logEntry = req.method + ' ' + req.url;
  if (req.headers['user-agent']) {
    logEntry += ' ' + req.headers['user-agent'];
  }
  sys.puts(logEntry);
  req.url = this.parseUrl_(req.url);
  var handler = this.handlers[req.method];
  if (!handler) {
    res.writeHead(501);
    res.end();
  } else {
    handler.call(this, req, res);
  }
};

/**
 * Handles static content.
 */
function StaticServlet() {}

StaticServlet.MimeMap = {
  'txt': 'text/plain',
  'html': 'text/html',
  'css': 'text/css',
  'xml': 'application/xml',
  'json': 'application/json',
  'js': 'application/javascript',
  'jpg': 'image/jpeg',
  'jpeg': 'image/jpeg',
  'gif': 'image/gif',
  'png': 'image/png',
  'manifest': 'text/cache-manifest'
};

StaticServlet.prototype.handleRequest = function(req, res) {
  var self = this;
  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/, function(match, hex){
    return String.fromCharCode(parseInt(hex, 16));
  });
  var parts = path.split('/');
  if (parts[parts.length-1].charAt(0) === '.')
    return self.sendForbidden_(req, res, path);

  // docs rewriting
  var REWRITE = /\/(guide|api|cookbook|misc|tutorial)\/.*$/,
      IGNORED = /(\.(css|js|png|jpg)$|partials\/.*\.html$)/,
      match;

  if (!IGNORED.test(path) && (match = path.match(REWRITE))) {
      path = path.replace(match[0], '/index.html');
      sys.puts('Rewrite to ' + path);
  }
  // end of docs rewriting

  fs.stat(path, function(err, stat) {
    if (err)
      return self.sendMissing_(req, res, path);
    if (stat.isDirectory())
      return fs.stat(path + 'index.html', function(err, stat) {
        // send index.html if exists
        if (!err)
          return self.sendFile_(req, res, path + 'index.html');

        // list files otherwise
        return self.sendDirectory_(req, res, path);
      });

    return self.sendFile_(req, res, path);
  });
};

StaticServlet.prototype.sendError_ = function(req, res, error) {
  res.writeHead(500, {
      'Content-Type': 'text/html'
  });
  res.write('<!doctype html>\n');
  res.write('<title>Internal Server Error</title>\n');
  res.write('
Internal Server Error
');
  res.write('
' + escapeHtml(sys.inspect(error)) + '
');
  sys.puts('500 Internal Server Error');
  sys.puts(sys.inspect(error));
};

StaticServlet.prototype.sendMissing_ = function(req, res, path) {
  path = path.substring(1);
  res.writeHead(404, {
      'Content-Type': 'text/html'
  });
  res.write('<!doctype html>\n');
  res.write('<title>404 Not Found</title>\n');
  res.write('
Not Found
');
  res.write(
    '
The requested URL ' +
    escapeHtml(path) +
    ' was not found on this server.
'
  );
  res.end();
  sys.puts('404 Not Found: ' + path);
};

StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
  path = path.substring(1);
  res.writeHead(403, {
      'Content-Type': 'text/html'
  });
  res.write('<!doctype html>\n');
  res.write('<title>403 Forbidden</title>\n');
  res.write('
Forbidden
');
  res.write(
    '
You do not have permission to access ' +
    escapeHtml(path) + ' on this server.
'
  );
  res.end();
  sys.puts('403 Forbidden: ' + path);
};

StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
  res.writeHead(301, {
      'Content-Type': 'text/html',
      'Location': redirectUrl
  });
  res.write('<!doctype html>\n');
  res.write('<title>301 Moved Permanently</title>\n');
  res.write('
Moved Permanently
');
  res.write(
    '
The document has moved here.
'
  );
  res.end();
  sys.puts('401 Moved Permanently: ' + redirectUrl);
};

StaticServlet.prototype.sendFile_ = function(req, res, path) {
  var self = this;
  var file = fs.createReadStream(path);
  res.writeHead(200, {
    'Content-Type': StaticServlet.
      MimeMap[path.split('.').pop()] || 'text/plain'
  });
  if (req.method === 'HEAD') {
    res.end();
  } else {
    file.on('data', res.write.bind(res));
    file.on('close', function() {
      res.end();
    });
    file.on('error', function(error) {
      self.sendError_(req, res, error);
    });
  }
};

StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
  var self = this;
  if (path.match(/[^\/]$/)) {
    req.url.pathname += '/';
    var redirectUrl = url.format(url.parse(url.format(req.url)));
    return self.sendRedirect_(req, res, redirectUrl);
  }
  fs.readdir(path, function(err, files) {
    if (err)
      return self.sendError_(req, res, error);

    if (!files.length)
      return self.writeDirectoryIndex_(req, res, path, []);

    var remaining = files.length;
    files.forEach(function(fileName, index) {
      fs.stat(path + '/' + fileName, function(err, stat) {
        if (err)
          return self.sendError_(req, res, err);
        if (stat.isDirectory()) {
          files[index] = fileName + '/';
        }
        if (!(--remaining))
          return self.writeDirectoryIndex_(req, res, path, files);
      });
    });
  });
};

StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
  path = path.substring(1);
  res.writeHead(200, {
    'Content-Type': 'text/html'
  });
  if (req.method === 'HEAD') {
    res.end();
    return;
  }
  res.write('<!doctype html>\n');
  res.write('<title>' + escapeHtml(path) + '</title>\n');
  res.write('\n');
  res.write('
Directory: ' + escapeHtml(path) + '
');
  res.write('
');
  files.forEach(function(fileName) {
    if (fileName.charAt(0) !== '.') {
      res.write('
' +
        escapeHtml(fileName) + '
');
    }
  });
  res.write('
');
  res.end();
};

// Must be last,
main(process.argv);
<commit_msg>fix(nodeserver): docs rewriting<commit_after>var sys = require('sys'),
    http = require('http'),
    fs = require('fs'),
    url = require('url'),
    events = require('events');

var DEFAULT_PORT = 8000;

function main(argv) {
  new HttpServer({
    'GET': createServlet(StaticServlet),
    'HEAD': createServlet(StaticServlet)
  }).start(Number(argv[2]) || DEFAULT_PORT);
}

function escapeHtml(value) {
  return value.toString().
    replace('<', '<').
    replace('>', '&gt').
    replace('"', '"');
}

function createServlet(Class) {
  var servlet = new Class();
  return servlet.handleRequest.bind(servlet);
}

/**
 * An Http server implementation that uses a map of methods to decide
 * action routing.
 *
 * @param {Object} Map of method => Handler function
 */
function HttpServer(handlers) {
  this.handlers = handlers;
  this.server = http.createServer(this.handleRequest_.bind(this));
}

HttpServer.prototype.start = function(port) {
  this.port = port;
  this.server.listen(port);
  sys.puts('Http Server running at http://127.0.0.1:' + port + '/');
};

HttpServer.prototype.parseUrl_ = function(urlString) {
  var parsed = url.parse(urlString);
  parsed.pathname = url.resolve('/', parsed.pathname);
  return url.parse(url.format(parsed), true);
};

HttpServer.prototype.handleRequest_ = function(req, res) {
  var logEntry = req.method + ' ' + req.url;
  if (req.headers['user-agent']) {
    logEntry += ' ' + req.headers['user-agent'];
  }
  sys.puts(logEntry);
  req.url = this.parseUrl_(req.url);
  var handler = this.handlers[req.method];
  if (!handler) {
    res.writeHead(501);
    res.end();
  } else {
    handler.call(this, req, res);
  }
};

/**
 * Handles static content.
 */
function StaticServlet() {}

StaticServlet.MimeMap = {
  'txt': 'text/plain',
  'html': 'text/html',
  'css': 'text/css',
  'xml': 'application/xml',
  'json': 'application/json',
  'js': 'application/javascript',
  'jpg': 'image/jpeg',
  'jpeg': 'image/jpeg',
  'gif': 'image/gif',
  'png': 'image/png',
  'manifest': 'text/cache-manifest'
};

StaticServlet.prototype.handleRequest = function(req, res) {
  var self = this;
  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/, function(match, hex){
    return String.fromCharCode(parseInt(hex, 16));
  });
  var parts = path.split('/');
  if (parts[parts.length-1].charAt(0) === '.')
    return self.sendForbidden_(req, res, path);

  // docs rewriting
  var REWRITE = /\/(guide|api|cookbook|misc|tutorial).*$/,
      IGNORED = /(\.(css|js|png|jpg)$|partials\/.*\.html$)/,
      match;

  if (!IGNORED.test(path) && (match = path.match(REWRITE))) {
      path = path.replace(match[0], '/index.html');
      sys.puts('Rewrite to ' + path);
  }
  // end of docs rewriting

  fs.stat(path, function(err, stat) {
    if (err)
      return self.sendMissing_(req, res, path);
    if (stat.isDirectory())
      return fs.stat(path + 'index.html', function(err, stat) {
        // send index.html if exists
        if (!err)
          return self.sendFile_(req, res, path + 'index.html');

        // list files otherwise
        return self.sendDirectory_(req, res, path);
      });

    return self.sendFile_(req, res, path);
  });
};

StaticServlet.prototype.sendError_ = function(req, res, error) {
  res.writeHead(500, {
      'Content-Type': 'text/html'
  });
  res.write('<!doctype html>\n');
  res.write('<title>Internal Server Error</title>\n');
  res.write('
Internal Server Error
');
  res.write('
' + escapeHtml(sys.inspect(error)) + '
');
  sys.puts('500 Internal Server Error');
  sys.puts(sys.inspect(error));
};

StaticServlet.prototype.sendMissing_ = function(req, res, path) {
  path = path.substring(1);
  res.writeHead(404, {
      'Content-Type': 'text/html'
  });
  res.write('<!doctype html>\n');
  res.write('<title>404 Not Found</title>\n');
  res.write('
Not Found
');
  res.write(
    '
The requested URL ' +
    escapeHtml(path) +
    ' was not found on this server.
'
  );
  res.end();
  sys.puts('404 Not Found: ' + path);
};

StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
  path = path.substring(1);
  res.writeHead(403, {
      'Content-Type': 'text/html'
  });
  res.write('<!doctype html>\n');
  res.write('<title>403 Forbidden</title>\n');
  res.write('
Forbidden
');
  res.write(
    '
You do not have permission to access ' +
    escapeHtml(path) + ' on this server.
'
  );
  res.end();
  sys.puts('403 Forbidden: ' + path);
};

StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
  res.writeHead(301, {
      'Content-Type': 'text/html',
      'Location': redirectUrl
  });
  res.write('<!doctype html>\n');
  res.write('<title>301 Moved Permanently</title>\n');
  res.write('
Moved Permanently
');
  res.write(
    '
The document has moved here.
'
  );
  res.end();
  sys.puts('401 Moved Permanently: ' + redirectUrl);
};

StaticServlet.prototype.sendFile_ = function(req, res, path) {
  var self = this;
  var file = fs.createReadStream(path);
  res.writeHead(200, {
    'Content-Type': StaticServlet.
      MimeMap[path.split('.').pop()] || 'text/plain'
  });
  if (req.method === 'HEAD') {
    res.end();
  } else {
    file.on('data', res.write.bind(res));
    file.on('close', function() {
      res.end();
    });
    file.on('error', function(error) {
      self.sendError_(req, res, error);
    });
  }
};

StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
  var self = this;
  if (path.match(/[^\/]$/)) {
    req.url.pathname += '/';
    var redirectUrl = url.format(url.parse(url.format(req.url)));
    return self.sendRedirect_(req, res, redirectUrl);
  }
  fs.readdir(path, function(err, files) {
    if (err)
      return self.sendError_(req, res, error);

    if (!files.length)
      return self.writeDirectoryIndex_(req, res, path, []);

    var remaining = files.length;
    files.forEach(function(fileName, index) {
      fs.stat(path + '/' + fileName, function(err, stat) {
        if (err)
          return self.sendError_(req, res, err);
        if (stat.isDirectory()) {
          files[index] = fileName + '/';
        }
        if (!(--remaining))
          return self.writeDirectoryIndex_(req, res, path, files);
      });
    });
  });
};

StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
  path = path.substring(1);
  res.writeHead(200, {
    'Content-Type': 'text/html'
  });
  if (req.method === 'HEAD') {
    res.end();
    return;
  }
  res.write('<!doctype html>\n');
  res.write('<title>' + escapeHtml(path) + '</title>\n');
  res.write('\n');
  res.write('
Directory: ' + escapeHtml(path) + '
');
  res.write('
');
  files.forEach(function(fileName) {
    if (fileName.charAt(0) !== '.') {
      res.write('
' +
        escapeHtml(fileName) + '
');
    }
  });
  res.write('
');
  res.end();
};

// Must be last,
main(process.argv);
<|endoftext|>


<commit_before>describe 'Circuit'
    describe 'Resistor'

        before_each
            resistor4 = new sparks.circuit.Resistor4band
            resistor5 = new sparks.circuit.Resistor5band
        end

        it 'should produce correct color bands for 4-band given a resistance/tolerance value'
            colors = resistor4.getColors(1, 0.1)
            colors[0].should.be 'brown'
            colors[1].should.be 'black'
            colors[2].should.be 'gold'
            colors[3].should.be 'silver'

            colors = resistor4.getColors(16, 0.05) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'blue'
            colors[2].should.be 'black'
            colors[3].should.be 'gold'

            colors = resistor4.getColors(680e3, 0.1) //don't remove. failed before
            colors[0].should.be 'blue'
            colors[1].should.be 'grey'
            colors[2].should.be 'yellow'
            colors[3].should.be 'silver'

            colors = resistor4.getColors(10e6, 0.05) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'black'
            colors[2].should.be 'blue'
            colors[3].should.be 'gold'

        end

        it 'should produce correct color bands for 5-band given a resistance/tolerance value'
            colors = resistor5.getColors(16.2, 0.01) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'blue'
            colors[2].should.be 'red'
            colors[3].should.be 'gold'
            colors[4].should.be 'brown'

            colors = resistor5.getColors(12.1, 0.02) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'red'
            colors[2].should.be 'brown'
            colors[3].should.be 'gold'
            colors[4].should.be 'red'

            colors = resistor5.getColors(14.0, 0.01) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'yellow'
            colors[2].should.be 'black'
            colors[3].should.be 'gold'
            colors[4].should.be 'brown'

            colors = resistor5.getColors(1, 0.01)
            colors[0].should.be 'brown'
            colors[1].should.be 'black'
            colors[2].should.be 'black'
            colors[3].should.be 'silver'
            colors[4].should.be 'brown'

            colors = resistor5.getColors(487e3, 0.02)
            colors[0].should.be 'yellow'
            colors[1].should.be 'grey'
            colors[2].should.be 'violet'
            colors[3].should.be 'orange'
            colors[4].should.be 'red'

            colors = resistor5.getColors(100e6, 0.02)
            colors[0].should.be 'brown'
            colors[1].should.be 'black'
            colors[2].should.be 'black'
            colors[3].should.be 'blue'
            colors[4].should.be 'red'
        end
    end

    describe 'Multimeter'
        before
            multimeter = new sparks.circuit.Multimeter
        end

        it 'should display the number correctly'
            // All connected
            multimeter.redProbeConnection = 'something'
            multimeter.blackProbeConnection = 'something_else'
            multimeter.redPlugConnection = 'voma_port'
            multimeter.blackPlugConnection = 'common_port'
            multimeter.powerOn = true
            multimeter.dialPosition = 'r_2000'

            multimeter.value = 100
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '  1 0 0'

            multimeter.value = 1024
            multimeter.dialPosition = 'r_200'
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be ' 1   . '

            multimeter.dialPosition = 'r_2000'
            multimeter.updateDisplay()

            multimeter.dialPosition = 'r_20k'
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '  1.0 2'

            multimeter.dialPosition = 'r_200k'
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '  0 1.0'

            multimeter.dialPosition = 'r_2000k'
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '  0 0 1'

            // power off
            multimeter.powerOn = false
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '       '

        end
    end
end
<commit_msg>Fixed failing tests.<commit_after>describe 'Circuit'
    describe 'Resistor'

        before_each
            resistor4 = new sparks.circuit.Resistor4band
            resistor5 = new sparks.circuit.Resistor5band
        end

        it 'should produce correct color bands for 4-band given a resistance/tolerance value'
            colors = resistor4.getColors(1, 0.1)
            colors[0].should.be 'brown'
            colors[1].should.be 'black'
            colors[2].should.be 'gold'
            colors[3].should.be 'silver'

            colors = resistor4.getColors(16, 0.05) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'blue'
            colors[2].should.be 'black'
            colors[3].should.be 'gold'

            colors = resistor4.getColors(680e3, 0.1) //don't remove. failed before
            colors[0].should.be 'blue'
            colors[1].should.be 'grey'
            colors[2].should.be 'yellow'
            colors[3].should.be 'silver'

            colors = resistor4.getColors(10e6, 0.05) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'black'
            colors[2].should.be 'blue'
            colors[3].should.be 'gold'

        end

        it 'should produce correct color bands for 5-band given a resistance/tolerance value'
            colors = resistor5.getColors(16.2, 0.01) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'blue'
            colors[2].should.be 'red'
            colors[3].should.be 'gold'
            colors[4].should.be 'brown'

            colors = resistor5.getColors(12.1, 0.02) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'red'
            colors[2].should.be 'brown'
            colors[3].should.be 'gold'
            colors[4].should.be 'red'

            colors = resistor5.getColors(14.0, 0.01) //don't remove. failed before
            colors[0].should.be 'brown'
            colors[1].should.be 'yellow'
            colors[2].should.be 'black'
            colors[3].should.be 'gold'
            colors[4].should.be 'brown'

            colors = resistor5.getColors(1, 0.01)
            colors[0].should.be 'brown'
            colors[1].should.be 'black'
            colors[2].should.be 'black'
            colors[3].should.be 'silver'
            colors[4].should.be 'brown'

            colors = resistor5.getColors(487e3, 0.02)
            colors[0].should.be 'yellow'
            colors[1].should.be 'grey'
            colors[2].should.be 'violet'
            colors[3].should.be 'orange'
            colors[4].should.be 'red'

            colors = resistor5.getColors(100e6, 0.02)
            colors[0].should.be 'brown'
            colors[1].should.be 'black'
            colors[2].should.be 'black'
            colors[3].should.be 'blue'
            colors[4].should.be 'red'
        end
    end

    describe 'Multimeter'
        before
            multimeter = new sparks.circuit.Multimeter
        end

        it 'should display the number correctly'
            // All connected
            multimeter.redProbeConnection = 'something'
            multimeter.blackProbeConnection = 'something_else'
            multimeter.redPlugConnection = 'voma_port'
            multimeter.blackPlugConnection = 'common_port'
            multimeter.powerOn = true
            multimeter.dialPosition = 'r_2000'

            multimeter.r_value = 100
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '  1 0 0'

            multimeter.r_value = 1024
            multimeter.dialPosition = 'r_200'
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be ' 1   . '

            multimeter.dialPosition = 'r_2000'
            multimeter.updateDisplay()

            multimeter.dialPosition = 'r_20k'
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '  1.0 2'

            multimeter.dialPosition = 'r_200k'
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '  0 1.0'

            multimeter.dialPosition = 'r_2000k'
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '  0 0 1'

            // power off
            multimeter.powerOn = false
            multimeter.updateDisplay()
            multimeter.getDisplayText().should.be '       '

        end
    end
end
<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    jade = require('jade');

var Index = function (siteData, config) {

  var readFile = function (path, callback) {
    fs.readFile(path, 'utf-8', function(err, data) {
      if (err) { throw err; }
      compileJade(data, callback);
    });
  };

  var compileJade = function (data, callback) {
    var fn = jade.compile(data, {
      filename: path.resolve(config.pages.index.template)
    }),
      out = fn({
        posts: siteData.posts,
        title: config.pages.index.title + " | " + config.pages.site_name
      });
    writeFile(path.resolve(config.build_dir), out, callback);
  };

  var writeFile = function (destination, out, callback) {
    fs.writeFile(path.resolve(destination + '/index.html'), out, function (err, data) {
      if (err) { throw err; }
      return callback(err, true);
    });
  };

  this.init = function(callback) {
    readFile(path.resolve(config.pages.index.template), callback);
  };

};

module.exports = Index;

<commit_msg>read sitename from config correctly<commit_after>var fs = require('fs'),
    path = require('path'),
    jade = require('jade');

var Index = function (siteData, config) {

  var readFile = function (path, callback) {
    fs.readFile(path, 'utf-8', function(err, data) {
      if (err) { throw err; }
      compileJade(data, callback);
    });
  };

  var compileJade = function (data, callback) {
    var fn = jade.compile(data, {
      filename: path.resolve(config.pages.index.template)
    }),
      out = fn({
        posts: siteData.posts,
        title: config.pages.index.title + " | " + config.site_name
      });
    writeFile(path.resolve(config.build_dir), out, callback);
  };

  var writeFile = function (destination, out, callback) {
    fs.writeFile(path.resolve(destination + '/index.html'), out, function (err, data) {
      if (err) { throw err; }
      return callback(err, true);
    });
  };

  this.init = function(callback) {
    readFile(path.resolve(config.pages.index.template), callback);
  };

};

module.exports = Index;

<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird');

module.exports = function (context) {

  return Promise.resolve().then(() => {
    const pug = require('pug');

    let tpl = pug.compileClient(context.asset.source, {
      // debug decrease speed and disable external cache
      // (injects unique paths every time, because of random tml dir)
      compileDebug: false,
      // NO `with` -> better speed
      self: true,
      // Set HTML5 mode, for terse attributes (boolean + without params)
      doctype: 'html',
      // Use helpers from outer module
      inlineRuntimeFunctions: false,
      // For error reporting
      filename: context.asset.logicalPath
    }).toString();

    context.asset.source = tpl;
  });
};
<commit_msg>pug: support npm package paths in template `include`<commit_after>'use strict';

const Promise = require('bluebird');
const resolve = require('resolve');
const path    = require('path');

function npmResolverPlugin() {
  return {
    resolve(filename, source /*, options */) {
      return resolve.sync(filename, { basedir: path.dirname(source) });
    }
  };
}

module.exports = function (context) {

  return Promise.resolve().then(() => {
    const pug = require('pug');

    let tpl = pug.compileClient(context.asset.source, {
      compileDebug:           false,
      doctype:                'html',
      filename:               context.asset.logicalPath,
      inlineRuntimeFunctions: false,
      plugins:                [ npmResolverPlugin() ],
      self:                   true
    }).toString();

    context.asset.source = tpl;
  });
};
<|endoftext|>


<commit_before>"use strict";

var spawn = require("child_process").spawn;
var util = require("util");
var Transform = require("stream").Transform || require("readable-stream").Transform;

// Transforming stream that replaces SMTP-style \r\n line endings to
// Sendmail-style \n line endings.
function NewlineTransform(options){
    Transform.call(this, options);
}
util.inherits(NewlineTransform, Transform);

NewlineTransform.prototype._transform = function(chunk, encoding, done){
    this.push(chunk.toString().replace(/\r\n/g, "\n"));
    done();
};

// Expose to the world
module.exports = SendmailTransport;

/**
 *
Generates a Transport object for Sendmail

 *
 * @constructor
 * @param {String} [config] path to the sendmail command
 */
function SendmailTransport(config){
    this.path = "sendmail";
    this.args = false;

    if(typeof config=="string"){
        this.path = config;
    }else if(typeof config=="object"){
        if(config.path){
            this.path = config.path;
        }
        if(Array.isArray(config.args)){
            this.args = config.args;
        }
    }
}

/**
 *
Spawns a sendmail command either using sendmail -i -f from_addr to_addr[]
 * (by default) or sendmail -i list_of_args[] (if args property was given)
 * and pipes message to sendmail stdin. Return callback checks if the sendmail process
 * ended with 0 (no error) or not.

 *
 * @param {Object} emailMessage MailComposer object
 * @param {Function} callback Callback function to run when the sending is completed
 */
SendmailTransport.prototype.sendMail = function sendMail(emailMessage, callback){

    var envelope = emailMessage.getEnvelope(),
        args = this.args || ["-f"].concat(envelope.from).concat(envelope.to),
        sendmail,
        cbCounter = 2,
        didCb,
        marker = "SendmailTransport.sendMail",
        transform;

    args.unshift("-i"); // force -i to keep single dots

    try {
        sendmail = spawn(this.path, args);
    } catch (e){
        e[marker] = "spawn exception";
        sendmailResult(e);
    }

    if(sendmail){
        sendmail.on("error", sendmailError);
        sendmail.once("exit", sendmailExit);
        sendmail.once("close", endEvent);
        sendmail.stdin.on("error", sendmailStdinError);

        transform = new NewlineTransform();
        emailMessage.pipe(transform).pipe(sendmail.stdin);
        emailMessage.streamMessage();
    }

    function sendmailError(e){
        e[marker] = "sendmailError";
        sendmailResult(e);
    }

    function sendmailStdinError(e){
        e[marker] = "sendmailStdinError";
        sendmailResult(e);
    }

    function sendmailExit(code){
        if(!code){
            endEvent();
        }else{
            sendmailResult(new Error("Sendmail exited with " + code));
        }
    }

    function endEvent(){
        if(!--cbCounter){
            sendmailResult();
        }
    }

    function sendmailResult(e){
        if(didCb){
            // ignore any additional responses
            return;
        }
        didCb = true;
        if(typeof callback === "function"){
            if(e){
                callback(e);
            }else{
                callback(null, {
                    messageId: emailMessage._messageId
                });
            }
        }
    }
};
<commit_msg>bugfix (adding "-i" to sendmail command line for each new mail)  by copying this.args instead of just making a reference<commit_after>"use strict";

var spawn = require("child_process").spawn;
var util = require("util");
var Transform = require("stream").Transform || require("readable-stream").Transform;

// Transforming stream that replaces SMTP-style \r\n line endings to
// Sendmail-style \n line endings.
function NewlineTransform(options){
    Transform.call(this, options);
}
util.inherits(NewlineTransform, Transform);

NewlineTransform.prototype._transform = function(chunk, encoding, done){
    this.push(chunk.toString().replace(/\r\n/g, "\n"));
    done();
};

// Expose to the world
module.exports = SendmailTransport;

/**
 *
Generates a Transport object for Sendmail

 *
 * @constructor
 * @param {String} [config] path to the sendmail command
 */
function SendmailTransport(config){
    this.path = "sendmail";
    this.args = false;

    if(typeof config=="string"){
        this.path = config;
    }else if(typeof config=="object"){
        if(config.path){
            this.path = config.path;
        }
        if(Array.isArray(config.args)){
            this.args = config.args;
        }
    }
}

/**
 *
Spawns a sendmail command either using sendmail -i -f from_addr to_addr[]
 * (by default) or sendmail -i list_of_args[] (if args property was given)
 * and pipes message to sendmail stdin. Return callback checks if the sendmail process
 * ended with 0 (no error) or not.

 *
 * @param {Object} emailMessage MailComposer object
 * @param {Function} callback Callback function to run when the sending is completed
 */
SendmailTransport.prototype.sendMail = function sendMail(emailMessage, callback){

    var envelope = emailMessage.getEnvelope(),
        args = this.args ? this.args.slice() : ["-f"].concat(envelope.from).concat(envelope.to),
        sendmail,
        cbCounter = 2,
        didCb,
        marker = "SendmailTransport.sendMail",
        transform;

    args.unshift("-i"); // force -i to keep single dots

    try {
        sendmail = spawn(this.path, args);
    } catch (e){
        e[marker] = "spawn exception";
        sendmailResult(e);
    }

    if(sendmail){
        sendmail.on("error", sendmailError);
        sendmail.once("exit", sendmailExit);
        sendmail.once("close", endEvent);
        sendmail.stdin.on("error", sendmailStdinError);

        transform = new NewlineTransform();
        emailMessage.pipe(transform).pipe(sendmail.stdin);
        emailMessage.streamMessage();
    }

    function sendmailError(e){
        e[marker] = "sendmailError";
        sendmailResult(e);
    }

    function sendmailStdinError(e){
        e[marker] = "sendmailStdinError";
        sendmailResult(e);
    }

    function sendmailExit(code){
        if(!code){
            endEvent();
        }else{
            sendmailResult(new Error("Sendmail exited with " + code));
        }
    }

    function endEvent(){
        if(!--cbCounter){
            sendmailResult();
        }
    }

    function sendmailResult(e){
        if(didCb){
            // ignore any additional responses
            return;
        }
        didCb = true;
        if(typeof callback === "function"){
            if(e){
                callback(e);
            }else{
                callback(null, {
                    messageId: emailMessage._messageId
                });
            }
        }
    }
};
<|endoftext|>


<commit_before>var debug = require("debug")("p3api-server:media/dna+fasta");
var when = require("promised-io/promise").when;
var es = require("event-stream");
var wrap = require("../util/linewrap");

function serializeRow(type, o){
	if(type == "genome_feature"){
		var fasta_id, row;
		if(o.annotation == "PATRIC"){
			fasta_id = o.patric_id + "|" + (o.refseq_locus_tag ? (o.refseq_locus_tag + "|") : "") + (o.alt_locus_tag ? (o.alt_locus_tag + "|") : "");
		}else if(o.annotation == "RefSeq"){
			fasta_id = "gi|" + o.gi + "|" + (o.refseq_locus_tag ? (o.refseq_locus_tag + "|") : "") + (o.alt_locus_tag ? (o.alt_locus_tag + "|") : "");
		}else{
			throw Error("Unknown Annotation Type: " + o.annotation);
		}

		row = ">" + fasta_id + "   " + o.product + "   [" + o.genome_name + " | " + o.genome_id + "]\n";
		row = row + wrap(o.na_sequence, 60) + "\n";
		return row;

	}else if(type == "genome_sequence"){
		row = ">accn|" + o.accession + "   " + o.description + "   " + "[" + (o.genome_name || "") + " | " + (o.genome_id || "") + "]\n";
		row = row + wrap(o.sequence, 60) + "\n";
		return row;
	}else{
		throw Error("Cannot serialize " + type + " to application/dna+fasta");
	}

}

module.exports = {
	contentType: "application/dna+fasta",
	serialize: function(req, res, next){
		debug("application/dna+fastahandler");

		if(req.isDownload){
			// res.set("content-disposition", "attachment; filename=patric_genomes.fasta");
			res.attachment('PATRIC_' + req.call_collection + '.fasta');
		}

		if(req.call_method == "stream"){
			when(res.results, function(results){
				debug("res.results: ", results);
				var docCount = 0;
				var head;

				if(!results.stream){
					throw Error("Expected ReadStream in Serializer")
				}

				results.stream.pipe(es.mapSync(function(data){
					debug("STREAM DATA: ", data);
					if(!head){
						head = data;
					}else{
						// debug(JSON.stringify(data));
						res.write(serializeRow(req.call_collection, data));
						docCount++;
					}
				})).on('end', function(){
					debug("Exported " + docCount + " Documents");
					res.end();
				})
			});
		}else{
			if(res.results && res.results.response && res.results.response.docs){
				res.results.response.docs.forEach(function(o){
					res.write(serializeRow(req.call_collection, o));
				});
			}
			res.end();
		}
	}
};
<commit_msg>mute too much details<commit_after>var debug = require("debug")("p3api-server:media/dna+fasta");
var when = require("promised-io/promise").when;
var es = require("event-stream");
var wrap = require("../util/linewrap");

function serializeRow(type, o){
	if(type == "genome_feature"){
		var fasta_id, row;
		if(o.annotation == "PATRIC"){
			fasta_id = o.patric_id + "|" + (o.refseq_locus_tag ? (o.refseq_locus_tag + "|") : "") + (o.alt_locus_tag ? (o.alt_locus_tag + "|") : "");
		}else if(o.annotation == "RefSeq"){
			fasta_id = "gi|" + o.gi + "|" + (o.refseq_locus_tag ? (o.refseq_locus_tag + "|") : "") + (o.alt_locus_tag ? (o.alt_locus_tag + "|") : "");
		}else{
			throw Error("Unknown Annotation Type: " + o.annotation);
		}

		row = ">" + fasta_id + "   " + o.product + "   [" + o.genome_name + " | " + o.genome_id + "]\n";
		row = row + wrap(o.na_sequence, 60) + "\n";
		return row;

	}else if(type == "genome_sequence"){
		row = ">accn|" + o.accession + "   " + o.description + "   " + "[" + (o.genome_name || "") + " | " + (o.genome_id || "") + "]\n";
		row = row + wrap(o.sequence, 60) + "\n";
		return row;
	}else{
		throw Error("Cannot serialize " + type + " to application/dna+fasta");
	}

}

module.exports = {
	contentType: "application/dna+fasta",
	serialize: function(req, res, next){
		debug("application/dna+fastahandler");

		if(req.isDownload){
			// res.set("content-disposition", "attachment; filename=patric_genomes.fasta");
			res.attachment('PATRIC_' + req.call_collection + '.fasta');
		}

		if(req.call_method == "stream"){
			when(res.results, function(results){
				// debug("res.results: ", results);
				var docCount = 0;
				var head;

				if(!results.stream){
					throw Error("Expected ReadStream in Serializer")
				}

				results.stream.pipe(es.mapSync(function(data){
					// debug("STREAM DATA: ", data);
					if(!head){
						head = data;
					}else{
						// debug(JSON.stringify(data));
						res.write(serializeRow(req.call_collection, data));
						docCount++;
					}
				})).on('end', function(){
					debug("Exported " + docCount + " Documents");
					res.end();
				})
			});
		}else{
			if(res.results && res.results.response && res.results.response.docs){
				res.results.response.docs.forEach(function(o){
					res.write(serializeRow(req.call_collection, o));
				});
			}
			res.end();
		}
	}
};
<|endoftext|>


<commit_before>/**
  Copyright 2018 LNFWebsite
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
**/

// * This function highlights playlist elements

function highlight(i, which, persist) {
  $("tr:nth-child(" + i + ")").attr("id", "new-" + which);
  if (!persist) {
    $("tr." + which).removeClass(which);
  }
  $("#new-" + which).addClass(which);
  $("#new-" + which).removeAttr("id");
}

// * This function adds video elements to the playlist

function addVideoToList(name, time, spot, smooth) {
  name = decodeURIComponent(name);

  if (smooth) {
    smooth = " class=\"animated flipInX\"";
  }
  else {
    smooth = "";
  }

  var trElement = "
" + name + "
<button class=\"tableButton removeButton\" onclick=\"buttonRemoveVideo(this);\" title=\"Remove\"></button>" +
  "<button class=\"tableButton playButton\" onclick=\"buttonPlayVideo(this);\" title=\"Play\"></button>
	" + time + "
";
  if ($("#videosTable > tr").length > 0) {
    if (spot > 1) {
      $("#videosTable > tr").eq(spot-2).after(trElement);
    }
    else {
      $(trElement).insertBefore("#videosTable > tr:first");
    }
  }
  else {
    $("#videosTable").append(trElement);
  }
}

// * This function removes video elements from the playlist

function removeVideoFromList(index, smooth) {
  if (smooth === true) {
    $("tr:nth-child(" + index + ")").fadeOut(function() {
      $(this).remove();
    });
  }
  else {
    $("tr:nth-child(" + index + ")").remove();
  }
}

// * This function restores the video list highlighting as applicable
// * It does not use stored values, but rather the state of the playlist

function restoreHighlight(which) {
  if (which === videoIteration) {
    highlight(which, "selected", false);
  }
  if (videos[which][2] === baseAutoplayVideoId) {
    highlight(which, "radio", false);
  }
  if (videoErrorIds.indexOf(videos[which][2]) > -1) {
    highlight(which, "videoError", true);
  }
}

// * This function refreshes the playlist viewer with videos in the videos array
// * It's primary use is for playlist shuffling

function refreshVideoList() {
  for (var i = 1; i < videos.length; i++) {
    removeVideoFromList(i, false);
    var printTime = msConversion(videos[i][1] * 1000);
    addVideoToList(videos[i][0], printTime, i, false);
    restoreHighlight(i);
  }
}

// * These functions are called when the play/remove video buttons in the playlist viewer are clicked

function buttonPlayVideo(element) {
  var index = $(".playButton").index(element);
  actionPlayVideo(index);
}
function buttonRemoveVideo(element) {
  var index = $(".removeButton").index(element) + 1;
  actionRemoveVideo(index);
}

// * This function makes the entire playlist viewer sortable by dragging&dropping
// * It calls the actionMoveVideo function above

function makeSortable() {
  $( "#videosTable" ).sortable({
    update: function(event, ui) {
      actionMoveVideo(oldIndex + 1, ui.item.index() + 1);
      setPlaylist();
      videoPreviews();
    },
    start: function(event, ui) {
      oldIndex = ui.item.index();
    }
  });
}

// * This object is for the settings available in the playlist manipulation footer
// * Those buttons call their corresponding functionality here

var PlaylistFeatures = function() {
  this.playNext = function() {
    sendStation("playlistfeaturesplaynext");
    playlistPlayNext = (playlistPlayNext ? false : true);
    $(".fa-arrow-circle-right").css("color", (playlistPlayNext ? "#F77F00" : "grey"));
  }
  this.repeat = function() {
    sendStation("playlistfeaturesrepeat");
    playlistRepeat = (playlistRepeat ? false : true);
    videoPreviews();
    $(".fa-redo-alt").css("color", (playlistRepeat ? "#F77F00" : "grey"));
  }
  this.shuffle = function() {
    sendStation("playlistfeaturesshuffle");
    playlistShuffle = (playlistShuffle ? false : true);
    shufflePlaylist();
    $(".fa-random").css("color", (playlistShuffle ? "#F77F00" : "grey"));
  }
  this.autoplay = function() {
    playlistAutoplay = (playlistAutoplay ? false : true);
    if (playlistAutoplay === false) {
      autoplayVideos = [];
      autoplayVideoIteration = 0;
      baseAutoplayVideoId = null;
      $("tr").removeClass("radio");
    }
    else {
      addAutoplayVideo();
      videoPreviews();
    }
    $(".fa-rss").css("color", (playlistAutoplay ? "#F77F00" : "grey"));
  }
}
var playlistFeatures = new PlaylistFeatures;

// * This function loads the previous and next video button's data in the playlist manipulation footer
// * It is called whenever anything changes in the playlist or the currently playing video changes

function videoPreviews() {
  function addData(which, iteration) {
    $("#" + which + "Video .videoName").text(decodeURIComponent(videos[iteration][0]));
    $("#" + which + "Video .videoTime").text(msConversion(videos[iteration][1] * 1000));
    $("#" + which + "Video .videoImage").attr("src", "https://i.ytimg.com/vi/" + videos[iteration][2] + "/default.jpg");
  }
  function changeOpacity(which, amount) {
    $("#" + which + "Video .videoName, #" + which + "Video .videoImage, #" + which + "Video .videoTime").css("opacity", amount);
  }
  function greyOut(which, color) {
    $("#" + which + "Video").css("background-color", color);
  }

  if (changeIteration(1) <= videoCounter) {
    changeOpacity("next", "1");
    greyOut("next", "white");
    addData("next", changeIteration(1));
  }
  else {
    changeOpacity("next", "0");
    greyOut("next", "grey");
  }

  if (changeIteration(-1) > 0 || (playlistRepeat && videoIteration == 1)) {
    changeOpacity("previous", "1");
    greyOut("previous", "white");
    addData("previous", (playlistRepeat && videoIteration == 1 ? changeIteration(-2) + 1 : changeIteration(-1)));
  }
  else {
    changeOpacity("previous", "0");
    greyOut("previous", "grey");
  }
}
<commit_msg>zero out here<commit_after>/**
  Copyright 2018 LNFWebsite
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
**/

// * This function highlights playlist elements

function highlight(i, which, persist) {
  $("tr:nth-child(" + i + ")").attr("id", "new-" + which);
  if (!persist) {
    $("tr." + which).removeClass(which);
  }
  $("#new-" + which).addClass(which);
  $("#new-" + which).removeAttr("id");
}

// * This function adds video elements to the playlist

function addVideoToList(name, time, spot, smooth) {
  name = decodeURIComponent(name);

  if (smooth) {
    smooth = " class=\"animated flipInX\"";
  }
  else {
    smooth = "";
  }

  var trElement = "
" + name + "
<button class=\"tableButton removeButton\" onclick=\"buttonRemoveVideo(this);\" title=\"Remove\"></button>" +
  "<button class=\"tableButton playButton\" onclick=\"buttonPlayVideo(this);\" title=\"Play\"></button>
	" + time + "
";
  if ($("#videosTable > tr").length > 0) {
    if (spot > 1) {
      $("#videosTable > tr").eq(spot-2).after(trElement);
    }
    else {
      $(trElement).insertBefore("#videosTable > tr:first");
    }
  }
  else {
    $("#videosTable").append(trElement);
  }
}

// * This function removes video elements from the playlist

function removeVideoFromList(index, smooth) {
  if (smooth === true) {
    $("tr:nth-child(" + index + ")").fadeOut(function() {
      $(this).remove();
    });
  }
  else {
    $("tr:nth-child(" + index + ")").remove();
  }
}

// * This function restores the video list highlighting as applicable
// * It does not use stored values, but rather the state of the playlist

function restoreHighlight(which) {
  if (which === videoIteration) {
    highlight(which, "selected", false);
  }
  if (videos[which][2] === baseAutoplayVideoId) {
    highlight(which, "radio", false);
  }
  if (videoErrorIds.indexOf(videos[which][2]) > -1) {
    highlight(which, "videoError", true);
  }
}

// * This function refreshes the playlist viewer with videos in the videos array
// * It's primary use is for playlist shuffling

function refreshVideoList() {
  for (var i = 1; i < videos.length; i++) {
    removeVideoFromList(i, false);
    var printTime = msConversion(videos[i][1] * 1000);
    addVideoToList(videos[i][0], printTime, i, false);
    restoreHighlight(i);
  }
}

// * These functions are called when the play/remove video buttons in the playlist viewer are clicked

function buttonPlayVideo(element) {
  var index = $(".playButton").index(element);
  actionPlayVideo(index);
}
function buttonRemoveVideo(element) {
  var index = $(".removeButton").index(element) + 1;
  actionRemoveVideo(index);
}

// * This function makes the entire playlist viewer sortable by dragging&dropping
// * It calls the actionMoveVideo function above

function makeSortable() {
  $( "#videosTable" ).sortable({
    update: function(event, ui) {
      actionMoveVideo(oldIndex + 1, ui.item.index() + 1);
      setPlaylist();
      videoPreviews();
    },
    start: function(event, ui) {
      oldIndex = ui.item.index();
    }
  });
}

// * This object is for the settings available in the playlist manipulation footer
// * Those buttons call their corresponding functionality here

var PlaylistFeatures = function() {
  this.playNext = function() {
    sendStation("playlistfeaturesplaynext");
    playlistPlayNext = (playlistPlayNext ? false : true);
    $(".fa-arrow-circle-right").css("color", (playlistPlayNext ? "#F77F00" : "grey"));
  }
  this.repeat = function() {
    sendStation("playlistfeaturesrepeat");
    playlistRepeat = (playlistRepeat ? false : true);
    videoPreviews();
    $(".fa-redo-alt").css("color", (playlistRepeat ? "#F77F00" : "grey"));
  }
  this.shuffle = function() {
    sendStation("playlistfeaturesshuffle");
    playlistShuffle = (playlistShuffle ? false : true);
    shufflePlaylist();
    $(".fa-random").css("color", (playlistShuffle ? "#F77F00" : "grey"));
  }
  this.autoplay = function() {
    playlistAutoplay = (playlistAutoplay ? false : true);
    if (playlistAutoplay === false) {
      autoplayVideos = [];
      autoplayVideoIteration = 0;
      baseAutoplayVideoId = false;
      autoplayList = false;
      $("tr").removeClass("radio");
    }
    else {
      addAutoplayVideo();
      videoPreviews();
    }
    $(".fa-rss").css("color", (playlistAutoplay ? "#F77F00" : "grey"));
  }
}
var playlistFeatures = new PlaylistFeatures;

// * This function loads the previous and next video button's data in the playlist manipulation footer
// * It is called whenever anything changes in the playlist or the currently playing video changes

function videoPreviews() {
  function addData(which, iteration) {
    $("#" + which + "Video .videoName").text(decodeURIComponent(videos[iteration][0]));
    $("#" + which + "Video .videoTime").text(msConversion(videos[iteration][1] * 1000));
    $("#" + which + "Video .videoImage").attr("src", "https://i.ytimg.com/vi/" + videos[iteration][2] + "/default.jpg");
  }
  function changeOpacity(which, amount) {
    $("#" + which + "Video .videoName, #" + which + "Video .videoImage, #" + which + "Video .videoTime").css("opacity", amount);
  }
  function greyOut(which, color) {
    $("#" + which + "Video").css("background-color", color);
  }

  if (changeIteration(1) <= videoCounter) {
    changeOpacity("next", "1");
    greyOut("next", "white");
    addData("next", changeIteration(1));
  }
  else {
    changeOpacity("next", "0");
    greyOut("next", "grey");
  }

  if (changeIteration(-1) > 0 || (playlistRepeat && videoIteration == 1)) {
    changeOpacity("previous", "1");
    greyOut("previous", "white");
    addData("previous", (playlistRepeat && videoIteration == 1 ? changeIteration(-2) + 1 : changeIteration(-1)));
  }
  else {
    changeOpacity("previous", "0");
    greyOut("previous", "grey");
  }
}
<|endoftext|>